1 ext4: propagate errors up to ext4_find_entry()'s callers
3 If we run into some kind of error, such as ENOMEM, while calling
4 ext4_getblk() or ext4_dx_find_entry(), we need to make sure this error
5 gets propagated up to ext4_find_entry() and then to its callers. This
6 way, transient errors such as ENOMEM can get propagated to the VFS.
7 This is important so that the system calls return the appropriate
8 error, and also so that in the case of ext4_lookup(), we return an
9 error instead of a NULL inode, since that will result in a negative
10 dentry cache entry that will stick around long past the OOM condition
11 which caused a transient ENOMEM error.
13 Google-Bug-Id: #17142205
15 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
16 Cc: stable@vger.kernel.org
18 fs/ext4/namei.c | 35 +++++++++++++++++++++++++++++++++--
19 1 file changed, 33 insertions(+), 2 deletions(-)
21 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
22 index b147a67..ae7088b 100644
25 @@ -1227,7 +1227,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
34 @@ -1264,7 +1264,11 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
35 * return. Otherwise, fall back to doing a search the
38 - if (bh || (err != ERR_BAD_DX_DIR))
41 + if (err && err != ERR_BAD_DX_DIR)
42 + return ERR_PTR(err);
45 dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
47 @@ -1295,6 +1299,11 @@ restart:
50 bh = ext4_getblk(NULL, dir, b++, 0, &err);
51 + if (unlikely(err)) {
53 + return ERR_PTR(err);
58 ll_rw_block(READ | REQ_META | REQ_PRIO,
59 @@ -1417,6 +1426,8 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
60 return ERR_PTR(-ENAMETOOLONG);
62 bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
64 + return (struct dentry *) bh;
67 __u32 ino = le32_to_cpu(de->inode);
68 @@ -1450,6 +1461,8 @@ struct dentry *ext4_get_parent(struct dentry *child)
69 struct buffer_head *bh;
71 bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL);
73 + return (struct dentry *) bh;
75 return ERR_PTR(-ENOENT);
76 ino = le32_to_cpu(de->inode);
77 @@ -2727,6 +2740,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
80 bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
86 @@ -2794,6 +2809,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
89 bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
95 @@ -3121,6 +3138,8 @@ static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
96 struct ext4_dir_entry_2 *de;
98 bh = ext4_find_entry(dir, d_name, &de, NULL);
100 + return PTR_ERR(bh);
102 retval = ext4_delete_entry(handle, dir, de, bh);
104 @@ -3202,6 +3221,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
105 dquot_initialize(new.inode);
107 old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
108 + if (IS_ERR(old.bh))
109 + return PTR_ERR(old.bh);
111 * Check for inode number is _not_ due to possible IO errors.
112 * We might rmdir the source, keep it as pwd of some process
113 @@ -3214,6 +3235,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
115 new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
116 &new.de, &new.inlined);
117 + if (IS_ERR(new.bh)) {
118 + retval = PTR_ERR(new.bh);
124 @@ -3330,6 +3355,8 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
126 old.bh = ext4_find_entry(old.dir, &old.dentry->d_name,
127 &old.de, &old.inlined);
128 + if (IS_ERR(old.bh))
129 + return PTR_ERR(old.bh);
131 * Check for inode number is _not_ due to possible IO errors.
132 * We might rmdir the source, keep it as pwd of some process
133 @@ -3342,6 +3369,10 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
135 new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
136 &new.de, &new.inlined);
137 + if (IS_ERR(new.bh)) {
138 + retval = PTR_ERR(new.bh);
142 /* RENAME_EXCHANGE case: old *and* new must both exist */
143 if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino)