All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sougata Santra <sougata@tuxera.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: <hch@infradead.org>, <linux-fsdevel@vger.kernel.org>,
	Vyacheslav Dubeyko <slava@dubeyko.com>,
	Sougata Santra <sougata@tuxera.com>,
	Fabian Frederick <fabf@skynet.be>
Subject: [PATCH 1/1] hfsplus: skip unnecessary volume header sync
Date: Thu, 17 Jul 2014 19:32:42 +0300	[thread overview]
Message-ID: <1405614762.25052.8.camel@ultrabook> (raw)


hfsplus_sync_fs always updates volume header information to disk with every
sync. This causes problem for systems trying to monitor disk activity to
switch them to low power state. Also hfsplus_sync_fs is explicitly called
from mount/unmount, which is unnecessary. During mount/unmount we only want
to set/clear volume dirty sate.

Signed-off-by: Sougata Santra <sougata@tuxera.com>
---
 fs/hfsplus/super.c | 101 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 79 insertions(+), 22 deletions(-)

diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 4cf2024..5cacb06 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -170,12 +170,61 @@ static void hfsplus_evict_inode(struct inode *inode)
 	}
 }
 
+/*
+ * Helper to sync volume header state to disk. Caller must acquire
+ * volume header mutex (vh_mutex).
+ */
+static int hfsplus_sync_volume_header_locked(struct super_block *sb)
+{
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+	int write_backup = 0;
+	int error = 0;
+
+	if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) {
+		memcpy(sbi->s_backup_vhdr, sbi->s_vhdr, sizeof(*sbi->s_vhdr));
+		write_backup = 1;
+	}
+
+	error = hfsplus_submit_bio(sb,
+			sbi->part_start + HFSPLUS_VOLHEAD_SECTOR,
+			sbi->s_vhdr_buf, NULL, WRITE_SYNC);
+
+	if (error || !write_backup)
+		goto out;
+
+	error = hfsplus_submit_bio(sb,
+			sbi->part_start + sbi->sect_count - 2,
+			sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC);
+out:
+	return error;
+}
+
+/* Sync dirty/clean volume header state to disk. */
+static int hfsplus_sync_volume_header(struct super_block *sb)
+{
+	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+	int error = 0;
+
+	hfs_dbg(SUPER, "hfsplus_sync_volume_header\n");
+
+	mutex_lock(&sbi->vh_mutex);
+	error = hfsplus_sync_volume_header_locked(sb);
+	mutex_unlock(&sbi->vh_mutex);
+
+	if (!error && !test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+		blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
+
+	return error;
+}
+
 static int hfsplus_sync_fs(struct super_block *sb, int wait)
 {
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
 	struct hfsplus_vh *vhdr = sbi->s_vhdr;
-	int write_backup = 0;
+	int write_header = 0;
 	int error, error2;
+	u32 free_blocks, next_cnid;
+	u32 folder_count, file_count;
 
 	if (!wait)
 		return 0;
@@ -196,7 +245,8 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait)
 		error = error2;
 	if (sbi->attr_tree) {
 		error2 =
-		    filemap_write_and_wait(sbi->attr_tree->inode->i_mapping);
+			filemap_write_and_wait(
+					sbi->attr_tree->inode->i_mapping);
 		if (!error)
 			error = error2;
 	}
@@ -206,34 +256,41 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait)
 
 	mutex_lock(&sbi->vh_mutex);
 	mutex_lock(&sbi->alloc_mutex);
-	vhdr->free_blocks = cpu_to_be32(sbi->free_blocks);
-	vhdr->next_cnid = cpu_to_be32(sbi->next_cnid);
-	vhdr->folder_count = cpu_to_be32(sbi->folder_count);
-	vhdr->file_count = cpu_to_be32(sbi->file_count);
 
-	if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) {
-		memcpy(sbi->s_backup_vhdr, sbi->s_vhdr, sizeof(*sbi->s_vhdr));
-		write_backup = 1;
+	free_blocks = cpu_to_be32(sbi->free_blocks);
+	next_cnid = cpu_to_be32(sbi->next_cnid);
+	folder_count = cpu_to_be32(sbi->folder_count);
+	file_count = cpu_to_be32(sbi->file_count);
+
+	/* Check if some attribute of volume header has changed. */
+	if (vhdr->free_blocks != free_blocks ||
+			vhdr->next_cnid != next_cnid ||
+			vhdr->folder_count != folder_count ||
+			vhdr->file_count != file_count) {
+		vhdr->free_blocks = free_blocks;
+		vhdr->next_cnid = next_cnid;
+		vhdr->folder_count = folder_count;
+		vhdr->file_count = file_count;
+		write_header = 1;
 	}
+	/*
+	 * Write volume header only when something has changed. Also there
+	 * is no need to write backup volume header if nothing has changed
+	 * in the the volume header itself.
+	 */
+	if (!write_header)
+		goto out;
 
-	error2 = hfsplus_submit_bio(sb,
-				   sbi->part_start + HFSPLUS_VOLHEAD_SECTOR,
-				   sbi->s_vhdr_buf, NULL, WRITE_SYNC);
+	error2 = hfsplus_sync_volume_header_locked(sb);
 	if (!error)
 		error = error2;
-	if (!write_backup)
-		goto out;
 
-	error2 = hfsplus_submit_bio(sb,
-				  sbi->part_start + sbi->sect_count - 2,
-				  sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC);
-	if (!error)
-		error2 = error;
 out:
 	mutex_unlock(&sbi->alloc_mutex);
 	mutex_unlock(&sbi->vh_mutex);
 
-	if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+	if (write_header && !error &&
+			!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
 		blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
 
 	return error;
@@ -287,7 +344,7 @@ static void hfsplus_put_super(struct super_block *sb)
 		vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT);
 		vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT);
 
-		hfsplus_sync_fs(sb, 1);
+		hfsplus_sync_volume_header(sb);
 	}
 
 	hfs_btree_close(sbi->attr_tree);
@@ -539,7 +596,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 		be32_add_cpu(&vhdr->write_count, 1);
 		vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
 		vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
-		hfsplus_sync_fs(sb, 1);
+		hfsplus_sync_volume_header(sb);
 
 		if (!sbi->hidden_dir) {
 			mutex_lock(&sbi->vh_mutex);



             reply	other threads:[~2014-07-17 16:35 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-17 16:32 Sougata Santra [this message]
2014-07-17 20:59 ` [PATCH 1/1] hfsplus: skip unnecessary volume header sync Andrew Morton
2014-07-18  8:35   ` Sougata Santra
2014-07-18  9:01     ` Vyacheslav Dubeyko
2014-07-18  9:49       ` Sougata Santra
2014-07-19 10:58         ` Vyacheslav Dubeyko
2014-07-19 12:18           ` sougata santra
2014-07-18  8:28 ` Vyacheslav Dubeyko
2014-07-18  9:24   ` Sougata Santra
2014-07-19 11:23     ` Vyacheslav Dubeyko
2014-07-19 11:59       ` sougata santra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1405614762.25052.8.camel@ultrabook \
    --to=sougata@tuxera.com \
    --cc=akpm@linux-foundation.org \
    --cc=fabf@skynet.be \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=slava@dubeyko.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.