]> git.dujemihanovic.xyz Git - linux.git/commitdiff
ceph: fix handling of "meta" errors
authorJeff Layton <jlayton@kernel.org>
Thu, 7 Oct 2021 18:19:49 +0000 (14:19 -0400)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 19 Oct 2021 07:36:06 +0000 (09:36 +0200)
Currently, we check the wb_err too early for directories, before all of
the unsafe child requests have been waited on. In order to fix that we
need to check the mapping->wb_err later nearer to the end of ceph_fsync.

We also have an overly-complex method for tracking errors after
blocklisting. The errors recorded in cleanup_session_requests go to a
completely separate field in the inode, but we end up reporting them the
same way we would for any other error (in fsync).

There's no real benefit to tracking these errors in two different
places, since the only reporting mechanism for them is in fsync, and
we'd need to advance them both every time.

Given that, we can just remove i_meta_err, and convert the places that
used it to instead just use mapping->wb_err instead. That also fixes
the original problem by ensuring that we do a check_and_advance of the
wb_err at the end of the fsync op.

Cc: stable@vger.kernel.org
URL: https://tracker.ceph.com/issues/52864
Reported-by: Patrick Donnelly <pdonnell@redhat.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/super.h

index 3e42d0466521fee94b01cf3273e4354257db6db4..8f537f1d9d1d3417e8dd627c50fc957592b65342 100644 (file)
@@ -2330,7 +2330,6 @@ retry:
 
 int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       struct ceph_file_info *fi = file->private_data;
        struct inode *inode = file->f_mapping->host;
        struct ceph_inode_info *ci = ceph_inode(inode);
        u64 flush_tid;
@@ -2365,14 +2364,9 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        if (err < 0)
                ret = err;
 
-       if (errseq_check(&ci->i_meta_err, READ_ONCE(fi->meta_err))) {
-               spin_lock(&file->f_lock);
-               err = errseq_check_and_advance(&ci->i_meta_err,
-                                              &fi->meta_err);
-               spin_unlock(&file->f_lock);
-               if (err < 0)
-                       ret = err;
-       }
+       err = file_check_and_advance_wb_err(file);
+       if (err < 0)
+               ret = err;
 out:
        dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret);
        return ret;
index d16fd2d5fd426205c8d3678430b677781bdea6dd..e61018d9764ee221ec5ee396f45ec01277211c8d 100644 (file)
@@ -233,7 +233,6 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,
 
        spin_lock_init(&fi->rw_contexts_lock);
        INIT_LIST_HEAD(&fi->rw_contexts);
-       fi->meta_err = errseq_sample(&ci->i_meta_err);
        fi->filp_gen = READ_ONCE(ceph_inode_to_client(inode)->filp_gen);
 
        return 0;
index 2df1e1284451e66999ac34465e1e7617a13d5fd9..1c7574105478fb9ca167b6ab1842fdfaf6daca63 100644 (file)
@@ -541,8 +541,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
 
        ceph_fscache_inode_init(ci);
 
-       ci->i_meta_err = 0;
-
        return &ci->vfs_inode;
 }
 
index 7cad180d6debc5a52be66ba082965201a6490e61..d64413adc0fd24d335564a72e2e9cdfb38062bee 100644 (file)
@@ -1493,7 +1493,6 @@ static void cleanup_session_requests(struct ceph_mds_client *mdsc,
 {
        struct ceph_mds_request *req;
        struct rb_node *p;
-       struct ceph_inode_info *ci;
 
        dout("cleanup_session_requests mds%d\n", session->s_mds);
        mutex_lock(&mdsc->mutex);
@@ -1502,16 +1501,10 @@ static void cleanup_session_requests(struct ceph_mds_client *mdsc,
                                       struct ceph_mds_request, r_unsafe_item);
                pr_warn_ratelimited(" dropping unsafe request %llu\n",
                                    req->r_tid);
-               if (req->r_target_inode) {
-                       /* dropping unsafe change of inode's attributes */
-                       ci = ceph_inode(req->r_target_inode);
-                       errseq_set(&ci->i_meta_err, -EIO);
-               }
-               if (req->r_unsafe_dir) {
-                       /* dropping unsafe directory operation */
-                       ci = ceph_inode(req->r_unsafe_dir);
-                       errseq_set(&ci->i_meta_err, -EIO);
-               }
+               if (req->r_target_inode)
+                       mapping_set_error(req->r_target_inode->i_mapping, -EIO);
+               if (req->r_unsafe_dir)
+                       mapping_set_error(req->r_unsafe_dir->i_mapping, -EIO);
                __unregister_request(mdsc, req);
        }
        /* zero r_attempts, so kick_requests() will re-send requests */
@@ -1678,7 +1671,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
                spin_unlock(&mdsc->cap_dirty_lock);
 
                if (dirty_dropped) {
-                       errseq_set(&ci->i_meta_err, -EIO);
+                       mapping_set_error(inode->i_mapping, -EIO);
 
                        if (ci->i_wrbuffer_ref_head == 0 &&
                            ci->i_wr_ref == 0 &&
index a40eb14c282af3604223fa47dcf99e0531e52b11..14f951cd5b61bf8042342fdd483b9d923f54c27e 100644 (file)
@@ -429,8 +429,6 @@ struct ceph_inode_info {
 #ifdef CONFIG_CEPH_FSCACHE
        struct fscache_cookie *fscache;
 #endif
-       errseq_t i_meta_err;
-
        struct inode vfs_inode; /* at end */
 };
 
@@ -774,7 +772,6 @@ struct ceph_file_info {
        spinlock_t rw_contexts_lock;
        struct list_head rw_contexts;
 
-       errseq_t meta_err;
        u32 filp_gen;
        atomic_t num_locks;
 };