aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/extents.c
diff options
context:
space:
mode:
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}