Update propagate-errors-up-to-ext4_find_entry-s-callers to define
[ext4-patch-queue.git] / propagate-errors-up-to-ext4_find_entry-s-callers
blob9e149a156d013dd7d3304b58b8a081014fa2ae89
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/ext4.h  |  2 +-
19  fs/ext4/namei.c | 35 +++++++++++++++++++++++++++++++++--
20  2 files changed, 34 insertions(+), 3 deletions(-)
22 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
23 index 5b19760..4d95c33 100644
24 --- a/fs/ext4/ext4.h
25 +++ b/fs/ext4/ext4.h
26 @@ -1825,7 +1825,7 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
27  /*
28   * Special error return code only used by dx_probe() and its callers.
29   */
30 -#define ERR_BAD_DX_DIR -75000
31 +#define ERR_BAD_DX_DIR (-(MAX_ERRNO - 1))
33  /*
34   * Timeout and state flag for lazy initialization inode thread.
35 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
36 index b147a67..ae7088b 100644
37 --- a/fs/ext4/namei.c
38 +++ b/fs/ext4/namei.c
39 @@ -1227,7 +1227,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
40                                    buffer */
41         int num = 0;
42         ext4_lblk_t  nblocks;
43 -       int i, err;
44 +       int i, err = 0;
45         int namelen;
47         *res_dir = NULL;
48 @@ -1264,7 +1264,11 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
49                  * return.  Otherwise, fall back to doing a search the
50                  * old fashioned way.
51                  */
52 -               if (bh || (err != ERR_BAD_DX_DIR))
53 +               if (err == -ENOENT)
54 +                       return NULL;
55 +               if (err && err != ERR_BAD_DX_DIR)
56 +                       return ERR_PTR(err);
57 +               if (bh)
58                         return bh;
59                 dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
60                                "falling back\n"));
61 @@ -1295,6 +1299,11 @@ restart:
62                                 }
63                                 num++;
64                                 bh = ext4_getblk(NULL, dir, b++, 0, &err);
65 +                               if (unlikely(err)) {
66 +                                       if (ra_max == 0)
67 +                                               return ERR_PTR(err);
68 +                                       break;
69 +                               }
70                                 bh_use[ra_max] = bh;
71                                 if (bh)
72                                         ll_rw_block(READ | REQ_META | REQ_PRIO,
73 @@ -1417,6 +1426,8 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
74                 return ERR_PTR(-ENAMETOOLONG);
76         bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
77 +       if (IS_ERR(bh))
78 +               return (struct dentry *) bh;
79         inode = NULL;
80         if (bh) {
81                 __u32 ino = le32_to_cpu(de->inode);
82 @@ -1450,6 +1461,8 @@ struct dentry *ext4_get_parent(struct dentry *child)
83         struct buffer_head *bh;
85         bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL);
86 +       if (IS_ERR(bh))
87 +               return (struct dentry *) bh;
88         if (!bh)
89                 return ERR_PTR(-ENOENT);
90         ino = le32_to_cpu(de->inode);
91 @@ -2727,6 +2740,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
93         retval = -ENOENT;
94         bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
95 +       if (IS_ERR(bh))
96 +               return PTR_ERR(bh);
97         if (!bh)
98                 goto end_rmdir;
100 @@ -2794,6 +2809,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
102         retval = -ENOENT;
103         bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
104 +       if (IS_ERR(bh))
105 +               return PTR_ERR(bh);
106         if (!bh)
107                 goto end_unlink;
109 @@ -3121,6 +3138,8 @@ static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
110         struct ext4_dir_entry_2 *de;
112         bh = ext4_find_entry(dir, d_name, &de, NULL);
113 +       if (IS_ERR(bh))
114 +               return PTR_ERR(bh);
115         if (bh) {
116                 retval = ext4_delete_entry(handle, dir, de, bh);
117                 brelse(bh);
118 @@ -3202,6 +3221,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
119                 dquot_initialize(new.inode);
121         old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
122 +       if (IS_ERR(old.bh))
123 +               return PTR_ERR(old.bh);
124         /*
125          *  Check for inode number is _not_ due to possible IO errors.
126          *  We might rmdir the source, keep it as pwd of some process
127 @@ -3214,6 +3235,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
129         new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
130                                  &new.de, &new.inlined);
131 +       if (IS_ERR(new.bh)) {
132 +               retval = PTR_ERR(new.bh);
133 +               goto end_rename;
134 +       }
135         if (new.bh) {
136                 if (!new.inode) {
137                         brelse(new.bh);
138 @@ -3330,6 +3355,8 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
140         old.bh = ext4_find_entry(old.dir, &old.dentry->d_name,
141                                  &old.de, &old.inlined);
142 +       if (IS_ERR(old.bh))
143 +               return PTR_ERR(old.bh);
144         /*
145          *  Check for inode number is _not_ due to possible IO errors.
146          *  We might rmdir the source, keep it as pwd of some process
147 @@ -3342,6 +3369,10 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
149         new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
150                                  &new.de, &new.inlined);
151 +       if (IS_ERR(new.bh)) {
152 +               retval = PTR_ERR(new.bh);
153 +               goto end_rename;
154 +       }
156         /* RENAME_EXCHANGE case: old *and* new must both exist */
157         if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino)