diff options
-rw-r--r-- | fs/ext4/namei.c | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index bd87b7a66afb..6d600a69fc9d 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -74,6 +74,12 @@ static struct buffer_head *ext4_append(handle_t *handle, | |||
74 | bh = NULL; | 74 | bh = NULL; |
75 | } | 75 | } |
76 | } | 76 | } |
77 | if (!bh && !(*err)) { | ||
78 | *err = -EIO; | ||
79 | ext4_error(inode->i_sb, | ||
80 | "Directory hole detected on inode %lu\n", | ||
81 | inode->i_ino); | ||
82 | } | ||
77 | return bh; | 83 | return bh; |
78 | } | 84 | } |
79 | 85 | ||
@@ -601,8 +607,11 @@ dx_probe(const struct qstr *d_name, struct inode *dir, | |||
601 | u32 hash; | 607 | u32 hash; |
602 | 608 | ||
603 | frame->bh = NULL; | 609 | frame->bh = NULL; |
604 | if (!(bh = ext4_bread (NULL,dir, 0, 0, err))) | 610 | if (!(bh = ext4_bread(NULL, dir, 0, 0, err))) { |
611 | if (*err == 0) | ||
612 | *err = ERR_BAD_DX_DIR; | ||
605 | goto fail; | 613 | goto fail; |
614 | } | ||
606 | root = (struct dx_root *) bh->b_data; | 615 | root = (struct dx_root *) bh->b_data; |
607 | if (root->info.hash_version != DX_HASH_TEA && | 616 | if (root->info.hash_version != DX_HASH_TEA && |
608 | root->info.hash_version != DX_HASH_HALF_MD4 && | 617 | root->info.hash_version != DX_HASH_HALF_MD4 && |
@@ -703,8 +712,11 @@ dx_probe(const struct qstr *d_name, struct inode *dir, | |||
703 | frame->entries = entries; | 712 | frame->entries = entries; |
704 | frame->at = at; | 713 | frame->at = at; |
705 | if (!indirect--) return frame; | 714 | if (!indirect--) return frame; |
706 | if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err))) | 715 | if (!(bh = ext4_bread(NULL, dir, dx_get_block(at), 0, err))) { |
716 | if (!(*err)) | ||
717 | *err = ERR_BAD_DX_DIR; | ||
707 | goto fail2; | 718 | goto fail2; |
719 | } | ||
708 | at = entries = ((struct dx_node *) bh->b_data)->entries; | 720 | at = entries = ((struct dx_node *) bh->b_data)->entries; |
709 | 721 | ||
710 | if (!buffer_verified(bh) && | 722 | if (!buffer_verified(bh) && |
@@ -814,8 +826,15 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash, | |||
814 | */ | 826 | */ |
815 | while (num_frames--) { | 827 | while (num_frames--) { |
816 | if (!(bh = ext4_bread(NULL, dir, dx_get_block(p->at), | 828 | if (!(bh = ext4_bread(NULL, dir, dx_get_block(p->at), |
817 | 0, &err))) | 829 | 0, &err))) { |
830 | if (!err) { | ||
831 | ext4_error(dir->i_sb, | ||
832 | "Directory hole detected on inode %lu\n", | ||
833 | dir->i_ino); | ||
834 | return -EIO; | ||
835 | } | ||
818 | return err; /* Failure */ | 836 | return err; /* Failure */ |
837 | } | ||
819 | 838 | ||
820 | if (!buffer_verified(bh) && | 839 | if (!buffer_verified(bh) && |
821 | !ext4_dx_csum_verify(dir, | 840 | !ext4_dx_csum_verify(dir, |
@@ -850,8 +869,15 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
850 | 869 | ||
851 | dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", | 870 | dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", |
852 | (unsigned long)block)); | 871 | (unsigned long)block)); |
853 | if (!(bh = ext4_bread (NULL, dir, block, 0, &err))) | 872 | if (!(bh = ext4_bread(NULL, dir, block, 0, &err))) { |
873 | if (!err) { | ||
874 | err = -EIO; | ||
875 | ext4_error(dir->i_sb, | ||
876 | "Directory hole detected on inode %lu\n", | ||
877 | dir->i_ino); | ||
878 | } | ||
854 | return err; | 879 | return err; |
880 | } | ||
855 | 881 | ||
856 | if (!buffer_verified(bh) && | 882 | if (!buffer_verified(bh) && |
857 | !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data)) | 883 | !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data)) |
@@ -1274,8 +1300,15 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q | |||
1274 | return NULL; | 1300 | return NULL; |
1275 | do { | 1301 | do { |
1276 | block = dx_get_block(frame->at); | 1302 | block = dx_get_block(frame->at); |
1277 | if (!(bh = ext4_bread(NULL, dir, block, 0, err))) | 1303 | if (!(bh = ext4_bread(NULL, dir, block, 0, err))) { |
1304 | if (!(*err)) { | ||
1305 | *err = -EIO; | ||
1306 | ext4_error(dir->i_sb, | ||
1307 | "Directory hole detected on inode %lu\n", | ||
1308 | dir->i_ino); | ||
1309 | } | ||
1278 | goto errout; | 1310 | goto errout; |
1311 | } | ||
1279 | 1312 | ||
1280 | if (!buffer_verified(bh) && | 1313 | if (!buffer_verified(bh) && |
1281 | !ext4_dirent_csum_verify(dir, | 1314 | !ext4_dirent_csum_verify(dir, |
@@ -1808,9 +1841,15 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, | |||
1808 | } | 1841 | } |
1809 | blocks = dir->i_size >> sb->s_blocksize_bits; | 1842 | blocks = dir->i_size >> sb->s_blocksize_bits; |
1810 | for (block = 0; block < blocks; block++) { | 1843 | for (block = 0; block < blocks; block++) { |
1811 | bh = ext4_bread(handle, dir, block, 0, &retval); | 1844 | if (!(bh = ext4_bread(handle, dir, block, 0, &retval))) { |
1812 | if(!bh) | 1845 | if (!retval) { |
1846 | retval = -EIO; | ||
1847 | ext4_error(inode->i_sb, | ||
1848 | "Directory hole detected on inode %lu\n", | ||
1849 | inode->i_ino); | ||
1850 | } | ||
1813 | return retval; | 1851 | return retval; |
1852 | } | ||
1814 | if (!buffer_verified(bh) && | 1853 | if (!buffer_verified(bh) && |
1815 | !ext4_dirent_csum_verify(dir, | 1854 | !ext4_dirent_csum_verify(dir, |
1816 | (struct ext4_dir_entry *)bh->b_data)) | 1855 | (struct ext4_dir_entry *)bh->b_data)) |
@@ -1867,8 +1906,15 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1867 | entries = frame->entries; | 1906 | entries = frame->entries; |
1868 | at = frame->at; | 1907 | at = frame->at; |
1869 | 1908 | ||
1870 | if (!(bh = ext4_bread(handle,dir, dx_get_block(frame->at), 0, &err))) | 1909 | if (!(bh = ext4_bread(handle, dir, dx_get_block(frame->at), 0, &err))) { |
1910 | if (!err) { | ||
1911 | err = -EIO; | ||
1912 | ext4_error(dir->i_sb, | ||
1913 | "Directory hole detected on inode %lu\n", | ||
1914 | dir->i_ino); | ||
1915 | } | ||
1871 | goto cleanup; | 1916 | goto cleanup; |
1917 | } | ||
1872 | 1918 | ||
1873 | if (!buffer_verified(bh) && | 1919 | if (!buffer_verified(bh) && |
1874 | !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data)) | 1920 | !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data)) |
@@ -2204,9 +2250,15 @@ retry: | |||
2204 | inode->i_op = &ext4_dir_inode_operations; | 2250 | inode->i_op = &ext4_dir_inode_operations; |
2205 | inode->i_fop = &ext4_dir_operations; | 2251 | inode->i_fop = &ext4_dir_operations; |
2206 | inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; | 2252 | inode->i_size = EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; |
2207 | dir_block = ext4_bread(handle, inode, 0, 1, &err); | 2253 | if (!(dir_block = ext4_bread(handle, inode, 0, 1, &err))) { |
2208 | if (!dir_block) | 2254 | if (!err) { |
2255 | err = -EIO; | ||
2256 | ext4_error(inode->i_sb, | ||
2257 | "Directory hole detected on inode %lu\n", | ||
2258 | inode->i_ino); | ||
2259 | } | ||
2209 | goto out_clear_inode; | 2260 | goto out_clear_inode; |
2261 | } | ||
2210 | BUFFER_TRACE(dir_block, "get_write_access"); | 2262 | BUFFER_TRACE(dir_block, "get_write_access"); |
2211 | err = ext4_journal_get_write_access(handle, dir_block); | 2263 | err = ext4_journal_get_write_access(handle, dir_block); |
2212 | if (err) | 2264 | if (err) |
@@ -2323,6 +2375,11 @@ static int empty_dir(struct inode *inode) | |||
2323 | EXT4_ERROR_INODE(inode, | 2375 | EXT4_ERROR_INODE(inode, |
2324 | "error %d reading directory " | 2376 | "error %d reading directory " |
2325 | "lblock %u", err, lblock); | 2377 | "lblock %u", err, lblock); |
2378 | else | ||
2379 | ext4_warning(inode->i_sb, | ||
2380 | "bad directory (dir #%lu) - no data block", | ||
2381 | inode->i_ino); | ||
2382 | |||
2326 | offset += sb->s_blocksize; | 2383 | offset += sb->s_blocksize; |
2327 | continue; | 2384 | continue; |
2328 | } | 2385 | } |
@@ -2830,9 +2887,15 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2830 | goto end_rename; | 2887 | goto end_rename; |
2831 | } | 2888 | } |
2832 | retval = -EIO; | 2889 | retval = -EIO; |
2833 | dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval); | 2890 | if (!(dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval))) { |
2834 | if (!dir_bh) | 2891 | if (!retval) { |
2892 | retval = -EIO; | ||
2893 | ext4_error(old_inode->i_sb, | ||
2894 | "Directory hole detected on inode %lu\n", | ||
2895 | old_inode->i_ino); | ||
2896 | } | ||
2835 | goto end_rename; | 2897 | goto end_rename; |
2898 | } | ||
2836 | if (!buffer_verified(dir_bh) && | 2899 | if (!buffer_verified(dir_bh) && |
2837 | !ext4_dirent_csum_verify(old_inode, | 2900 | !ext4_dirent_csum_verify(old_inode, |
2838 | (struct ext4_dir_entry *)dir_bh->b_data)) | 2901 | (struct ext4_dir_entry *)dir_bh->b_data)) |