diff options
author | Yan, Zheng <zyan@redhat.com> | 2015-10-27 06:36:06 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2015-11-02 17:36:48 -0500 |
commit | 68cd5b4b7612c2956d8553dfb39490b29f32566d (patch) | |
tree | e66461c4e1241a3dc5797a650a16683470185140 /fs/ceph/caps.c | |
parent | 4c06ace81a60636dec358c288ef6aaf3aa6dc599 (diff) |
ceph: make fsync() wait unsafe requests that created/modified inode
If we get a unsafe reply for request that created/modified inode,
add the unsafe request to a list in the newly created/modified
inode. So we can make fsync() wait these unsafe requests.
Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 71 |
1 files changed, 34 insertions, 37 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 349315332040..c69e1253b47b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1970,49 +1970,46 @@ out: | |||
1970 | } | 1970 | } |
1971 | 1971 | ||
1972 | /* | 1972 | /* |
1973 | * wait for any uncommitted directory operations to commit. | 1973 | * wait for any unsafe requests to complete. |
1974 | */ | 1974 | */ |
1975 | static int unsafe_dirop_wait(struct inode *inode) | 1975 | static int unsafe_request_wait(struct inode *inode) |
1976 | { | 1976 | { |
1977 | struct ceph_inode_info *ci = ceph_inode(inode); | 1977 | struct ceph_inode_info *ci = ceph_inode(inode); |
1978 | struct list_head *head = &ci->i_unsafe_dirops; | 1978 | struct ceph_mds_request *req1 = NULL, *req2 = NULL; |
1979 | struct ceph_mds_request *req; | 1979 | int ret, err = 0; |
1980 | u64 last_tid; | ||
1981 | int ret = 0; | ||
1982 | |||
1983 | if (!S_ISDIR(inode->i_mode)) | ||
1984 | return 0; | ||
1985 | 1980 | ||
1986 | spin_lock(&ci->i_unsafe_lock); | 1981 | spin_lock(&ci->i_unsafe_lock); |
1987 | if (list_empty(head)) | 1982 | if (S_ISDIR(inode->i_mode) && !list_empty(&ci->i_unsafe_dirops)) { |
1988 | goto out; | 1983 | req1 = list_last_entry(&ci->i_unsafe_dirops, |
1989 | 1984 | struct ceph_mds_request, | |
1990 | req = list_last_entry(head, struct ceph_mds_request, | 1985 | r_unsafe_dir_item); |
1991 | r_unsafe_dir_item); | 1986 | ceph_mdsc_get_request(req1); |
1992 | last_tid = req->r_tid; | 1987 | } |
1993 | 1988 | if (!list_empty(&ci->i_unsafe_iops)) { | |
1994 | do { | 1989 | req2 = list_last_entry(&ci->i_unsafe_iops, |
1995 | ceph_mdsc_get_request(req); | 1990 | struct ceph_mds_request, |
1996 | spin_unlock(&ci->i_unsafe_lock); | 1991 | r_unsafe_target_item); |
1992 | ceph_mdsc_get_request(req2); | ||
1993 | } | ||
1994 | spin_unlock(&ci->i_unsafe_lock); | ||
1997 | 1995 | ||
1998 | dout("unsafe_dirop_wait %p wait on tid %llu (until %llu)\n", | 1996 | dout("unsafe_requeset_wait %p wait on tid %llu %llu\n", |
1999 | inode, req->r_tid, last_tid); | 1997 | inode, req1 ? req1->r_tid : 0ULL, req2 ? req2->r_tid : 0ULL); |
2000 | ret = !wait_for_completion_timeout(&req->r_safe_completion, | 1998 | if (req1) { |
2001 | ceph_timeout_jiffies(req->r_timeout)); | 1999 | ret = !wait_for_completion_timeout(&req1->r_safe_completion, |
2000 | ceph_timeout_jiffies(req1->r_timeout)); | ||
2002 | if (ret) | 2001 | if (ret) |
2003 | ret = -EIO; /* timed out */ | 2002 | err = -EIO; |
2004 | 2003 | ceph_mdsc_put_request(req1); | |
2005 | ceph_mdsc_put_request(req); | 2004 | } |
2006 | 2005 | if (req2) { | |
2007 | spin_lock(&ci->i_unsafe_lock); | 2006 | ret = !wait_for_completion_timeout(&req2->r_safe_completion, |
2008 | if (ret || list_empty(head)) | 2007 | ceph_timeout_jiffies(req2->r_timeout)); |
2009 | break; | 2008 | if (ret) |
2010 | req = list_first_entry(head, struct ceph_mds_request, | 2009 | err = -EIO; |
2011 | r_unsafe_dir_item); | 2010 | ceph_mdsc_put_request(req2); |
2012 | } while (req->r_tid < last_tid); | 2011 | } |
2013 | out: | 2012 | return err; |
2014 | spin_unlock(&ci->i_unsafe_lock); | ||
2015 | return ret; | ||
2016 | } | 2013 | } |
2017 | 2014 | ||
2018 | int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync) | 2015 | int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
@@ -2038,7 +2035,7 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
2038 | dirty = try_flush_caps(inode, &flush_tid); | 2035 | dirty = try_flush_caps(inode, &flush_tid); |
2039 | dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); | 2036 | dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); |
2040 | 2037 | ||
2041 | ret = unsafe_dirop_wait(inode); | 2038 | ret = unsafe_request_wait(inode); |
2042 | 2039 | ||
2043 | /* | 2040 | /* |
2044 | * only wait on non-file metadata writeback (the mds | 2041 | * only wait on non-file metadata writeback (the mds |