]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ceph: fix error handling in ceph_atomic_open and ceph_lookup
authorJeff Layton <jlayton@kernel.org>
Wed, 2 Jun 2021 16:46:07 +0000 (12:46 -0400)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 22 Jun 2021 11:53:28 +0000 (13:53 +0200)
Commit e8961c80c68b broke the error handling in these functions such
that they don't handle non-ENOENT errors from ceph_mdsc_do_request
properly.

Move the checking of -ENOENT out of ceph_handle_snapdir and into the
callers, and if we get a different error, return it immediately.

Fixes: e8961c80c68b ("ceph: don't use d_add in ceph_handle_snapdir")
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/super.h

index 5624fae7a603dad12f84e3de7f11a11fdada5ad2..9ba79b6531fba55451ff1a4a5ebf45e4a93fd442 100644 (file)
@@ -668,14 +668,13 @@ out:
  * Handle lookups for the hidden .snap directory.
  */
 struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
-                                  struct dentry *dentry, int err)
+                                  struct dentry *dentry)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
        struct inode *parent = d_inode(dentry->d_parent); /* we hold i_mutex */
 
        /* .snap dir? */
-       if (err == -ENOENT &&
-           ceph_snap(parent) == CEPH_NOSNAP &&
+       if (ceph_snap(parent) == CEPH_NOSNAP &&
            strcmp(dentry->d_name.name, fsc->mount_options->snapdir_name) == 0) {
                struct dentry *res;
                struct inode *inode = ceph_get_snapdir(parent);
@@ -742,7 +741,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
        struct ceph_mds_request *req;
-       struct dentry *res;
        int op;
        int mask;
        int err;
@@ -793,12 +791,16 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        req->r_parent = dir;
        set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
        err = ceph_mdsc_do_request(mdsc, NULL, req);
-       res = ceph_handle_snapdir(req, dentry, err);
-       if (IS_ERR(res)) {
-               err = PTR_ERR(res);
-       } else {
-               dentry = res;
-               err = 0;
+       if (err == -ENOENT) {
+               struct dentry *res;
+
+               res = ceph_handle_snapdir(req, dentry);
+               if (IS_ERR(res)) {
+                       err = PTR_ERR(res);
+               } else {
+                       dentry = res;
+                       err = 0;
+               }
        }
        dentry = ceph_finish_lookup(req, dentry, err);
        ceph_mdsc_put_request(req);  /* will dput(dentry) */
index 4dc96885acd058d95aaec40399db8f8d345b3faa..d51af36980324e6ded4ec63a2214d0f17b3b64ce 100644 (file)
@@ -742,14 +742,16 @@ retry:
        err = ceph_mdsc_do_request(mdsc,
                                   (flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
                                   req);
-       dentry = ceph_handle_snapdir(req, dentry, err);
-       if (IS_ERR(dentry)) {
-               err = PTR_ERR(dentry);
-               goto out_req;
+       if (err == -ENOENT) {
+               dentry = ceph_handle_snapdir(req, dentry);
+               if (IS_ERR(dentry)) {
+                       err = PTR_ERR(dentry);
+                       goto out_req;
+               }
+               err = 0;
        }
-       err = 0;
 
-       if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
+       if (!err && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
                err = ceph_handle_notrace_create(dir, dentry);
 
        if (d_in_lookup(dentry)) {
index db80d89556b10674b03d161116ab9ff440c63125..839e6b0239eeb7eb28c50a8be289bfe6a69df09c 100644 (file)
@@ -1218,7 +1218,7 @@ extern const struct dentry_operations ceph_dentry_ops;
 extern loff_t ceph_make_fpos(unsigned high, unsigned off, bool hash_order);
 extern int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry);
 extern struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
-                              struct dentry *dentry, int err);
+                              struct dentry *dentry);
 extern struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
                                         struct dentry *dentry, int err);