fwd->put();
}
+bool Client::is_dir_operation(MetaRequest *req)
+{
+ int op = req->get_op();
+ if (op == CEPH_MDS_OP_MKNOD || op == CEPH_MDS_OP_LINK ||
+ op == CEPH_MDS_OP_UNLINK || op == CEPH_MDS_OP_RENAME ||
+ op == CEPH_MDS_OP_MKDIR || op == CEPH_MDS_OP_RMDIR ||
+ op == CEPH_MDS_OP_SYMLINK || op == CEPH_MDS_OP_CREATE)
+ return true;
+ return false;
+}
+
void Client::handle_client_reply(MClientReply *reply)
{
mds_rank_t mds_num = mds_rank_t(reply->get_source().num());
if (!is_safe) {
request->got_unsafe = true;
session->unsafe_requests.push_back(&request->unsafe_item);
+ if (is_dir_operation(request)) {
+ Inode *dir = request->inode();
+ assert(dir);
+ dir->unsafe_dir_ops.push_back(&request->unsafe_dir_item);
+ }
}
// Only signal the caller once (on the first reply):
// we're done, clean up
if (request->got_unsafe) {
request->unsafe_item.remove_myself();
+ request->unsafe_dir_item.remove_myself();
+ signal_cond_list(request->waitfor_safe);
}
request->item.remove_myself();
mds_requests.erase(tid);
if (req->got_unsafe) {
lderr(cct) << "kick_requests_closed removing unsafe request " << req->get_tid() << dendl;
req->unsafe_item.remove_myself();
+ req->unsafe_dir_item.remove_myself();
+ signal_cond_list(req->waitfor_safe);
mds_requests.erase(req->get_tid());
put_request(req);
}
}
}
+ if (!in->unsafe_dir_ops.empty()) {
+ MetaRequest *req = in->unsafe_dir_ops.back();
+ uint64_t last_tid = req->get_tid();
+ ldout(cct, 15) << "waiting on unsafe requests, last tid " << last_tid << dendl;
+
+ do {
+ req->get();
+ wait_on_list(req->waitfor_safe);
+ put_request(req);
+ if (in->unsafe_dir_ops.empty())
+ break;
+ req = in->unsafe_dir_ops.front();
+ } while (req->tid < last_tid);
+ }
+
if (!r) {
if (flushed_metadata)
wait_sync_caps(in, wait_on_flush);
if (res < 0)
goto fail;
if (req->get_op() == CEPH_MDS_OP_RMDIR) {
+ req->set_inode(dir);
req->set_dentry(de);
req->set_other_inode(in);
} else {
void kick_requests_closed(MetaSession *session);
void handle_client_request_forward(MClientRequestForward *reply);
void handle_client_reply(MClientReply *reply);
+ bool is_dir_operation(MetaRequest *request);
bool initialized;
bool authenticated;
struct SnapRealm;
struct Inode;
class ceph_lock_state_t;
+class MetaRequest;
struct Cap {
MetaSession *session;
ceph_lock_state_t *fcntl_locks;
ceph_lock_state_t *flock_locks;
+ xlist<MetaRequest*> unsafe_dir_ops;
+
Inode(CephContext *cct_, vinodeno_t vino, ceph_file_layout *newlayout)
: cct(cct_), ino(vino.ino), snapid(vino.snapid),
rdev(0), mode(0), uid(0), gid(0), nlink(0),
xlist<MetaRequest*>::item item;
xlist<MetaRequest*>::item unsafe_item;
+ xlist<MetaRequest*>::item unsafe_dir_item;
Mutex lock; //for get/set sync
Cond *caller_cond; // who to take up
Cond *dispatch_cond; // who to kick back
+ list<Cond*> waitfor_safe;
Inode *target;
ref(1), reply(0),
kick(false), aborted(false), success(false),
readdir_offset(0), readdir_end(false), readdir_num(0),
- got_unsafe(false), item(this), unsafe_item(this),
+ got_unsafe(false), item(this), unsafe_item(this), unsafe_dir_item(this),
lock("MetaRequest lock"),
caller_cond(0), dispatch_cond(0),
target(0) {
opendir: fuse_ll_opendir,
readdir: fuse_ll_readdir,
releasedir: fuse_ll_releasedir,
- fsyncdir: 0,
+ fsyncdir: fuse_ll_fsync,
statfs: fuse_ll_statfs,
setxattr: fuse_ll_setxattr,
getxattr: fuse_ll_getxattr,