diff options
-rw-r--r-- | fs/hfsplus/bnode.c | 17 | ||||
-rw-r--r-- | fs/hfsplus/btree.c | 2 | ||||
-rw-r--r-- | fs/hfsplus/extents.c | 10 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 3 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_raw.h | 1 | ||||
-rw-r--r-- | fs/hfsplus/xattr.c | 2 |
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 | */ | ||
663 | bool 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 | ||
428 | int hfsplus_file_extend(struct inode *inode) | 428 | int 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 *); | |||
414 | struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32); | 414 | struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32); |
415 | void hfs_bnode_get(struct hfs_bnode *); | 415 | void hfs_bnode_get(struct hfs_bnode *); |
416 | void hfs_bnode_put(struct hfs_bnode *); | 416 | void hfs_bnode_put(struct hfs_bnode *); |
417 | bool hfs_bnode_need_zeroout(struct hfs_btree *); | ||
417 | 418 | ||
418 | /* brec.c */ | 419 | /* brec.c */ |
419 | u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *); | 420 | u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *); |
@@ -460,7 +461,7 @@ int hfsplus_ext_write_extent(struct inode *); | |||
460 | int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); | 461 | int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); |
461 | int hfsplus_free_fork(struct super_block *, u32, | 462 | int hfsplus_free_fork(struct super_block *, u32, |
462 | struct hfsplus_fork_raw *, int); | 463 | struct hfsplus_fork_raw *, int); |
463 | int hfsplus_file_extend(struct inode *); | 464 | int hfsplus_file_extend(struct inode *, bool zeroout); |
464 | void hfsplus_file_truncate(struct inode *); | 465 | void 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 */ |
149 | struct hfs_bnode_desc { | 150 | struct 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; |