add patch propagate-errors-up-to-ext4_find_entry-s-callers
[ext4-patch-queue.git] / propagate-errors-up-to-ext4_find_entry-s-callers
blob727a9d83b21f3612930f1606de829615222a5fe6
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
17 ---
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
23 --- a/fs/ext4/namei.c
24 +++ b/fs/ext4/namei.c
25 @@ -1227,7 +1227,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
26                                    buffer */
27         int num = 0;
28         ext4_lblk_t  nblocks;
29 -       int i, err;
30 +       int i, err = 0;
31         int namelen;
33         *res_dir = NULL;
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
36                  * old fashioned way.
37                  */
38 -               if (bh || (err != ERR_BAD_DX_DIR))
39 +               if (err == -ENOENT)
40 +                       return NULL;
41 +               if (err && err != ERR_BAD_DX_DIR)
42 +                       return ERR_PTR(err);
43 +               if (bh)
44                         return bh;
45                 dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
46                                "falling back\n"));
47 @@ -1295,6 +1299,11 @@ restart:
48                                 }
49                                 num++;
50                                 bh = ext4_getblk(NULL, dir, b++, 0, &err);
51 +                               if (unlikely(err)) {
52 +                                       if (ra_max == 0)
53 +                                               return ERR_PTR(err);
54 +                                       break;
55 +                               }
56                                 bh_use[ra_max] = bh;
57                                 if (bh)
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);
63 +       if (IS_ERR(bh))
64 +               return (struct dentry *) bh;
65         inode = NULL;
66         if (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);
72 +       if (IS_ERR(bh))
73 +               return (struct dentry *) bh;
74         if (!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)
79         retval = -ENOENT;
80         bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
81 +       if (IS_ERR(bh))
82 +               return PTR_ERR(bh);
83         if (!bh)
84                 goto end_rmdir;
86 @@ -2794,6 +2809,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
88         retval = -ENOENT;
89         bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
90 +       if (IS_ERR(bh))
91 +               return PTR_ERR(bh);
92         if (!bh)
93                 goto end_unlink;
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);
99 +       if (IS_ERR(bh))
100 +               return PTR_ERR(bh);
101         if (bh) {
102                 retval = ext4_delete_entry(handle, dir, de, bh);
103                 brelse(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);
110         /*
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);
119 +               goto end_rename;
120 +       }
121         if (new.bh) {
122                 if (!new.inode) {
123                         brelse(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);
130         /*
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);
139 +               goto end_rename;
140 +       }
142         /* RENAME_EXCHANGE case: old *and* new must both exist */
143         if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino)
144 -- 
145 2.1.0