diff options
Diffstat (limited to 'fs/hfsplus/extents.c')
-rw-r--r-- | fs/hfsplus/extents.c | 30 |
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 | ||
113 | static void hfsplus_ext_write_extent_locked(struct inode *inode) | 121 | static 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 | ||
236 | done: | 251 | done: |
@@ -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 | } |