aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/namei.c291
1 files changed, 119 insertions, 172 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 3e1529c39808..0e28c749e273 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -83,6 +83,86 @@ static struct buffer_head *ext4_append(handle_t *handle,
83 return bh; 83 return bh;
84} 84}
85 85
86static int ext4_dx_csum_verify(struct inode *inode,
87 struct ext4_dir_entry *dirent);
88
89typedef enum {
90 EITHER, INDEX, DIRENT
91} dirblock_type_t;
92
93#define ext4_read_dirblock(inode, block, type) \
94 __ext4_read_dirblock((inode), (block), (type), __LINE__)
95
96static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
97 ext4_lblk_t block,
98 dirblock_type_t type,
99 unsigned int line)
100{
101 struct buffer_head *bh;
102 struct ext4_dir_entry *dirent;
103 int err = 0, is_dx_block = 0;
104
105 bh = ext4_bread(NULL, inode, block, 0, &err);
106 if (!bh) {
107 if (err == 0) {
108 ext4_error_inode(inode, __func__, line, block,
109 "Directory hole found");
110 return ERR_PTR(-EIO);
111 }
112 __ext4_warning(inode->i_sb, __func__, line,
113 "error reading directory block "
114 "(ino %lu, block %lu)", inode->i_ino,
115 (unsigned long) block);
116 return ERR_PTR(err);
117 }
118 dirent = (struct ext4_dir_entry *) bh->b_data;
119 /* Determine whether or not we have an index block */
120 if (is_dx(inode)) {
121 if (block == 0)
122 is_dx_block = 1;
123 else if (ext4_rec_len_from_disk(dirent->rec_len,
124 inode->i_sb->s_blocksize) ==
125 inode->i_sb->s_blocksize)
126 is_dx_block = 1;
127 }
128 if (!is_dx_block && type == INDEX) {
129 ext4_error_inode(inode, __func__, line, block,
130 "directory leaf block found instead of index block");
131 return ERR_PTR(-EIO);
132 }
133 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
134 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) ||
135 buffer_verified(bh))
136 return bh;
137
138 /*
139 * An empty leaf block can get mistaken for a index block; for
140 * this reason, we can only check the index checksum when the
141 * caller is sure it should be an index block.
142 */
143 if (is_dx_block && type == INDEX) {
144 if (ext4_dx_csum_verify(inode, dirent))
145 set_buffer_verified(bh);
146 else {
147 ext4_error_inode(inode, __func__, line, block,
148 "Directory index failed checksum");
149 brelse(bh);
150 return ERR_PTR(-EIO);
151 }
152 }
153 if (!is_dx_block) {
154 if (ext4_dirent_csum_verify(inode, dirent))
155 set_buffer_verified(bh);
156 else {
157 ext4_error_inode(inode, __func__, line, block,
158 "Directory block failed checksum");
159 brelse(bh);
160 return ERR_PTR(-EIO);
161 }
162 }
163 return bh;
164}
165
86#ifndef assert 166#ifndef assert
87#define assert(test) J_ASSERT(test) 167#define assert(test) J_ASSERT(test)
88#endif 168#endif
@@ -604,9 +684,9 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
604 u32 hash; 684 u32 hash;
605 685
606 frame->bh = NULL; 686 frame->bh = NULL;
607 if (!(bh = ext4_bread(NULL, dir, 0, 0, err))) { 687 bh = ext4_read_dirblock(dir, 0, INDEX);
608 if (*err == 0) 688 if (IS_ERR(bh)) {
609 *err = ERR_BAD_DX_DIR; 689 *err = PTR_ERR(bh);
610 goto fail; 690 goto fail;
611 } 691 }
612 root = (struct dx_root *) bh->b_data; 692 root = (struct dx_root *) bh->b_data;
@@ -643,15 +723,6 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
643 goto fail; 723 goto fail;
644 } 724 }
645 725
646 if (!buffer_verified(bh) &&
647 !ext4_dx_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data)) {
648 ext4_warning(dir->i_sb, "Root failed checksum");
649 brelse(bh);
650 *err = ERR_BAD_DX_DIR;
651 goto fail;
652 }
653 set_buffer_verified(bh);
654
655 entries = (struct dx_entry *) (((char *)&root->info) + 726 entries = (struct dx_entry *) (((char *)&root->info) +
656 root->info.info_length); 727 root->info.info_length);
657 728
@@ -709,23 +780,13 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
709 frame->entries = entries; 780 frame->entries = entries;
710 frame->at = at; 781 frame->at = at;
711 if (!indirect--) return frame; 782 if (!indirect--) return frame;
712 if (!(bh = ext4_bread(NULL, dir, dx_get_block(at), 0, err))) { 783 bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
713 if (!(*err)) 784 if (IS_ERR(bh)) {
714 *err = ERR_BAD_DX_DIR; 785 *err = PTR_ERR(bh);
715 goto fail2; 786 goto fail2;
716 } 787 }
717 entries = ((struct dx_node *) bh->b_data)->entries; 788 entries = ((struct dx_node *) bh->b_data)->entries;
718 789
719 if (!buffer_verified(bh) &&
720 !ext4_dx_csum_verify(dir,
721 (struct ext4_dir_entry *)bh->b_data)) {
722 ext4_warning(dir->i_sb, "Node failed checksum");
723 brelse(bh);
724 *err = ERR_BAD_DX_DIR;
725 goto fail2;
726 }
727 set_buffer_verified(bh);
728
729 if (dx_get_limit(entries) != dx_node_limit (dir)) { 790 if (dx_get_limit(entries) != dx_node_limit (dir)) {
730 ext4_warning(dir->i_sb, 791 ext4_warning(dir->i_sb,
731 "dx entry: limit != node limit"); 792 "dx entry: limit != node limit");
@@ -783,7 +844,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
783{ 844{
784 struct dx_frame *p; 845 struct dx_frame *p;
785 struct buffer_head *bh; 846 struct buffer_head *bh;
786 int err, num_frames = 0; 847 int num_frames = 0;
787 __u32 bhash; 848 __u32 bhash;
788 849
789 p = frame; 850 p = frame;
@@ -822,26 +883,9 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
822 * block so no check is necessary 883 * block so no check is necessary
823 */ 884 */
824 while (num_frames--) { 885 while (num_frames--) {
825 if (!(bh = ext4_bread(NULL, dir, dx_get_block(p->at), 886 bh = ext4_read_dirblock(dir, dx_get_block(p->at), INDEX);
826 0, &err))) { 887 if (IS_ERR(bh))
827 if (!err) { 888 return PTR_ERR(bh);
828 ext4_error(dir->i_sb,
829 "Directory hole detected on inode %lu\n",
830 dir->i_ino);
831 return -EIO;
832 }
833 return err; /* Failure */
834 }
835
836 if (!buffer_verified(bh) &&
837 !ext4_dx_csum_verify(dir,
838 (struct ext4_dir_entry *)bh->b_data)) {
839 ext4_warning(dir->i_sb, "Node failed checksum");
840 brelse(bh);
841 return -EIO;
842 }
843 set_buffer_verified(bh);
844
845 p++; 889 p++;
846 brelse(p->bh); 890 brelse(p->bh);
847 p->bh = bh; 891 p->bh = bh;
@@ -867,23 +911,9 @@ static int htree_dirblock_to_tree(struct file *dir_file,
867 911
868 dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", 912 dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
869 (unsigned long)block)); 913 (unsigned long)block));
870 if (!(bh = ext4_bread(NULL, dir, block, 0, &err))) { 914 bh = ext4_read_dirblock(dir, block, DIRENT);
871 if (!err) { 915 if (IS_ERR(bh))
872 err = -EIO; 916 return PTR_ERR(bh);
873 ext4_error(dir->i_sb,
874 "Directory hole detected on inode %lu\n",
875 dir->i_ino);
876 }
877 return err;
878 }
879
880 if (!buffer_verified(bh) &&
881 !ext4_dirent_csum_verify(dir,
882 (struct ext4_dir_entry *)bh->b_data)) {
883 brelse(bh);
884 return -EIO;
885 }
886 set_buffer_verified(bh);
887 917
888 de = (struct ext4_dir_entry_2 *) bh->b_data; 918 de = (struct ext4_dir_entry_2 *) bh->b_data;
889 top = (struct ext4_dir_entry_2 *) ((char *) de + 919 top = (struct ext4_dir_entry_2 *) ((char *) de +
@@ -1337,26 +1367,11 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
1337 return NULL; 1367 return NULL;
1338 do { 1368 do {
1339 block = dx_get_block(frame->at); 1369 block = dx_get_block(frame->at);
1340 if (!(bh = ext4_bread(NULL, dir, block, 0, err))) { 1370 bh = ext4_read_dirblock(dir, block, DIRENT);
1341 if (!(*err)) { 1371 if (IS_ERR(bh)) {
1342 *err = -EIO; 1372 *err = PTR_ERR(bh);
1343 ext4_error(dir->i_sb,
1344 "Directory hole detected on inode %lu\n",
1345 dir->i_ino);
1346 }
1347 goto errout; 1373 goto errout;
1348 } 1374 }
1349
1350 if (!buffer_verified(bh) &&
1351 !ext4_dirent_csum_verify(dir,
1352 (struct ext4_dir_entry *)bh->b_data)) {
1353 EXT4_ERROR_INODE(dir, "checksumming directory "
1354 "block %lu", (unsigned long)block);
1355 brelse(bh);
1356 *err = -EIO;
1357 goto errout;
1358 }
1359 set_buffer_verified(bh);
1360 retval = search_dirblock(bh, dir, d_name, 1375 retval = search_dirblock(bh, dir, d_name,
1361 block << EXT4_BLOCK_SIZE_BITS(sb), 1376 block << EXT4_BLOCK_SIZE_BITS(sb),
1362 res_dir); 1377 res_dir);
@@ -1920,22 +1935,10 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
1920 } 1935 }
1921 blocks = dir->i_size >> sb->s_blocksize_bits; 1936 blocks = dir->i_size >> sb->s_blocksize_bits;
1922 for (block = 0; block < blocks; block++) { 1937 for (block = 0; block < blocks; block++) {
1923 if (!(bh = ext4_bread(handle, dir, block, 0, &retval))) { 1938 bh = ext4_read_dirblock(dir, block, DIRENT);
1924 if (!retval) { 1939 if (IS_ERR(bh))
1925 retval = -EIO; 1940 return PTR_ERR(bh);
1926 ext4_error(inode->i_sb, 1941
1927 "Directory hole detected on inode %lu\n",
1928 inode->i_ino);
1929 }
1930 return retval;
1931 }
1932 if (!buffer_verified(bh) &&
1933 !ext4_dirent_csum_verify(dir,
1934 (struct ext4_dir_entry *)bh->b_data)) {
1935 brelse(bh);
1936 return -EIO;
1937 }
1938 set_buffer_verified(bh);
1939 retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); 1942 retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
1940 if (retval != -ENOSPC) { 1943 if (retval != -ENOSPC) {
1941 brelse(bh); 1944 brelse(bh);
@@ -1986,22 +1989,13 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
1986 return err; 1989 return err;
1987 entries = frame->entries; 1990 entries = frame->entries;
1988 at = frame->at; 1991 at = frame->at;
1989 1992 bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
1990 if (!(bh = ext4_bread(handle, dir, dx_get_block(frame->at), 0, &err))) { 1993 if (IS_ERR(bh)) {
1991 if (!err) { 1994 err = PTR_ERR(bh);
1992 err = -EIO; 1995 bh = NULL;
1993 ext4_error(dir->i_sb,
1994 "Directory hole detected on inode %lu\n",
1995 dir->i_ino);
1996 }
1997 goto cleanup; 1996 goto cleanup;
1998 } 1997 }
1999 1998
2000 if (!buffer_verified(bh) &&
2001 !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data))
2002 goto journal_error;
2003 set_buffer_verified(bh);
2004
2005 BUFFER_TRACE(bh, "get_write_access"); 1999 BUFFER_TRACE(bh, "get_write_access");
2006 err = ext4_journal_get_write_access(handle, bh); 2000 err = ext4_journal_get_write_access(handle, bh);
2007 if (err) 2001 if (err)
@@ -2352,6 +2346,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
2352 struct buffer_head *dir_block = NULL; 2346 struct buffer_head *dir_block = NULL;
2353 struct ext4_dir_entry_2 *de; 2347 struct ext4_dir_entry_2 *de;
2354 struct ext4_dir_entry_tail *t; 2348 struct ext4_dir_entry_tail *t;
2349 ext4_lblk_t block = 0;
2355 unsigned int blocksize = dir->i_sb->s_blocksize; 2350 unsigned int blocksize = dir->i_sb->s_blocksize;
2356 int csum_size = 0; 2351 int csum_size = 0;
2357 int err; 2352 int err;
@@ -2368,16 +2363,9 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
2368 goto out; 2363 goto out;
2369 } 2364 }
2370 2365
2371 inode->i_size = EXT4_I(inode)->i_disksize = blocksize; 2366 inode->i_size = 0;
2372 if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) { 2367 if (!(dir_block = ext4_append(handle, inode, &block, &err)))
2373 if (!err) {
2374 err = -EIO;
2375 ext4_error(inode->i_sb,
2376 "Directory hole detected on inode %lu\n",
2377 inode->i_ino);
2378 }
2379 goto out; 2368 goto out;
2380 }
2381 BUFFER_TRACE(dir_block, "get_write_access"); 2369 BUFFER_TRACE(dir_block, "get_write_access");
2382 err = ext4_journal_get_write_access(handle, dir_block); 2370 err = ext4_journal_get_write_access(handle, dir_block);
2383 if (err) 2371 if (err)
@@ -2477,26 +2465,14 @@ static int empty_dir(struct inode *inode)
2477 } 2465 }
2478 2466
2479 sb = inode->i_sb; 2467 sb = inode->i_sb;
2480 if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) || 2468 if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2)) {
2481 !(bh = ext4_bread(NULL, inode, 0, 0, &err))) { 2469 EXT4_ERROR_INODE(inode, "invalid size");
2482 if (err)
2483 EXT4_ERROR_INODE(inode,
2484 "error %d reading directory lblock 0", err);
2485 else
2486 ext4_warning(inode->i_sb,
2487 "bad directory (dir #%lu) - no data block",
2488 inode->i_ino);
2489 return 1; 2470 return 1;
2490 } 2471 }
2491 if (!buffer_verified(bh) && 2472 bh = ext4_read_dirblock(inode, 0, EITHER);
2492 !ext4_dirent_csum_verify(inode, 2473 if (IS_ERR(bh))
2493 (struct ext4_dir_entry *)bh->b_data)) { 2474 return 1;
2494 EXT4_ERROR_INODE(inode, "checksum error reading directory " 2475
2495 "lblock 0");
2496 brelse(bh);
2497 return -EIO;
2498 }
2499 set_buffer_verified(bh);
2500 de = (struct ext4_dir_entry_2 *) bh->b_data; 2476 de = (struct ext4_dir_entry_2 *) bh->b_data;
2501 de1 = ext4_next_entry(de, sb->s_blocksize); 2477 de1 = ext4_next_entry(de, sb->s_blocksize);
2502 if (le32_to_cpu(de->inode) != inode->i_ino || 2478 if (le32_to_cpu(de->inode) != inode->i_ino ||
@@ -2519,29 +2495,9 @@ static int empty_dir(struct inode *inode)
2519 err = 0; 2495 err = 0;
2520 brelse(bh); 2496 brelse(bh);
2521 lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb); 2497 lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
2522 bh = ext4_bread(NULL, inode, lblock, 0, &err); 2498 bh = ext4_read_dirblock(inode, lblock, EITHER);
2523 if (!bh) { 2499 if (IS_ERR(bh))
2524 if (err) 2500 return 1;
2525 EXT4_ERROR_INODE(inode,
2526 "error %d reading directory "
2527 "lblock %u", err, lblock);
2528 else
2529 ext4_warning(inode->i_sb,
2530 "bad directory (dir #%lu) - no data block",
2531 inode->i_ino);
2532
2533 offset += sb->s_blocksize;
2534 continue;
2535 }
2536 if (!buffer_verified(bh) &&
2537 !ext4_dirent_csum_verify(inode,
2538 (struct ext4_dir_entry *)bh->b_data)) {
2539 EXT4_ERROR_INODE(inode, "checksum error "
2540 "reading directory lblock 0");
2541 brelse(bh);
2542 return -EIO;
2543 }
2544 set_buffer_verified(bh);
2545 de = (struct ext4_dir_entry_2 *) bh->b_data; 2501 de = (struct ext4_dir_entry_2 *) bh->b_data;
2546 } 2502 }
2547 if (ext4_check_dir_entry(inode, NULL, de, bh, 2503 if (ext4_check_dir_entry(inode, NULL, de, bh,
@@ -3004,13 +2960,9 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
3004 struct buffer_head *bh; 2960 struct buffer_head *bh;
3005 2961
3006 if (!ext4_has_inline_data(inode)) { 2962 if (!ext4_has_inline_data(inode)) {
3007 if (!(bh = ext4_bread(handle, inode, 0, 0, retval))) { 2963 bh = ext4_read_dirblock(inode, 0, EITHER);
3008 if (!*retval) { 2964 if (IS_ERR(bh)) {
3009 *retval = -EIO; 2965 *retval = PTR_ERR(bh);
3010 ext4_error(inode->i_sb,
3011 "Directory hole detected on inode %lu\n",
3012 inode->i_ino);
3013 }
3014 return NULL; 2966 return NULL;
3015 } 2967 }
3016 *parent_de = ext4_next_entry( 2968 *parent_de = ext4_next_entry(
@@ -3089,11 +3041,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3089 &inlined); 3041 &inlined);
3090 if (!dir_bh) 3042 if (!dir_bh)
3091 goto end_rename; 3043 goto end_rename;
3092 if (!inlined && !buffer_verified(dir_bh) &&
3093 !ext4_dirent_csum_verify(old_inode,
3094 (struct ext4_dir_entry *)dir_bh->b_data))
3095 goto end_rename;
3096 set_buffer_verified(dir_bh);
3097 if (le32_to_cpu(parent_de->inode) != old_dir->i_ino) 3044 if (le32_to_cpu(parent_de->inode) != old_dir->i_ino)
3098 goto end_rename; 3045 goto end_rename;
3099 retval = -EMLINK; 3046 retval = -EMLINK;