diff options
author | Christoph Hellwig <hch@tuxera.com> | 2010-11-23 14:38:15 +0100 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2010-11-23 14:38:15 +0100 |
commit | e34947056076ca5467ee8256d2d9cbc594a79b37 (patch) | |
tree | c1b70f51c1e4bc38e0b0389224862afe26c5720f /fs/hfsplus/inode.c | |
parent | b33b7921db14abcd10c30d0ccfc68e364f5ef7fe (diff) |
hfsplus: optimize fsync
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>
Diffstat (limited to 'fs/hfsplus/inode.c')
-rw-r--r-- | fs/hfsplus/inode.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 0946e2cdca5e..bf6535b73261 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -307,8 +307,9 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr) 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; /* * Sync inode metadata into the catalog and extent trees. @@ -318,13 +319,21 @@ int hfsplus_file_fsync(struct file *file, int datasync) /* * 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 +599,8 @@ int hfsplus_cat_write_inode(struct inode *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; |