summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-06-15 04:29:18 -0400
committerIlya Dryomov <idryomov@gmail.com>2016-07-27 20:55:40 -0400
commit9a5530c63889ac928a45c4645ab0bc23b4fbfcb8 (patch)
tree6c3d76c198fd3b26c6fe9e5c7f922ad62cbafdc7 /fs/ceph/caps.c
parentfc8c3892f30c39f28fdb835f7c8598ac4cf5ed1e (diff)
ceph: wait unsafe sync writes for evicting inode
Otherwise ceph_sync_write_unsafe() may access/modify freed inode. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c50
1 files changed, 2 insertions, 48 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index a08d245f16f5..1e48377f18a7 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1928,53 +1928,6 @@ static int caps_are_flushed(struct inode *inode, u64 flush_tid)
1928} 1928}
1929 1929
1930/* 1930/*
1931 * Wait on any unsafe replies for the given inode. First wait on the
1932 * newest request, and make that the upper bound. Then, if there are
1933 * more requests, keep waiting on the oldest as long as it is still older
1934 * than the original request.
1935 */
1936static void sync_write_wait(struct inode *inode)
1937{
1938 struct ceph_inode_info *ci = ceph_inode(inode);
1939 struct list_head *head = &ci->i_unsafe_writes;
1940 struct ceph_osd_request *req;
1941 u64 last_tid;
1942
1943 if (!S_ISREG(inode->i_mode))
1944 return;
1945
1946 spin_lock(&ci->i_unsafe_lock);
1947 if (list_empty(head))
1948 goto out;
1949
1950 /* set upper bound as _last_ entry in chain */
1951 req = list_last_entry(head, struct ceph_osd_request,
1952 r_unsafe_item);
1953 last_tid = req->r_tid;
1954
1955 do {
1956 ceph_osdc_get_request(req);
1957 spin_unlock(&ci->i_unsafe_lock);
1958 dout("sync_write_wait on tid %llu (until %llu)\n",
1959 req->r_tid, last_tid);
1960 wait_for_completion(&req->r_safe_completion);
1961 spin_lock(&ci->i_unsafe_lock);
1962 ceph_osdc_put_request(req);
1963
1964 /*
1965 * from here on look at first entry in chain, since we
1966 * only want to wait for anything older than last_tid
1967 */
1968 if (list_empty(head))
1969 break;
1970 req = list_first_entry(head, struct ceph_osd_request,
1971 r_unsafe_item);
1972 } while (req->r_tid < last_tid);
1973out:
1974 spin_unlock(&ci->i_unsafe_lock);
1975}
1976
1977/*
1978 * wait for any unsafe requests to complete. 1931 * wait for any unsafe requests to complete.
1979 */ 1932 */
1980static int unsafe_request_wait(struct inode *inode) 1933static int unsafe_request_wait(struct inode *inode)
@@ -2026,7 +1979,8 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
2026 int dirty; 1979 int dirty;
2027 1980
2028 dout("fsync %p%s\n", inode, datasync ? " datasync" : ""); 1981 dout("fsync %p%s\n", inode, datasync ? " datasync" : "");
2029 sync_write_wait(inode); 1982
1983 ceph_sync_write_wait(inode);
2030 1984
2031 ret = filemap_write_and_wait_range(inode->i_mapping, start, end); 1985 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
2032 if (ret < 0) 1986 if (ret < 0)