diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-20 12:50:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-20 12:50:11 -0400 |
commit | c2661b806092d8ea2dccb7b02b65776555e0ee47 (patch) | |
tree | ebc73fa58706e5a0a79235953c532ac6c6e2b539 /fs/ext4/namei.c | |
parent | f114040e3ea6e07372334ade75d1ee0775c355e1 (diff) | |
parent | 813d32f91333e4c33d5a19b67167c4bae42dae75 (diff) |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o:
"A large number of cleanups and bug fixes, with some (minor) journal
optimizations"
[ This got sent to me before -rc1, but was stuck in my spam folder. - Linus ]
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (67 commits)
ext4: check s_chksum_driver when looking for bg csum presence
ext4: move error report out of atomic context in ext4_init_block_bitmap()
ext4: Replace open coded mdata csum feature to helper function
ext4: delete useless comments about ext4_move_extents
ext4: fix reservation overflow in ext4_da_write_begin
ext4: add ext4_iget_normal() which is to be used for dir tree lookups
ext4: don't orphan or truncate the boot loader inode
ext4: grab missed write_count for EXT4_IOC_SWAP_BOOT
ext4: optimize block allocation on grow indepth
ext4: get rid of code duplication
ext4: fix over-defensive complaint after journal abort
ext4: fix return value of ext4_do_update_inode
ext4: fix mmap data corruption when blocksize < pagesize
vfs: fix data corruption when blocksize < pagesize for mmaped data
ext4: fold ext4_nojournal_sops into ext4_sops
ext4: support freezing ext2 (nojournal) file systems
ext4: fold ext4_sync_fs_nojournal() into ext4_sync_fs()
ext4: don't check quota format when there are no quota files
jbd2: simplify calling convention around __jbd2_journal_clean_checkpoint_list
jbd2: avoid pointless scanning of checkpoint lists
...
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r-- | fs/ext4/namei.c | 240 |
1 files changed, 99 insertions, 141 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 603e4ebbd0ac..adb559de23c1 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -53,7 +53,7 @@ static struct buffer_head *ext4_append(handle_t *handle, | |||
53 | ext4_lblk_t *block) | 53 | ext4_lblk_t *block) |
54 | { | 54 | { |
55 | struct buffer_head *bh; | 55 | struct buffer_head *bh; |
56 | int err = 0; | 56 | int err; |
57 | 57 | ||
58 | if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb && | 58 | if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb && |
59 | ((inode->i_size >> 10) >= | 59 | ((inode->i_size >> 10) >= |
@@ -62,9 +62,9 @@ static struct buffer_head *ext4_append(handle_t *handle, | |||
62 | 62 | ||
63 | *block = inode->i_size >> inode->i_sb->s_blocksize_bits; | 63 | *block = inode->i_size >> inode->i_sb->s_blocksize_bits; |
64 | 64 | ||
65 | bh = ext4_bread(handle, inode, *block, 1, &err); | 65 | bh = ext4_bread(handle, inode, *block, 1); |
66 | if (!bh) | 66 | if (IS_ERR(bh)) |
67 | return ERR_PTR(err); | 67 | return bh; |
68 | inode->i_size += inode->i_sb->s_blocksize; | 68 | inode->i_size += inode->i_sb->s_blocksize; |
69 | EXT4_I(inode)->i_disksize = inode->i_size; | 69 | EXT4_I(inode)->i_disksize = inode->i_size; |
70 | BUFFER_TRACE(bh, "get_write_access"); | 70 | BUFFER_TRACE(bh, "get_write_access"); |
@@ -94,20 +94,20 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, | |||
94 | { | 94 | { |
95 | struct buffer_head *bh; | 95 | struct buffer_head *bh; |
96 | struct ext4_dir_entry *dirent; | 96 | struct ext4_dir_entry *dirent; |
97 | int err = 0, is_dx_block = 0; | 97 | int is_dx_block = 0; |
98 | 98 | ||
99 | bh = ext4_bread(NULL, inode, block, 0, &err); | 99 | bh = ext4_bread(NULL, inode, block, 0); |
100 | if (!bh) { | 100 | if (IS_ERR(bh)) { |
101 | if (err == 0) { | ||
102 | ext4_error_inode(inode, __func__, line, block, | ||
103 | "Directory hole found"); | ||
104 | return ERR_PTR(-EIO); | ||
105 | } | ||
106 | __ext4_warning(inode->i_sb, __func__, line, | 101 | __ext4_warning(inode->i_sb, __func__, line, |
107 | "error reading directory block " | 102 | "error %ld reading directory block " |
108 | "(ino %lu, block %lu)", inode->i_ino, | 103 | "(ino %lu, block %lu)", PTR_ERR(bh), inode->i_ino, |
109 | (unsigned long) block); | 104 | (unsigned long) block); |
110 | return ERR_PTR(err); | 105 | |
106 | return bh; | ||
107 | } | ||
108 | if (!bh) { | ||
109 | ext4_error_inode(inode, __func__, line, block, "Directory hole found"); | ||
110 | return ERR_PTR(-EIO); | ||
111 | } | 111 | } |
112 | dirent = (struct ext4_dir_entry *) bh->b_data; | 112 | dirent = (struct ext4_dir_entry *) bh->b_data; |
113 | /* Determine whether or not we have an index block */ | 113 | /* Determine whether or not we have an index block */ |
@@ -124,8 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, | |||
124 | "directory leaf block found instead of index block"); | 124 | "directory leaf block found instead of index block"); |
125 | return ERR_PTR(-EIO); | 125 | return ERR_PTR(-EIO); |
126 | } | 126 | } |
127 | if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 127 | if (!ext4_has_metadata_csum(inode->i_sb) || |
128 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) || | ||
129 | buffer_verified(bh)) | 128 | buffer_verified(bh)) |
130 | return bh; | 129 | return bh; |
131 | 130 | ||
@@ -253,8 +252,7 @@ static unsigned dx_node_limit(struct inode *dir); | |||
253 | static struct dx_frame *dx_probe(const struct qstr *d_name, | 252 | static struct dx_frame *dx_probe(const struct qstr *d_name, |
254 | struct inode *dir, | 253 | struct inode *dir, |
255 | struct dx_hash_info *hinfo, | 254 | struct dx_hash_info *hinfo, |
256 | struct dx_frame *frame, | 255 | struct dx_frame *frame); |
257 | int *err); | ||
258 | static void dx_release(struct dx_frame *frames); | 256 | static void dx_release(struct dx_frame *frames); |
259 | static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, | 257 | static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize, |
260 | struct dx_hash_info *hinfo, struct dx_map_entry map[]); | 258 | struct dx_hash_info *hinfo, struct dx_map_entry map[]); |
@@ -270,8 +268,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash, | |||
270 | __u32 *start_hash); | 268 | __u32 *start_hash); |
271 | static struct buffer_head * ext4_dx_find_entry(struct inode *dir, | 269 | static struct buffer_head * ext4_dx_find_entry(struct inode *dir, |
272 | const struct qstr *d_name, | 270 | const struct qstr *d_name, |
273 | struct ext4_dir_entry_2 **res_dir, | 271 | struct ext4_dir_entry_2 **res_dir); |
274 | int *err); | ||
275 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | 272 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, |
276 | struct inode *inode); | 273 | struct inode *inode); |
277 | 274 | ||
@@ -340,8 +337,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent) | |||
340 | { | 337 | { |
341 | struct ext4_dir_entry_tail *t; | 338 | struct ext4_dir_entry_tail *t; |
342 | 339 | ||
343 | if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 340 | if (!ext4_has_metadata_csum(inode->i_sb)) |
344 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
345 | return 1; | 341 | return 1; |
346 | 342 | ||
347 | t = get_dirent_tail(inode, dirent); | 343 | t = get_dirent_tail(inode, dirent); |
@@ -362,8 +358,7 @@ static void ext4_dirent_csum_set(struct inode *inode, | |||
362 | { | 358 | { |
363 | struct ext4_dir_entry_tail *t; | 359 | struct ext4_dir_entry_tail *t; |
364 | 360 | ||
365 | if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 361 | if (!ext4_has_metadata_csum(inode->i_sb)) |
366 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
367 | return; | 362 | return; |
368 | 363 | ||
369 | t = get_dirent_tail(inode, dirent); | 364 | t = get_dirent_tail(inode, dirent); |
@@ -438,8 +433,7 @@ static int ext4_dx_csum_verify(struct inode *inode, | |||
438 | struct dx_tail *t; | 433 | struct dx_tail *t; |
439 | int count_offset, limit, count; | 434 | int count_offset, limit, count; |
440 | 435 | ||
441 | if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 436 | if (!ext4_has_metadata_csum(inode->i_sb)) |
442 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
443 | return 1; | 437 | return 1; |
444 | 438 | ||
445 | c = get_dx_countlimit(inode, dirent, &count_offset); | 439 | c = get_dx_countlimit(inode, dirent, &count_offset); |
@@ -468,8 +462,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent) | |||
468 | struct dx_tail *t; | 462 | struct dx_tail *t; |
469 | int count_offset, limit, count; | 463 | int count_offset, limit, count; |
470 | 464 | ||
471 | if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 465 | if (!ext4_has_metadata_csum(inode->i_sb)) |
472 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
473 | return; | 466 | return; |
474 | 467 | ||
475 | c = get_dx_countlimit(inode, dirent, &count_offset); | 468 | c = get_dx_countlimit(inode, dirent, &count_offset); |
@@ -557,8 +550,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize) | |||
557 | unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) - | 550 | unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) - |
558 | EXT4_DIR_REC_LEN(2) - infosize; | 551 | EXT4_DIR_REC_LEN(2) - infosize; |
559 | 552 | ||
560 | if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, | 553 | if (ext4_has_metadata_csum(dir->i_sb)) |
561 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
562 | entry_space -= sizeof(struct dx_tail); | 554 | entry_space -= sizeof(struct dx_tail); |
563 | return entry_space / sizeof(struct dx_entry); | 555 | return entry_space / sizeof(struct dx_entry); |
564 | } | 556 | } |
@@ -567,8 +559,7 @@ static inline unsigned dx_node_limit(struct inode *dir) | |||
567 | { | 559 | { |
568 | unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0); | 560 | unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0); |
569 | 561 | ||
570 | if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, | 562 | if (ext4_has_metadata_csum(dir->i_sb)) |
571 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
572 | entry_space -= sizeof(struct dx_tail); | 563 | entry_space -= sizeof(struct dx_tail); |
573 | return entry_space / sizeof(struct dx_entry); | 564 | return entry_space / sizeof(struct dx_entry); |
574 | } | 565 | } |
@@ -641,7 +632,9 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, | |||
641 | u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; | 632 | u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; |
642 | struct stats stats; | 633 | struct stats stats; |
643 | printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); | 634 | printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); |
644 | if (!(bh = ext4_bread (NULL,dir, block, 0,&err))) continue; | 635 | bh = ext4_bread(NULL,dir, block, 0); |
636 | if (!bh || IS_ERR(bh)) | ||
637 | continue; | ||
645 | stats = levels? | 638 | stats = levels? |
646 | dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): | 639 | dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): |
647 | dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0); | 640 | dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0); |
@@ -669,29 +662,25 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, | |||
669 | */ | 662 | */ |
670 | static struct dx_frame * | 663 | static struct dx_frame * |
671 | dx_probe(const struct qstr *d_name, struct inode *dir, | 664 | dx_probe(const struct qstr *d_name, struct inode *dir, |
672 | struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) | 665 | struct dx_hash_info *hinfo, struct dx_frame *frame_in) |
673 | { | 666 | { |
674 | unsigned count, indirect; | 667 | unsigned count, indirect; |
675 | struct dx_entry *at, *entries, *p, *q, *m; | 668 | struct dx_entry *at, *entries, *p, *q, *m; |
676 | struct dx_root *root; | 669 | struct dx_root *root; |
677 | struct buffer_head *bh; | ||
678 | struct dx_frame *frame = frame_in; | 670 | struct dx_frame *frame = frame_in; |
671 | struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR); | ||
679 | u32 hash; | 672 | u32 hash; |
680 | 673 | ||
681 | frame->bh = NULL; | 674 | frame->bh = ext4_read_dirblock(dir, 0, INDEX); |
682 | bh = ext4_read_dirblock(dir, 0, INDEX); | 675 | if (IS_ERR(frame->bh)) |
683 | if (IS_ERR(bh)) { | 676 | return (struct dx_frame *) frame->bh; |
684 | *err = PTR_ERR(bh); | 677 | |
685 | goto fail; | 678 | root = (struct dx_root *) frame->bh->b_data; |
686 | } | ||
687 | root = (struct dx_root *) bh->b_data; | ||
688 | if (root->info.hash_version != DX_HASH_TEA && | 679 | if (root->info.hash_version != DX_HASH_TEA && |
689 | root->info.hash_version != DX_HASH_HALF_MD4 && | 680 | root->info.hash_version != DX_HASH_HALF_MD4 && |
690 | root->info.hash_version != DX_HASH_LEGACY) { | 681 | root->info.hash_version != DX_HASH_LEGACY) { |
691 | ext4_warning(dir->i_sb, "Unrecognised inode hash code %d", | 682 | ext4_warning(dir->i_sb, "Unrecognised inode hash code %d", |
692 | root->info.hash_version); | 683 | root->info.hash_version); |
693 | brelse(bh); | ||
694 | *err = ERR_BAD_DX_DIR; | ||
695 | goto fail; | 684 | goto fail; |
696 | } | 685 | } |
697 | hinfo->hash_version = root->info.hash_version; | 686 | hinfo->hash_version = root->info.hash_version; |
@@ -705,16 +694,12 @@ dx_probe(const struct qstr *d_name, struct inode *dir, | |||
705 | if (root->info.unused_flags & 1) { | 694 | if (root->info.unused_flags & 1) { |
706 | ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x", | 695 | ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x", |
707 | root->info.unused_flags); | 696 | root->info.unused_flags); |
708 | brelse(bh); | ||
709 | *err = ERR_BAD_DX_DIR; | ||
710 | goto fail; | 697 | goto fail; |
711 | } | 698 | } |
712 | 699 | ||
713 | if ((indirect = root->info.indirect_levels) > 1) { | 700 | if ((indirect = root->info.indirect_levels) > 1) { |
714 | ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x", | 701 | ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x", |
715 | root->info.indirect_levels); | 702 | root->info.indirect_levels); |
716 | brelse(bh); | ||
717 | *err = ERR_BAD_DX_DIR; | ||
718 | goto fail; | 703 | goto fail; |
719 | } | 704 | } |
720 | 705 | ||
@@ -724,27 +709,21 @@ dx_probe(const struct qstr *d_name, struct inode *dir, | |||
724 | if (dx_get_limit(entries) != dx_root_limit(dir, | 709 | if (dx_get_limit(entries) != dx_root_limit(dir, |
725 | root->info.info_length)) { | 710 | root->info.info_length)) { |
726 | ext4_warning(dir->i_sb, "dx entry: limit != root limit"); | 711 | ext4_warning(dir->i_sb, "dx entry: limit != root limit"); |
727 | brelse(bh); | ||
728 | *err = ERR_BAD_DX_DIR; | ||
729 | goto fail; | 712 | goto fail; |
730 | } | 713 | } |
731 | 714 | ||
732 | dxtrace(printk("Look up %x", hash)); | 715 | dxtrace(printk("Look up %x", hash)); |
733 | while (1) | 716 | while (1) { |
734 | { | ||
735 | count = dx_get_count(entries); | 717 | count = dx_get_count(entries); |
736 | if (!count || count > dx_get_limit(entries)) { | 718 | if (!count || count > dx_get_limit(entries)) { |
737 | ext4_warning(dir->i_sb, | 719 | ext4_warning(dir->i_sb, |
738 | "dx entry: no count or count > limit"); | 720 | "dx entry: no count or count > limit"); |
739 | brelse(bh); | 721 | goto fail; |
740 | *err = ERR_BAD_DX_DIR; | ||
741 | goto fail2; | ||
742 | } | 722 | } |
743 | 723 | ||
744 | p = entries + 1; | 724 | p = entries + 1; |
745 | q = entries + count - 1; | 725 | q = entries + count - 1; |
746 | while (p <= q) | 726 | while (p <= q) { |
747 | { | ||
748 | m = p + (q - p)/2; | 727 | m = p + (q - p)/2; |
749 | dxtrace(printk(".")); | 728 | dxtrace(printk(".")); |
750 | if (dx_get_hash(m) > hash) | 729 | if (dx_get_hash(m) > hash) |
@@ -753,8 +732,7 @@ dx_probe(const struct qstr *d_name, struct inode *dir, | |||
753 | p = m + 1; | 732 | p = m + 1; |
754 | } | 733 | } |
755 | 734 | ||
756 | if (0) // linear search cross check | 735 | if (0) { // linear search cross check |
757 | { | ||
758 | unsigned n = count - 1; | 736 | unsigned n = count - 1; |
759 | at = entries; | 737 | at = entries; |
760 | while (n--) | 738 | while (n--) |
@@ -771,38 +749,35 @@ dx_probe(const struct qstr *d_name, struct inode *dir, | |||
771 | 749 | ||
772 | at = p - 1; | 750 | at = p - 1; |
773 | dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); | 751 | dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); |
774 | frame->bh = bh; | ||
775 | frame->entries = entries; | 752 | frame->entries = entries; |
776 | frame->at = at; | 753 | frame->at = at; |
777 | if (!indirect--) return frame; | 754 | if (!indirect--) |
778 | bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX); | 755 | return frame; |
779 | if (IS_ERR(bh)) { | 756 | frame++; |
780 | *err = PTR_ERR(bh); | 757 | frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX); |
781 | goto fail2; | 758 | if (IS_ERR(frame->bh)) { |
759 | ret_err = (struct dx_frame *) frame->bh; | ||
760 | frame->bh = NULL; | ||
761 | goto fail; | ||
782 | } | 762 | } |
783 | entries = ((struct dx_node *) bh->b_data)->entries; | 763 | entries = ((struct dx_node *) frame->bh->b_data)->entries; |
784 | 764 | ||
785 | if (dx_get_limit(entries) != dx_node_limit (dir)) { | 765 | if (dx_get_limit(entries) != dx_node_limit (dir)) { |
786 | ext4_warning(dir->i_sb, | 766 | ext4_warning(dir->i_sb, |
787 | "dx entry: limit != node limit"); | 767 | "dx entry: limit != node limit"); |
788 | brelse(bh); | 768 | goto fail; |
789 | *err = ERR_BAD_DX_DIR; | ||
790 | goto fail2; | ||
791 | } | 769 | } |
792 | frame++; | ||
793 | frame->bh = NULL; | ||
794 | } | 770 | } |
795 | fail2: | 771 | fail: |
796 | while (frame >= frame_in) { | 772 | while (frame >= frame_in) { |
797 | brelse(frame->bh); | 773 | brelse(frame->bh); |
798 | frame--; | 774 | frame--; |
799 | } | 775 | } |
800 | fail: | 776 | if (ret_err == ERR_PTR(ERR_BAD_DX_DIR)) |
801 | if (*err == ERR_BAD_DX_DIR) | ||
802 | ext4_warning(dir->i_sb, | 777 | ext4_warning(dir->i_sb, |
803 | "Corrupt dir inode %lu, running e2fsck is " | 778 | "Corrupt dir inode %lu, running e2fsck is " |
804 | "recommended.", dir->i_ino); | 779 | "recommended.", dir->i_ino); |
805 | return NULL; | 780 | return ret_err; |
806 | } | 781 | } |
807 | 782 | ||
808 | static void dx_release (struct dx_frame *frames) | 783 | static void dx_release (struct dx_frame *frames) |
@@ -988,9 +963,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, | |||
988 | } | 963 | } |
989 | hinfo.hash = start_hash; | 964 | hinfo.hash = start_hash; |
990 | hinfo.minor_hash = 0; | 965 | hinfo.minor_hash = 0; |
991 | frame = dx_probe(NULL, dir, &hinfo, frames, &err); | 966 | frame = dx_probe(NULL, dir, &hinfo, frames); |
992 | if (!frame) | 967 | if (IS_ERR(frame)) |
993 | return err; | 968 | return PTR_ERR(frame); |
994 | 969 | ||
995 | /* Add '.' and '..' from the htree header */ | 970 | /* Add '.' and '..' from the htree header */ |
996 | if (!start_hash && !start_minor_hash) { | 971 | if (!start_hash && !start_minor_hash) { |
@@ -1227,8 +1202,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, | |||
1227 | buffer */ | 1202 | buffer */ |
1228 | int num = 0; | 1203 | int num = 0; |
1229 | ext4_lblk_t nblocks; | 1204 | ext4_lblk_t nblocks; |
1230 | int i, err = 0; | 1205 | int i, namelen; |
1231 | int namelen; | ||
1232 | 1206 | ||
1233 | *res_dir = NULL; | 1207 | *res_dir = NULL; |
1234 | sb = dir->i_sb; | 1208 | sb = dir->i_sb; |
@@ -1258,17 +1232,13 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, | |||
1258 | goto restart; | 1232 | goto restart; |
1259 | } | 1233 | } |
1260 | if (is_dx(dir)) { | 1234 | if (is_dx(dir)) { |
1261 | bh = ext4_dx_find_entry(dir, d_name, res_dir, &err); | 1235 | bh = ext4_dx_find_entry(dir, d_name, res_dir); |
1262 | /* | 1236 | /* |
1263 | * On success, or if the error was file not found, | 1237 | * On success, or if the error was file not found, |
1264 | * return. Otherwise, fall back to doing a search the | 1238 | * return. Otherwise, fall back to doing a search the |
1265 | * old fashioned way. | 1239 | * old fashioned way. |
1266 | */ | 1240 | */ |
1267 | if (err == -ENOENT) | 1241 | if (!IS_ERR(bh) || PTR_ERR(bh) != ERR_BAD_DX_DIR) |
1268 | return NULL; | ||
1269 | if (err && err != ERR_BAD_DX_DIR) | ||
1270 | return ERR_PTR(err); | ||
1271 | if (bh) | ||
1272 | return bh; | 1242 | return bh; |
1273 | dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " | 1243 | dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " |
1274 | "falling back\n")); | 1244 | "falling back\n")); |
@@ -1298,10 +1268,10 @@ restart: | |||
1298 | break; | 1268 | break; |
1299 | } | 1269 | } |
1300 | num++; | 1270 | num++; |
1301 | bh = ext4_getblk(NULL, dir, b++, 0, &err); | 1271 | bh = ext4_getblk(NULL, dir, b++, 0); |
1302 | if (unlikely(err)) { | 1272 | if (unlikely(IS_ERR(bh))) { |
1303 | if (ra_max == 0) | 1273 | if (ra_max == 0) |
1304 | return ERR_PTR(err); | 1274 | return bh; |
1305 | break; | 1275 | break; |
1306 | } | 1276 | } |
1307 | bh_use[ra_max] = bh; | 1277 | bh_use[ra_max] = bh; |
@@ -1366,7 +1336,7 @@ cleanup_and_exit: | |||
1366 | } | 1336 | } |
1367 | 1337 | ||
1368 | static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name, | 1338 | static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name, |
1369 | struct ext4_dir_entry_2 **res_dir, int *err) | 1339 | struct ext4_dir_entry_2 **res_dir) |
1370 | { | 1340 | { |
1371 | struct super_block * sb = dir->i_sb; | 1341 | struct super_block * sb = dir->i_sb; |
1372 | struct dx_hash_info hinfo; | 1342 | struct dx_hash_info hinfo; |
@@ -1375,25 +1345,23 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q | |||
1375 | ext4_lblk_t block; | 1345 | ext4_lblk_t block; |
1376 | int retval; | 1346 | int retval; |
1377 | 1347 | ||
1378 | if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err))) | 1348 | frame = dx_probe(d_name, dir, &hinfo, frames); |
1379 | return NULL; | 1349 | if (IS_ERR(frame)) |
1350 | return (struct buffer_head *) frame; | ||
1380 | do { | 1351 | do { |
1381 | block = dx_get_block(frame->at); | 1352 | block = dx_get_block(frame->at); |
1382 | bh = ext4_read_dirblock(dir, block, DIRENT); | 1353 | bh = ext4_read_dirblock(dir, block, DIRENT); |
1383 | if (IS_ERR(bh)) { | 1354 | if (IS_ERR(bh)) |
1384 | *err = PTR_ERR(bh); | ||
1385 | goto errout; | 1355 | goto errout; |
1386 | } | 1356 | |
1387 | retval = search_dirblock(bh, dir, d_name, | 1357 | retval = search_dirblock(bh, dir, d_name, |
1388 | block << EXT4_BLOCK_SIZE_BITS(sb), | 1358 | block << EXT4_BLOCK_SIZE_BITS(sb), |
1389 | res_dir); | 1359 | res_dir); |
1390 | if (retval == 1) { /* Success! */ | 1360 | if (retval == 1) |
1391 | dx_release(frames); | 1361 | goto success; |
1392 | return bh; | ||
1393 | } | ||
1394 | brelse(bh); | 1362 | brelse(bh); |
1395 | if (retval == -1) { | 1363 | if (retval == -1) { |
1396 | *err = ERR_BAD_DX_DIR; | 1364 | bh = ERR_PTR(ERR_BAD_DX_DIR); |
1397 | goto errout; | 1365 | goto errout; |
1398 | } | 1366 | } |
1399 | 1367 | ||
@@ -1402,18 +1370,19 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q | |||
1402 | frames, NULL); | 1370 | frames, NULL); |
1403 | if (retval < 0) { | 1371 | if (retval < 0) { |
1404 | ext4_warning(sb, | 1372 | ext4_warning(sb, |
1405 | "error reading index page in directory #%lu", | 1373 | "error %d reading index page in directory #%lu", |
1406 | dir->i_ino); | 1374 | retval, dir->i_ino); |
1407 | *err = retval; | 1375 | bh = ERR_PTR(retval); |
1408 | goto errout; | 1376 | goto errout; |
1409 | } | 1377 | } |
1410 | } while (retval == 1); | 1378 | } while (retval == 1); |
1411 | 1379 | ||
1412 | *err = -ENOENT; | 1380 | bh = NULL; |
1413 | errout: | 1381 | errout: |
1414 | dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name)); | 1382 | dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name)); |
1415 | dx_release (frames); | 1383 | success: |
1416 | return NULL; | 1384 | dx_release(frames); |
1385 | return bh; | ||
1417 | } | 1386 | } |
1418 | 1387 | ||
1419 | static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | 1388 | static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
@@ -1441,7 +1410,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi | |||
1441 | dentry); | 1410 | dentry); |
1442 | return ERR_PTR(-EIO); | 1411 | return ERR_PTR(-EIO); |
1443 | } | 1412 | } |
1444 | inode = ext4_iget(dir->i_sb, ino); | 1413 | inode = ext4_iget_normal(dir->i_sb, ino); |
1445 | if (inode == ERR_PTR(-ESTALE)) { | 1414 | if (inode == ERR_PTR(-ESTALE)) { |
1446 | EXT4_ERROR_INODE(dir, | 1415 | EXT4_ERROR_INODE(dir, |
1447 | "deleted inode referenced: %u", | 1416 | "deleted inode referenced: %u", |
@@ -1474,7 +1443,7 @@ struct dentry *ext4_get_parent(struct dentry *child) | |||
1474 | return ERR_PTR(-EIO); | 1443 | return ERR_PTR(-EIO); |
1475 | } | 1444 | } |
1476 | 1445 | ||
1477 | return d_obtain_alias(ext4_iget(child->d_inode->i_sb, ino)); | 1446 | return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino)); |
1478 | } | 1447 | } |
1479 | 1448 | ||
1480 | /* | 1449 | /* |
@@ -1533,7 +1502,7 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize) | |||
1533 | */ | 1502 | */ |
1534 | static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | 1503 | static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, |
1535 | struct buffer_head **bh,struct dx_frame *frame, | 1504 | struct buffer_head **bh,struct dx_frame *frame, |
1536 | struct dx_hash_info *hinfo, int *error) | 1505 | struct dx_hash_info *hinfo) |
1537 | { | 1506 | { |
1538 | unsigned blocksize = dir->i_sb->s_blocksize; | 1507 | unsigned blocksize = dir->i_sb->s_blocksize; |
1539 | unsigned count, continued; | 1508 | unsigned count, continued; |
@@ -1548,16 +1517,14 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1548 | int csum_size = 0; | 1517 | int csum_size = 0; |
1549 | int err = 0, i; | 1518 | int err = 0, i; |
1550 | 1519 | ||
1551 | if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, | 1520 | if (ext4_has_metadata_csum(dir->i_sb)) |
1552 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
1553 | csum_size = sizeof(struct ext4_dir_entry_tail); | 1521 | csum_size = sizeof(struct ext4_dir_entry_tail); |
1554 | 1522 | ||
1555 | bh2 = ext4_append(handle, dir, &newblock); | 1523 | bh2 = ext4_append(handle, dir, &newblock); |
1556 | if (IS_ERR(bh2)) { | 1524 | if (IS_ERR(bh2)) { |
1557 | brelse(*bh); | 1525 | brelse(*bh); |
1558 | *bh = NULL; | 1526 | *bh = NULL; |
1559 | *error = PTR_ERR(bh2); | 1527 | return (struct ext4_dir_entry_2 *) bh2; |
1560 | return NULL; | ||
1561 | } | 1528 | } |
1562 | 1529 | ||
1563 | BUFFER_TRACE(*bh, "get_write_access"); | 1530 | BUFFER_TRACE(*bh, "get_write_access"); |
@@ -1617,8 +1584,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1617 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); | 1584 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); |
1618 | 1585 | ||
1619 | /* Which block gets the new entry? */ | 1586 | /* Which block gets the new entry? */ |
1620 | if (hinfo->hash >= hash2) | 1587 | if (hinfo->hash >= hash2) { |
1621 | { | ||
1622 | swap(*bh, bh2); | 1588 | swap(*bh, bh2); |
1623 | de = de2; | 1589 | de = de2; |
1624 | } | 1590 | } |
@@ -1638,8 +1604,7 @@ journal_error: | |||
1638 | brelse(bh2); | 1604 | brelse(bh2); |
1639 | *bh = NULL; | 1605 | *bh = NULL; |
1640 | ext4_std_error(dir->i_sb, err); | 1606 | ext4_std_error(dir->i_sb, err); |
1641 | *error = err; | 1607 | return ERR_PTR(err); |
1642 | return NULL; | ||
1643 | } | 1608 | } |
1644 | 1609 | ||
1645 | int ext4_find_dest_de(struct inode *dir, struct inode *inode, | 1610 | int ext4_find_dest_de(struct inode *dir, struct inode *inode, |
@@ -1718,8 +1683,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1718 | int csum_size = 0; | 1683 | int csum_size = 0; |
1719 | int err; | 1684 | int err; |
1720 | 1685 | ||
1721 | if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 1686 | if (ext4_has_metadata_csum(inode->i_sb)) |
1722 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
1723 | csum_size = sizeof(struct ext4_dir_entry_tail); | 1687 | csum_size = sizeof(struct ext4_dir_entry_tail); |
1724 | 1688 | ||
1725 | if (!de) { | 1689 | if (!de) { |
@@ -1786,8 +1750,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1786 | struct fake_dirent *fde; | 1750 | struct fake_dirent *fde; |
1787 | int csum_size = 0; | 1751 | int csum_size = 0; |
1788 | 1752 | ||
1789 | if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 1753 | if (ext4_has_metadata_csum(inode->i_sb)) |
1790 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
1791 | csum_size = sizeof(struct ext4_dir_entry_tail); | 1754 | csum_size = sizeof(struct ext4_dir_entry_tail); |
1792 | 1755 | ||
1793 | blocksize = dir->i_sb->s_blocksize; | 1756 | blocksize = dir->i_sb->s_blocksize; |
@@ -1862,8 +1825,8 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1862 | ext4_handle_dirty_dx_node(handle, dir, frame->bh); | 1825 | ext4_handle_dirty_dx_node(handle, dir, frame->bh); |
1863 | ext4_handle_dirty_dirent_node(handle, dir, bh); | 1826 | ext4_handle_dirty_dirent_node(handle, dir, bh); |
1864 | 1827 | ||
1865 | de = do_split(handle,dir, &bh, frame, &hinfo, &retval); | 1828 | de = do_split(handle,dir, &bh, frame, &hinfo); |
1866 | if (!de) { | 1829 | if (IS_ERR(de)) { |
1867 | /* | 1830 | /* |
1868 | * Even if the block split failed, we have to properly write | 1831 | * Even if the block split failed, we have to properly write |
1869 | * out all the changes we did so far. Otherwise we can end up | 1832 | * out all the changes we did so far. Otherwise we can end up |
@@ -1871,7 +1834,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1871 | */ | 1834 | */ |
1872 | ext4_mark_inode_dirty(handle, dir); | 1835 | ext4_mark_inode_dirty(handle, dir); |
1873 | dx_release(frames); | 1836 | dx_release(frames); |
1874 | return retval; | 1837 | return PTR_ERR(de); |
1875 | } | 1838 | } |
1876 | dx_release(frames); | 1839 | dx_release(frames); |
1877 | 1840 | ||
@@ -1904,8 +1867,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, | |||
1904 | ext4_lblk_t block, blocks; | 1867 | ext4_lblk_t block, blocks; |
1905 | int csum_size = 0; | 1868 | int csum_size = 0; |
1906 | 1869 | ||
1907 | if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 1870 | if (ext4_has_metadata_csum(inode->i_sb)) |
1908 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
1909 | csum_size = sizeof(struct ext4_dir_entry_tail); | 1871 | csum_size = sizeof(struct ext4_dir_entry_tail); |
1910 | 1872 | ||
1911 | sb = dir->i_sb; | 1873 | sb = dir->i_sb; |
@@ -1982,9 +1944,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1982 | struct ext4_dir_entry_2 *de; | 1944 | struct ext4_dir_entry_2 *de; |
1983 | int err; | 1945 | int err; |
1984 | 1946 | ||
1985 | frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err); | 1947 | frame = dx_probe(&dentry->d_name, dir, &hinfo, frames); |
1986 | if (!frame) | 1948 | if (IS_ERR(frame)) |
1987 | return err; | 1949 | return PTR_ERR(frame); |
1988 | entries = frame->entries; | 1950 | entries = frame->entries; |
1989 | at = frame->at; | 1951 | at = frame->at; |
1990 | bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT); | 1952 | bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT); |
@@ -2095,9 +2057,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
2095 | goto cleanup; | 2057 | goto cleanup; |
2096 | } | 2058 | } |
2097 | } | 2059 | } |
2098 | de = do_split(handle, dir, &bh, frame, &hinfo, &err); | 2060 | de = do_split(handle, dir, &bh, frame, &hinfo); |
2099 | if (!de) | 2061 | if (IS_ERR(de)) { |
2062 | err = PTR_ERR(de); | ||
2100 | goto cleanup; | 2063 | goto cleanup; |
2064 | } | ||
2101 | err = add_dirent_to_buf(handle, dentry, inode, de, bh); | 2065 | err = add_dirent_to_buf(handle, dentry, inode, de, bh); |
2102 | goto cleanup; | 2066 | goto cleanup; |
2103 | 2067 | ||
@@ -2167,8 +2131,7 @@ static int ext4_delete_entry(handle_t *handle, | |||
2167 | return err; | 2131 | return err; |
2168 | } | 2132 | } |
2169 | 2133 | ||
2170 | if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, | 2134 | if (ext4_has_metadata_csum(dir->i_sb)) |
2171 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
2172 | csum_size = sizeof(struct ext4_dir_entry_tail); | 2135 | csum_size = sizeof(struct ext4_dir_entry_tail); |
2173 | 2136 | ||
2174 | BUFFER_TRACE(bh, "get_write_access"); | 2137 | BUFFER_TRACE(bh, "get_write_access"); |
@@ -2387,8 +2350,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir, | |||
2387 | int csum_size = 0; | 2350 | int csum_size = 0; |
2388 | int err; | 2351 | int err; |
2389 | 2352 | ||
2390 | if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, | 2353 | if (ext4_has_metadata_csum(dir->i_sb)) |
2391 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
2392 | csum_size = sizeof(struct ext4_dir_entry_tail); | 2354 | csum_size = sizeof(struct ext4_dir_entry_tail); |
2393 | 2355 | ||
2394 | if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { | 2356 | if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { |
@@ -2403,10 +2365,6 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir, | |||
2403 | dir_block = ext4_append(handle, inode, &block); | 2365 | dir_block = ext4_append(handle, inode, &block); |
2404 | if (IS_ERR(dir_block)) | 2366 | if (IS_ERR(dir_block)) |
2405 | return PTR_ERR(dir_block); | 2367 | return PTR_ERR(dir_block); |
2406 | BUFFER_TRACE(dir_block, "get_write_access"); | ||
2407 | err = ext4_journal_get_write_access(handle, dir_block); | ||
2408 | if (err) | ||
2409 | goto out; | ||
2410 | de = (struct ext4_dir_entry_2 *)dir_block->b_data; | 2368 | de = (struct ext4_dir_entry_2 *)dir_block->b_data; |
2411 | ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0); | 2369 | ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0); |
2412 | set_nlink(inode, 2); | 2370 | set_nlink(inode, 2); |
@@ -2573,7 +2531,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode) | |||
2573 | int err = 0, rc; | 2531 | int err = 0, rc; |
2574 | bool dirty = false; | 2532 | bool dirty = false; |
2575 | 2533 | ||
2576 | if (!sbi->s_journal) | 2534 | if (!sbi->s_journal || is_bad_inode(inode)) |
2577 | return 0; | 2535 | return 0; |
2578 | 2536 | ||
2579 | WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) && | 2537 | WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) && |