aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <[email protected]>2019-07-25 20:16:42 +0800
committerIlya Dryomov <[email protected]>2019-09-16 12:06:23 +0200
commitf4b97866223b8dddd1bcb9d2a9546c5a5e430249 (patch)
treec9d4d9feede3bb044cd7131e202602b446c43147 /fs/ceph/caps.c
parentceph: allow closing session in restarting/reconnect state (diff)
downloadwireguard-linux-f4b97866223b8dddd1bcb9d2a9546c5a5e430249.tar.xz
wireguard-linux-f4b97866223b8dddd1bcb9d2a9546c5a5e430249.zip
ceph: track and report error of async metadata operation
Use errseq_t to track and report errors of async metadata operations, similar to how kernel handles errors during writeback. If any dirty caps or any unsafe request gets dropped during session eviction, record -EIO in corresponding inode's i_meta_err. The error will be reported by subsequent fsync, Signed-off-by: "Yan, Zheng" <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index ce0f5658720a..321ba9b30968 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2261,35 +2261,45 @@ static int unsafe_request_wait(struct inode *inode)
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;
- int ret;
+ int ret, err;
int dirty;
dout("fsync %p%s\n", inode, datasync ? " datasync" : "");
ret = file_write_and_wait_range(file, start, end);
- if (ret < 0)
- goto out;
-
if (datasync)
goto out;
dirty = try_flush_caps(inode, &flush_tid);
dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
- ret = unsafe_request_wait(inode);
+ err = unsafe_request_wait(inode);
/*
* only wait on non-file metadata writeback (the mds
* can recover size and mtime, so we don't need to
* wait for that)
*/
- if (!ret && (dirty & ~CEPH_CAP_ANY_FILE_WR)) {
- ret = wait_event_interruptible(ci->i_cap_wq,
+ if (!err && (dirty & ~CEPH_CAP_ANY_FILE_WR)) {
+ err = wait_event_interruptible(ci->i_cap_wq,
caps_are_flushed(inode, flush_tid));
}
+
+ 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;
+ }
out:
dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret);
return ret;
OSZAR »