aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/hfsplus/bnode.c17
-rw-r--r--fs/hfsplus/btree.c2
-rw-r--r--fs/hfsplus/extents.c10
-rw-r--r--fs/hfsplus/hfsplus_fs.h3
-rw-r--r--fs/hfsplus/hfsplus_raw.h1
-rw-r--r--fs/hfsplus/xattr.c2
6 files changed, 28 insertions, 7 deletions
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 285502af8df1..759708fd9331 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -646,8 +646,8 @@ void hfs_bnode_put(struct hfs_bnode *node)
646 if (test_bit(HFS_BNODE_DELETED, &node->flags)) { 646 if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
647 hfs_bnode_unhash(node); 647 hfs_bnode_unhash(node);
648 spin_unlock(&tree->hash_lock); 648 spin_unlock(&tree->hash_lock);
649 hfs_bnode_clear(node, 0, 649 if (hfs_bnode_need_zeroout(tree))
650 PAGE_CACHE_SIZE * tree->pages_per_bnode); 650 hfs_bnode_clear(node, 0, tree->node_size);
651 hfs_bmap_free(node); 651 hfs_bmap_free(node);
652 hfs_bnode_free(node); 652 hfs_bnode_free(node);
653 return; 653 return;
@@ -656,3 +656,16 @@ void hfs_bnode_put(struct hfs_bnode *node)
656 } 656 }
657} 657}
658 658
659/*
660 * Unused nodes have to be zeroed if this is the catalog tree and
661 * a corresponding flag in the volume header is set.
662 */
663bool hfs_bnode_need_zeroout(struct hfs_btree *tree)
664{
665 struct super_block *sb = tree->inode->i_sb;
666 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
667 const u32 volume_attr = be32_to_cpu(sbi->s_vhdr->attributes);
668
669 return tree->cnid == HFSPLUS_CAT_CNID &&
670 volume_attr & HFSPLUS_VOL_UNUSED_NODE_FIX;
671}
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 0fcec8b2a90b..3345c7553edc 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -358,7 +358,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
358 u32 count; 358 u32 count;
359 int res; 359 int res;
360 360
361 res = hfsplus_file_extend(inode); 361 res = hfsplus_file_extend(inode, hfs_bnode_need_zeroout(tree));
362 if (res) 362 if (res)
363 return ERR_PTR(res); 363 return ERR_PTR(res);
364 hip->phys_size = inode->i_size = 364 hip->phys_size = inode->i_size =
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) {
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 6c08ff6b11b2..d5ab79bd2f0f 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -414,6 +414,7 @@ void hfs_bnode_free(struct hfs_bnode *);
414struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32); 414struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32);
415void hfs_bnode_get(struct hfs_bnode *); 415void hfs_bnode_get(struct hfs_bnode *);
416void hfs_bnode_put(struct hfs_bnode *); 416void hfs_bnode_put(struct hfs_bnode *);
417bool hfs_bnode_need_zeroout(struct hfs_btree *);
417 418
418/* brec.c */ 419/* brec.c */
419u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *); 420u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *);
@@ -460,7 +461,7 @@ int hfsplus_ext_write_extent(struct inode *);
460int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); 461int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
461int hfsplus_free_fork(struct super_block *, u32, 462int hfsplus_free_fork(struct super_block *, u32,
462 struct hfsplus_fork_raw *, int); 463 struct hfsplus_fork_raw *, int);
463int hfsplus_file_extend(struct inode *); 464int hfsplus_file_extend(struct inode *, bool zeroout);
464void hfsplus_file_truncate(struct inode *); 465void hfsplus_file_truncate(struct inode *);
465 466
466/* inode.c */ 467/* inode.c */
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 5a126828d85e..8298d0985f81 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -144,6 +144,7 @@ struct hfsplus_vh {
144#define HFSPLUS_VOL_NODEID_REUSED (1 << 12) 144#define HFSPLUS_VOL_NODEID_REUSED (1 << 12)
145#define HFSPLUS_VOL_JOURNALED (1 << 13) 145#define HFSPLUS_VOL_JOURNALED (1 << 13)
146#define HFSPLUS_VOL_SOFTLOCK (1 << 15) 146#define HFSPLUS_VOL_SOFTLOCK (1 << 15)
147#define HFSPLUS_VOL_UNUSED_NODE_FIX (1 << 31)
147 148
148/* HFS+ BTree node descriptor */ 149/* HFS+ BTree node descriptor */
149struct hfs_bnode_desc { 150struct hfs_bnode_desc {
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index c03c94611cce..aab093c27c59 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -196,7 +196,7 @@ check_attr_tree_state_again:
196 } 196 }
197 197
198 while (hip->alloc_blocks < hip->clump_blocks) { 198 while (hip->alloc_blocks < hip->clump_blocks) {
199 err = hfsplus_file_extend(attr_file); 199 err = hfsplus_file_extend(attr_file, false);
200 if (unlikely(err)) { 200 if (unlikely(err)) {
201 pr_err("failed to extend attributes file\n"); 201 pr_err("failed to extend attributes file\n");
202 goto end_attr_file_creation; 202 goto end_attr_file_creation;