diff options
-rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
-rw-r--r-- | fs/ext4/namei.c | 35 |
2 files changed, 34 insertions, 3 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 5b19760b1de5..4d95c3301775 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1825,7 +1825,7 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no) | |||
1825 | /* | 1825 | /* |
1826 | * Special error return code only used by dx_probe() and its callers. | 1826 | * Special error return code only used by dx_probe() and its callers. |
1827 | */ | 1827 | */ |
1828 | #define ERR_BAD_DX_DIR -75000 | 1828 | #define ERR_BAD_DX_DIR (-(MAX_ERRNO - 1)) |
1829 | 1829 | ||
1830 | /* | 1830 | /* |
1831 | * Timeout and state flag for lazy initialization inode thread. | 1831 | * Timeout and state flag for lazy initialization inode thread. |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index b147a67baa0d..ae7088b446d1 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1227,7 +1227,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, | |||
1227 | buffer */ | 1227 | buffer */ |
1228 | int num = 0; | 1228 | int num = 0; |
1229 | ext4_lblk_t nblocks; | 1229 | ext4_lblk_t nblocks; |
1230 | int i, err; | 1230 | int i, err = 0; |
1231 | int namelen; | 1231 | int namelen; |
1232 | 1232 | ||
1233 | *res_dir = NULL; | 1233 | *res_dir = NULL; |
@@ -1264,7 +1264,11 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, | |||
1264 | * return. Otherwise, fall back to doing a search the | 1264 | * return. Otherwise, fall back to doing a search the |
1265 | * old fashioned way. | 1265 | * old fashioned way. |
1266 | */ | 1266 | */ |
1267 | if (bh || (err != ERR_BAD_DX_DIR)) | 1267 | if (err == -ENOENT) |
1268 | return NULL; | ||
1269 | if (err && err != ERR_BAD_DX_DIR) | ||
1270 | return ERR_PTR(err); | ||
1271 | if (bh) | ||
1268 | return bh; | 1272 | return bh; |
1269 | dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " | 1273 | dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " |
1270 | "falling back\n")); | 1274 | "falling back\n")); |
@@ -1295,6 +1299,11 @@ restart: | |||
1295 | } | 1299 | } |
1296 | num++; | 1300 | num++; |
1297 | bh = ext4_getblk(NULL, dir, b++, 0, &err); | 1301 | bh = ext4_getblk(NULL, dir, b++, 0, &err); |
1302 | if (unlikely(err)) { | ||
1303 | if (ra_max == 0) | ||
1304 | return ERR_PTR(err); | ||
1305 | break; | ||
1306 | } | ||
1298 | bh_use[ra_max] = bh; | 1307 | bh_use[ra_max] = bh; |
1299 | if (bh) | 1308 | if (bh) |
1300 | ll_rw_block(READ | REQ_META | REQ_PRIO, | 1309 | ll_rw_block(READ | REQ_META | REQ_PRIO, |
@@ -1417,6 +1426,8 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi | |||
1417 | return ERR_PTR(-ENAMETOOLONG); | 1426 | return ERR_PTR(-ENAMETOOLONG); |
1418 | 1427 | ||
1419 | bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); | 1428 | bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); |
1429 | if (IS_ERR(bh)) | ||
1430 | return (struct dentry *) bh; | ||
1420 | inode = NULL; | 1431 | inode = NULL; |
1421 | if (bh) { | 1432 | if (bh) { |
1422 | __u32 ino = le32_to_cpu(de->inode); | 1433 | __u32 ino = le32_to_cpu(de->inode); |
@@ -1450,6 +1461,8 @@ struct dentry *ext4_get_parent(struct dentry *child) | |||
1450 | struct buffer_head *bh; | 1461 | struct buffer_head *bh; |
1451 | 1462 | ||
1452 | bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL); | 1463 | bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL); |
1464 | if (IS_ERR(bh)) | ||
1465 | return (struct dentry *) bh; | ||
1453 | if (!bh) | 1466 | if (!bh) |
1454 | return ERR_PTR(-ENOENT); | 1467 | return ERR_PTR(-ENOENT); |
1455 | ino = le32_to_cpu(de->inode); | 1468 | ino = le32_to_cpu(de->inode); |
@@ -2727,6 +2740,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) | |||
2727 | 2740 | ||
2728 | retval = -ENOENT; | 2741 | retval = -ENOENT; |
2729 | bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); | 2742 | bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); |
2743 | if (IS_ERR(bh)) | ||
2744 | return PTR_ERR(bh); | ||
2730 | if (!bh) | 2745 | if (!bh) |
2731 | goto end_rmdir; | 2746 | goto end_rmdir; |
2732 | 2747 | ||
@@ -2794,6 +2809,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) | |||
2794 | 2809 | ||
2795 | retval = -ENOENT; | 2810 | retval = -ENOENT; |
2796 | bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); | 2811 | bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); |
2812 | if (IS_ERR(bh)) | ||
2813 | return PTR_ERR(bh); | ||
2797 | if (!bh) | 2814 | if (!bh) |
2798 | goto end_unlink; | 2815 | goto end_unlink; |
2799 | 2816 | ||
@@ -3121,6 +3138,8 @@ static int ext4_find_delete_entry(handle_t *handle, struct inode *dir, | |||
3121 | struct ext4_dir_entry_2 *de; | 3138 | struct ext4_dir_entry_2 *de; |
3122 | 3139 | ||
3123 | bh = ext4_find_entry(dir, d_name, &de, NULL); | 3140 | bh = ext4_find_entry(dir, d_name, &de, NULL); |
3141 | if (IS_ERR(bh)) | ||
3142 | return PTR_ERR(bh); | ||
3124 | if (bh) { | 3143 | if (bh) { |
3125 | retval = ext4_delete_entry(handle, dir, de, bh); | 3144 | retval = ext4_delete_entry(handle, dir, de, bh); |
3126 | brelse(bh); | 3145 | brelse(bh); |
@@ -3202,6 +3221,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3202 | dquot_initialize(new.inode); | 3221 | dquot_initialize(new.inode); |
3203 | 3222 | ||
3204 | old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); | 3223 | old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); |
3224 | if (IS_ERR(old.bh)) | ||
3225 | return PTR_ERR(old.bh); | ||
3205 | /* | 3226 | /* |
3206 | * Check for inode number is _not_ due to possible IO errors. | 3227 | * Check for inode number is _not_ due to possible IO errors. |
3207 | * We might rmdir the source, keep it as pwd of some process | 3228 | * We might rmdir the source, keep it as pwd of some process |
@@ -3214,6 +3235,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3214 | 3235 | ||
3215 | new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, | 3236 | new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, |
3216 | &new.de, &new.inlined); | 3237 | &new.de, &new.inlined); |
3238 | if (IS_ERR(new.bh)) { | ||
3239 | retval = PTR_ERR(new.bh); | ||
3240 | goto end_rename; | ||
3241 | } | ||
3217 | if (new.bh) { | 3242 | if (new.bh) { |
3218 | if (!new.inode) { | 3243 | if (!new.inode) { |
3219 | brelse(new.bh); | 3244 | brelse(new.bh); |
@@ -3330,6 +3355,8 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3330 | 3355 | ||
3331 | old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, | 3356 | old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, |
3332 | &old.de, &old.inlined); | 3357 | &old.de, &old.inlined); |
3358 | if (IS_ERR(old.bh)) | ||
3359 | return PTR_ERR(old.bh); | ||
3333 | /* | 3360 | /* |
3334 | * Check for inode number is _not_ due to possible IO errors. | 3361 | * Check for inode number is _not_ due to possible IO errors. |
3335 | * We might rmdir the source, keep it as pwd of some process | 3362 | * We might rmdir the source, keep it as pwd of some process |
@@ -3342,6 +3369,10 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
3342 | 3369 | ||
3343 | new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, | 3370 | new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, |
3344 | &new.de, &new.inlined); | 3371 | &new.de, &new.inlined); |
3372 | if (IS_ERR(new.bh)) { | ||
3373 | retval = PTR_ERR(new.bh); | ||
3374 | goto end_rename; | ||
3375 | } | ||
3345 | 3376 | ||
3346 | /* RENAME_EXCHANGE case: old *and* new must both exist */ | 3377 | /* RENAME_EXCHANGE case: old *and* new must both exist */ |
3347 | if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino) | 3378 | if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino) |