aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/extents.c
diff options
context:
space:
mode:
authorSergei Antonov <saproj@gmail.com>2014-06-06 17:36:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-06 19:08:10 -0400
commit2cd282a1bc6b9d111b8beee63bea0af735a8a1aa (patch)
tree80dff1bb5f089868bdbee433b0308098b2c2e6b4 /fs/hfsplus/extents.c
parent915ab236d3c491f9bb0f6596d03e25b37f4d5a20 (diff)
hfsplus: fix "unused node is not erased" error
Zero newly allocated extents in the catalog tree if volume attributes tell us to. Not doing so we risk getting the "unused node is not erased" error. See kHFSUnusedNodeFix flag in Apple's source code for reference. There was a previous commit clearing the node when it is freed: commit 899bed05e9f6 ("hfsplus: fix issue with unzeroed unused b-tree nodes"). But it did not handle newly allocated extents (this patch fixes it). And it zeroed nodes in all trees unconditionally which is an overkill. This patch adds a condition and also switches to 'tree->node_size' as a simpler method of getting the length to zero. Signed-off-by: Sergei Antonov <saproj@gmail.com> Cc: Anton Altaparmakov <aia21@cam.ac.uk> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@infradead.org> Cc: Vyacheslav Dubeyko <slava@dubeyko.com> Cc: Hin-Tak Leung <htl10@users.sourceforge.net> Cc: Kyle Laracey <kalaracey@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hfsplus/extents.c')
-rw-r--r--fs/hfsplus/extents.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index a7aafb35b624..a09fcb68c364 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -235,7 +235,7 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
235 if (iblock > hip->fs_blocks || !create) 235 if (iblock > hip->fs_blocks || !create)
236 return -EIO; 236 return -EIO;
237 if (ablock >= hip->alloc_blocks) { 237 if (ablock >= hip->alloc_blocks) {
238 res = hfsplus_file_extend(inode); 238 res = hfsplus_file_extend(inode, false);
239 if (res) 239 if (res)
240 return res; 240 return res;
241 } 241 }
@@ -425,7 +425,7 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid,
425 return res; 425 return res;
426} 426}
427 427
428int hfsplus_file_extend(struct inode *inode) 428int hfsplus_file_extend(struct inode *inode, bool zeroout)
429{ 429{
430 struct super_block *sb = inode->i_sb; 430 struct super_block *sb = inode->i_sb;
431 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 431 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
@@ -463,6 +463,12 @@ int hfsplus_file_extend(struct inode *inode)
463 } 463 }
464 } 464 }
465 465
466 if (zeroout) {
467 res = sb_issue_zeroout(sb, start, len, GFP_NOFS);
468 if (res)
469 goto out;
470 }
471
466 hfs_dbg(EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len); 472 hfs_dbg(EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len);
467 473
468 if (hip->alloc_blocks <= hip->first_blocks) { 474 if (hip->alloc_blocks <= hip->first_blocks) {