|
@@ -1970,49 +1970,46 @@ out:
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * wait for any uncommitted directory operations to commit.
|
|
|
|
|
|
+ * wait for any unsafe requests to complete.
|
|
*/
|
|
*/
|
|
-static int unsafe_dirop_wait(struct inode *inode)
|
|
|
|
|
|
+static int unsafe_request_wait(struct inode *inode)
|
|
{
|
|
{
|
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
|
- struct list_head *head = &ci->i_unsafe_dirops;
|
|
|
|
- struct ceph_mds_request *req;
|
|
|
|
- u64 last_tid;
|
|
|
|
- int ret = 0;
|
|
|
|
-
|
|
|
|
- if (!S_ISDIR(inode->i_mode))
|
|
|
|
- return 0;
|
|
|
|
|
|
+ struct ceph_mds_request *req1 = NULL, *req2 = NULL;
|
|
|
|
+ int ret, err = 0;
|
|
|
|
|
|
spin_lock(&ci->i_unsafe_lock);
|
|
spin_lock(&ci->i_unsafe_lock);
|
|
- if (list_empty(head))
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
- req = list_last_entry(head, struct ceph_mds_request,
|
|
|
|
- r_unsafe_dir_item);
|
|
|
|
- last_tid = req->r_tid;
|
|
|
|
-
|
|
|
|
- do {
|
|
|
|
- ceph_mdsc_get_request(req);
|
|
|
|
- spin_unlock(&ci->i_unsafe_lock);
|
|
|
|
|
|
+ if (S_ISDIR(inode->i_mode) && !list_empty(&ci->i_unsafe_dirops)) {
|
|
|
|
+ req1 = list_last_entry(&ci->i_unsafe_dirops,
|
|
|
|
+ struct ceph_mds_request,
|
|
|
|
+ r_unsafe_dir_item);
|
|
|
|
+ ceph_mdsc_get_request(req1);
|
|
|
|
+ }
|
|
|
|
+ if (!list_empty(&ci->i_unsafe_iops)) {
|
|
|
|
+ req2 = list_last_entry(&ci->i_unsafe_iops,
|
|
|
|
+ struct ceph_mds_request,
|
|
|
|
+ r_unsafe_target_item);
|
|
|
|
+ ceph_mdsc_get_request(req2);
|
|
|
|
+ }
|
|
|
|
+ spin_unlock(&ci->i_unsafe_lock);
|
|
|
|
|
|
- dout("unsafe_dirop_wait %p wait on tid %llu (until %llu)\n",
|
|
|
|
- inode, req->r_tid, last_tid);
|
|
|
|
- ret = !wait_for_completion_timeout(&req->r_safe_completion,
|
|
|
|
- ceph_timeout_jiffies(req->r_timeout));
|
|
|
|
|
|
+ dout("unsafe_requeset_wait %p wait on tid %llu %llu\n",
|
|
|
|
+ inode, req1 ? req1->r_tid : 0ULL, req2 ? req2->r_tid : 0ULL);
|
|
|
|
+ if (req1) {
|
|
|
|
+ ret = !wait_for_completion_timeout(&req1->r_safe_completion,
|
|
|
|
+ ceph_timeout_jiffies(req1->r_timeout));
|
|
if (ret)
|
|
if (ret)
|
|
- ret = -EIO; /* timed out */
|
|
|
|
-
|
|
|
|
- ceph_mdsc_put_request(req);
|
|
|
|
-
|
|
|
|
- spin_lock(&ci->i_unsafe_lock);
|
|
|
|
- if (ret || list_empty(head))
|
|
|
|
- break;
|
|
|
|
- req = list_first_entry(head, struct ceph_mds_request,
|
|
|
|
- r_unsafe_dir_item);
|
|
|
|
- } while (req->r_tid < last_tid);
|
|
|
|
-out:
|
|
|
|
- spin_unlock(&ci->i_unsafe_lock);
|
|
|
|
- return ret;
|
|
|
|
|
|
+ err = -EIO;
|
|
|
|
+ ceph_mdsc_put_request(req1);
|
|
|
|
+ }
|
|
|
|
+ if (req2) {
|
|
|
|
+ ret = !wait_for_completion_timeout(&req2->r_safe_completion,
|
|
|
|
+ ceph_timeout_jiffies(req2->r_timeout));
|
|
|
|
+ if (ret)
|
|
|
|
+ err = -EIO;
|
|
|
|
+ ceph_mdsc_put_request(req2);
|
|
|
|
+ }
|
|
|
|
+ return err;
|
|
}
|
|
}
|
|
|
|
|
|
int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
|
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)
|
|
dirty = try_flush_caps(inode, &flush_tid);
|
|
dirty = try_flush_caps(inode, &flush_tid);
|
|
dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
|
|
dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
|
|
|
|
|
|
- ret = unsafe_dirop_wait(inode);
|
|
|
|
|
|
+ ret = unsafe_request_wait(inode);
|
|
|
|
|
|
/*
|
|
/*
|
|
* only wait on non-file metadata writeback (the mds
|
|
* only wait on non-file metadata writeback (the mds
|