aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/extents.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@tuxera.com>2010-11-23 08:38:15 -0500
committerChristoph Hellwig <hch@lst.de>2010-11-23 08:38:15 -0500
commite34947056076ca5467ee8256d2d9cbc594a79b37 (patch)
treec1b70f51c1e4bc38e0b0389224862afe26c5720f /fs/hfsplus/extents.c
parentb33b7921db14abcd10c30d0ccfc68e364f5ef7fe (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/extents.c')
-rw-r--r--fs/hfsplus/extents.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 06b4fc3151a3..b1127ef26750 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -108,6 +108,14 @@ static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data
108 fd->entryoffset, fd->entrylength); 108 fd->entryoffset, fd->entrylength);
109 hip->extent_state &= ~HFSPLUS_EXT_DIRTY; 109 hip->extent_state &= ~HFSPLUS_EXT_DIRTY;
110 } 110 }
111
112 /*
113 * We can't just use hfsplus_mark_inode_dirty here, because we
114 * also get called from hfsplus_write_inode, which should not
115 * redirty the inode. Instead the callers have to be careful
116 * to explicily mark the inode dirty, too.
117 */
118 set_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags);
111} 119}
112 120
113static void hfsplus_ext_write_extent_locked(struct inode *inode) 121static void hfsplus_ext_write_extent_locked(struct inode *inode)
@@ -197,6 +205,7 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
197 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 205 struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
198 int res = -EIO; 206 int res = -EIO;
199 u32 ablock, dblock, mask; 207 u32 ablock, dblock, mask;
208 int was_dirty = 0;
200 int shift; 209 int shift;
201 210
202 /* Convert inode block to disk allocation block */ 211 /* Convert inode block to disk allocation block */
@@ -223,14 +232,20 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
223 return -EIO; 232 return -EIO;
224 233
225 mutex_lock(&hip->extents_lock); 234 mutex_lock(&hip->extents_lock);
235
236 /*
237 * hfsplus_ext_read_extent will write out a cached extent into
238 * the extents btree. In that case we may have to mark the inode
239 * dirty even for a pure read of an extent here.
240 */
241 was_dirty = (hip->extent_state & HFSPLUS_EXT_DIRTY);
226 res = hfsplus_ext_read_extent(inode, ablock); 242 res = hfsplus_ext_read_extent(inode, ablock);
227 if (!res) { 243 if (res) {
228 dblock = hfsplus_ext_find_block(hip->cached_extents,
229 ablock - hip->cached_start);
230 } else {
231 mutex_unlock(&hip->extents_lock); 244 mutex_unlock(&hip->extents_lock);
232 return -EIO; 245 return -EIO;
233 } 246 }
247 dblock = hfsplus_ext_find_block(hip->cached_extents,
248 ablock - hip->cached_start);
234 mutex_unlock(&hip->extents_lock); 249 mutex_unlock(&hip->extents_lock);
235 250
236done: 251done:
@@ -242,8 +257,9 @@ done:
242 hip->phys_size += sb->s_blocksize; 257 hip->phys_size += sb->s_blocksize;
243 hip->fs_blocks++; 258 hip->fs_blocks++;
244 inode_add_bytes(inode, sb->s_blocksize); 259 inode_add_bytes(inode, sb->s_blocksize);
245 mark_inode_dirty(inode);
246 } 260 }
261 if (create || was_dirty)
262 mark_inode_dirty(inode);
247 return 0; 263 return 0;
248} 264}
249 265
@@ -438,7 +454,7 @@ out:
438 mutex_unlock(&hip->extents_lock); 454 mutex_unlock(&hip->extents_lock);
439 if (!res) { 455 if (!res) {
440 hip->alloc_blocks += len; 456 hip->alloc_blocks += len;
441 mark_inode_dirty(inode); 457 hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ALLOC_DIRTY);
442 } 458 }
443 return res; 459 return res;
444 460
@@ -529,5 +545,5 @@ out:
529 hip->phys_size = inode->i_size; 545 hip->phys_size = inode->i_size;
530 hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 546 hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
531 inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); 547 inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
532 mark_inode_dirty(inode); 548 hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ALLOC_DIRTY);
533} 549}