From: Christoph Hellwig <hch@lst.de>
To: linux-fsdevel@vger.kernel.org
Subject: [PATCH 10/11] hfsplus: optimize fsync
Date: Wed, 17 Nov 2010 23:23:13 +0100 [thread overview]
Message-ID: <20101117222313.GK21700@lst.de> (raw)
In-Reply-To: <20101117222117.GA21700@lst.de>
Avoid doing unessecary work in fsync. Do nothing unless the inode
was marked dirty, and only write the various metadata inodes out if
they contain any dirty state from this inode. This is archived by
adding three new dirty bits to the hfsplus-specific inode which are
set in the correct places.
Signed-off-by: Christoph Hellwig <hch@tuxera.com>
Index: linux-2.6/fs/hfsplus/inode.c
===================================================================
--- linux-2.6.orig/fs/hfsplus/inode.c 2010-11-17 22:54:53.842254646 +0100
+++ linux-2.6/fs/hfsplus/inode.c 2010-11-17 22:56:01.488273225 +0100
@@ -307,8 +307,12 @@ static int hfsplus_setattr(struct dentry
int hfsplus_file_fsync(struct file *file, int datasync)
{
struct inode *inode = file->f_mapping->host;
+ struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
- int error, error2;
+ int error = 0, error2;
+
+ if (!(inode->i_state & I_DIRTY))
+ return 0;
/*
* Sync inode metadata into the catalog and extent trees.
@@ -318,13 +322,21 @@ int hfsplus_file_fsync(struct file *file
/*
* And explicitly write out the btrees.
*/
- error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
- error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
- if (!error)
- error = error2;
- error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
- if (!error)
- error = error2;
+ if (test_and_clear_bit(HFSPLUS_I_CAT_DIRTY, &hip->flags))
+ error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
+
+ if (test_and_clear_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags)) {
+ error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
+ if (!error)
+ error = error2;
+ }
+
+ if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags)) {
+ error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
+ if (!error)
+ error = error2;
+ }
+
return error;
}
@@ -590,6 +602,8 @@ int hfsplus_cat_write_inode(struct inode
hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_file));
}
+
+ set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
out:
hfs_find_exit(&fd);
return 0;
Index: linux-2.6/fs/hfsplus/hfsplus_fs.h
===================================================================
--- linux-2.6.orig/fs/hfsplus/hfsplus_fs.h 2010-11-17 22:54:53.843254576 +0100
+++ linux-2.6/fs/hfsplus/hfsplus_fs.h 2010-11-17 22:56:01.488273225 +0100
@@ -157,6 +157,11 @@ struct hfsplus_sb_info {
#define HFSPLUS_SB_HFSX 3
#define HFSPLUS_SB_CASEFOLD 4
+static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
+{
+ return sb->s_fs_info;
+}
+
struct hfsplus_inode_info {
atomic_t opencnt;
@@ -205,10 +210,24 @@ struct hfsplus_inode_info {
#define HFSPLUS_EXT_NEW 0x0002
#define HFSPLUS_I_RSRC 0 /* represents a resource fork */
+#define HFSPLUS_I_CAT_DIRTY 1 /* has changes in the catalog tree */
+#define HFSPLUS_I_EXT_DIRTY 2 /* has changes in the extent tree */
+#define HFSPLUS_I_ALLOC_DIRTY 3 /* has changes in the allocation file */
#define HFSPLUS_IS_RSRC(inode) \
test_bit(HFSPLUS_I_RSRC, &HFSPLUS_I(inode)->flags)
+static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
+{
+ return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
+}
+
+static inline void hfsplus_mark_catalog_dirty(struct inode *inode)
+{
+ set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
+ mark_inode_dirty(inode);
+}
+
struct hfs_find_data {
/* filled by caller */
hfsplus_btree_key *search_key;
@@ -397,17 +416,6 @@ int hfs_part_find(struct super_block *,
int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
void *data, int rw);
-/* access macros */
-static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
-{
- return sb->s_fs_info;
-}
-
-static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
-{
- return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
-}
-
/* time macros */
#define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U)
#define __hfsp_ut2mt(t) (cpu_to_be32(t + 2082844800U))
Index: linux-2.6/fs/hfsplus/catalog.c
===================================================================
--- linux-2.6.orig/fs/hfsplus/catalog.c 2010-11-17 22:43:05.439004891 +0100
+++ linux-2.6/fs/hfsplus/catalog.c 2010-11-17 22:56:01.490026123 +0100
@@ -227,7 +227,8 @@ int hfsplus_create_cat(u32 cnid, struct
dir->i_size++;
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(dir);
+ hfsplus_mark_catalog_dirty(dir);
+
hfs_find_exit(&fd);
return 0;
@@ -308,7 +309,7 @@ int hfsplus_delete_cat(u32 cnid, struct
dir->i_size--;
dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(dir);
+ hfsplus_mark_catalog_dirty(dir);
out:
hfs_find_exit(&fd);
@@ -353,7 +354,6 @@ int hfsplus_rename_cat(u32 cnid,
goto out;
dst_dir->i_size++;
dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(dst_dir);
/* finally remove the old entry */
hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
@@ -365,7 +365,6 @@ int hfsplus_rename_cat(u32 cnid,
goto out;
src_dir->i_size--;
src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(src_dir);
/* remove old thread entry */
hfsplus_cat_build_key(sb, src_fd.search_key, cnid, NULL);
@@ -387,6 +386,9 @@ int hfsplus_rename_cat(u32 cnid,
goto out;
}
err = hfs_brec_insert(&dst_fd, &entry, entry_size);
+
+ hfsplus_mark_catalog_dirty(dst_dir);
+ hfsplus_mark_catalog_dirty(src_dir);
out:
hfs_bnode_put(dst_fd.bnode);
hfs_find_exit(&src_fd);
Index: linux-2.6/fs/hfsplus/extents.c
===================================================================
--- linux-2.6.orig/fs/hfsplus/extents.c 2010-11-17 22:54:53.850253110 +0100
+++ linux-2.6/fs/hfsplus/extents.c 2010-11-17 22:56:01.494045889 +0100
@@ -108,6 +108,7 @@ static void __hfsplus_ext_write_extent(s
fd->entryoffset, fd->entrylength);
hip->extent_state &= ~HFSPLUS_EXT_DIRTY;
}
+ set_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags);
}
static void hfsplus_ext_write_extent_locked(struct inode *inode)
@@ -403,6 +404,7 @@ int hfsplus_file_extend(struct inode *in
}
dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
+ set_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags);
if (hip->alloc_blocks <= hip->first_blocks) {
if (!hip->first_blocks) {
@@ -530,4 +532,5 @@ out:
hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
mark_inode_dirty(inode);
+ set_bit(HFSPLUS_I_ALLOC_DIRTY, &HFSPLUS_I(inode)->flags);
}
Index: linux-2.6/fs/hfsplus/ioctl.c
===================================================================
--- linux-2.6.orig/fs/hfsplus/ioctl.c 2010-11-17 22:43:05.452004821 +0100
+++ linux-2.6/fs/hfsplus/ioctl.c 2010-11-17 22:56:01.498003634 +0100
@@ -147,9 +147,11 @@ int hfsplus_setxattr(struct dentry *dent
res = -ERANGE;
} else
res = -EOPNOTSUPP;
- if (!res)
+ if (!res) {
hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_file));
+ hfsplus_mark_catalog_dirty(inode);
+ }
out:
hfs_find_exit(&fd);
return res;
Index: linux-2.6/fs/hfsplus/super.c
===================================================================
--- linux-2.6.orig/fs/hfsplus/super.c 2010-11-17 22:54:53.845253878 +0100
+++ linux-2.6/fs/hfsplus/super.c 2010-11-17 22:56:01.505005590 +0100
@@ -472,7 +472,7 @@ static int hfsplus_fill_super(struct sup
&str, sbi->hidden_dir);
mutex_unlock(&sbi->vh_mutex);
- mark_inode_dirty(sbi->hidden_dir);
+ hfsplus_mark_catalog_dirty(sbi->hidden_dir);
}
out:
unload_nls(sbi->nls);
next prev parent reply other threads:[~2010-11-17 22:23 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-17 22:21 hfsplus patch review Christoph Hellwig
2010-11-17 22:21 ` [PATCH 1/11] hfsplus: silence a few debug printks Christoph Hellwig
2010-11-17 22:21 ` [PATCH 2/11] hfsplus: always use hfsplus_sync_fs to write the volume header Christoph Hellwig
2010-11-17 22:22 ` [PATCH 3/11] hfsplus: use raw bio access for the volume headers Christoph Hellwig
2010-11-17 22:22 ` [PATCH 4/11] hfsplus: use raw bio access for partition tables Christoph Hellwig
2010-11-17 22:22 ` [PATCH 5/11] hfsplus: make sure sync writes out all metadata Christoph Hellwig
2010-11-17 22:22 ` [PATCH 6/11] hfsplus: avoid useless work in hfsplus_sync_fs Christoph Hellwig
2010-11-17 22:22 ` [PATCH 7/11] hfsplus: simplify fsync Christoph Hellwig
2010-11-17 22:22 ` [PATCH 8/11] hfsplus: write up fsync for directories Christoph Hellwig
2010-11-17 22:23 ` [PATCH 9/11] hfsplus: split up inode flags Christoph Hellwig
2010-11-17 22:23 ` Christoph Hellwig [this message]
2010-11-18 6:40 ` [PATCH 10/11] hfsplus: optimize fsync Nick Piggin
2010-11-18 13:50 ` Christoph Hellwig
2010-11-18 14:13 ` Nick Piggin
2010-11-18 14:16 ` Christoph Hellwig
2010-11-22 13:03 ` Nick Piggin
2010-11-22 13:18 ` Nick Piggin
2010-11-22 13:29 ` Christoph Hellwig
2010-11-22 11:35 ` [PATCH v2] " Christoph Hellwig
2010-11-17 22:23 ` [PATCH 11/11] hfsplus: flush disk caches in sync and fsync Christoph Hellwig
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=20101117222313.GK21700@lst.de \
--to=hch@lst.de \
--cc=linux-fsdevel@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).