}
int Client::_do_filelock(Inode *in, Fh *fh, int lock_type, int op, int sleep,
- struct flock *fl, uint64_t owner)
+ struct flock *fl, uint64_t owner, void *fuse_req)
{
ldout(cct, 10) << "_do_filelock ino " << in->ino
<< (lock_type == CEPH_LOCK_FCNTL ? " fcntl" : " flock")
else
return -EIO;
+ if (op != CEPH_MDS_OP_SETFILELOCK || lock_cmd == CEPH_LOCK_UNLOCK)
+ sleep = 0;
+
/*
* Set the most significant bit, so that MDS knows the 'owner'
* is sufficient to identify the owner of lock. (old code uses
req->head.args.filelock_change.length = fl->l_len;
req->head.args.filelock_change.wait = sleep;
+ int ret;
bufferlist bl;
- int ret = make_request(req, -1, -1, NULL, NULL, -1, &bl);
+
+ if (sleep && switch_interrupt_cb && fuse_req) {
+ // enable interrupt
+ switch_interrupt_cb(fuse_req, req->get());
+
+ ret = make_request(req, -1, -1, NULL, NULL, -1, &bl);
+
+ // disable interrupt
+ switch_interrupt_cb(fuse_req, NULL);
+ put_request(req);
+ } else {
+ ret = make_request(req, -1, -1, NULL, NULL, -1, &bl);
+ }
if (ret == 0) {
if (op == CEPH_MDS_OP_GETFILELOCK) {
return ret;
}
+int Client::_interrupt_filelock(MetaRequest *req)
+{
+ Inode *in = req->inode();
+
+ int lock_type;
+ if (req->head.args.filelock_change.rule == CEPH_LOCK_FLOCK)
+ lock_type = CEPH_LOCK_FLOCK_INTR;
+ else if (req->head.args.filelock_change.rule == CEPH_LOCK_FCNTL)
+ lock_type = CEPH_LOCK_FCNTL_INTR;
+ else
+ assert(0);
+
+ MetaRequest *intr_req = new MetaRequest(CEPH_MDS_OP_SETFILELOCK);
+ filepath path;
+ in->make_nosnap_relative_path(path);
+ intr_req->set_filepath(path);
+ intr_req->set_inode(in);
+ intr_req->head.args.filelock_change = req->head.args.filelock_change;
+ intr_req->head.args.filelock_change.rule = lock_type;
+ intr_req->head.args.filelock_change.type = CEPH_LOCK_UNLOCK;
+
+ return make_request(intr_req, -1, -1, NULL, NULL, -1);
+}
+
void Client::_encode_filelocks(Inode *in, bufferlist& bl)
{
if (!in->fcntl_locks && !in->flock_locks)
return ret;
}
-int Client::_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep)
+int Client::_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep, void *fuse_req)
{
Inode *in = fh->inode;
ldout(cct, 10) << "_setlk " << fh << " ino " << in->ino << dendl;
- int ret = _do_filelock(in, fh, CEPH_LOCK_FCNTL, CEPH_MDS_OP_SETFILELOCK, sleep, fl, owner);
+ int ret = _do_filelock(in, fh, CEPH_LOCK_FCNTL, CEPH_MDS_OP_SETFILELOCK, sleep, fl, owner, fuse_req);
ldout(cct, 10) << "_setlk " << fh << " ino " << in->ino << " result=" << ret << dendl;
return ret;
}
-int Client::_flock(Fh *fh, int cmd, uint64_t owner)
+int Client::_flock(Fh *fh, int cmd, uint64_t owner, void *fuse_req)
{
Inode *in = fh->inode;
ldout(cct, 10) << "_flock " << fh << " ino " << in->ino << dendl;
fl.l_type = type;
fl.l_whence = SEEK_SET;
- int ret = _do_filelock(in, fh, CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, sleep, &fl, owner);
+ int ret = _do_filelock(in, fh, CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK, sleep, &fl, owner, fuse_req);
ldout(cct, 10) << "_flock " << fh << " ino " << in->ino << " result=" << ret << dendl;
return ret;
}
return _getlk(fh, fl, owner);
}
-int Client::ll_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep)
+int Client::ll_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep, void *fuse_req)
{
Mutex::Locker lock(client_lock);
ldout(cct, 3) << "ll_setlk (fh) " << fh << " " << fh->inode->ino << dendl;
tout(cct) << "ll_setk (fh)" << (unsigned long)fh << std::endl;
- return _setlk(fh, fl, owner, sleep);
+ return _setlk(fh, fl, owner, sleep, fuse_req);
}
-int Client::ll_flock(Fh *fh, int cmd, uint64_t owner)
+int Client::ll_flock(Fh *fh, int cmd, uint64_t owner, void *fuse_req)
{
Mutex::Locker lock(client_lock);
ldout(cct, 3) << "ll_flock (fh) " << fh << " " << fh->inode->ino << dendl;
tout(cct) << "ll_flock (fh)" << (unsigned long)fh << std::endl;
- return _flock(fh, cmd, owner);
+ return _flock(fh, cmd, owner, fuse_req);
}
void Client::ll_interrupt(void *d)
{
+ Mutex::Locker lock(client_lock);
+
+ MetaRequest *req = static_cast<MetaRequest*>(d);
+ ldout(cct, 3) << "ll_interrupt tid " << req->get_tid() << dendl;
+ tout(cct) << "ll_interrupt tid " << req->get_tid() << std::endl;
+
+ assert(req->head.op == CEPH_MDS_OP_SETFILELOCK);
+ _interrupt_filelock(req);
}
// =========================================
int _sync_fs();
int _fallocate(Fh *fh, int mode, int64_t offset, int64_t length);
int _getlk(Fh *fh, struct flock *fl, uint64_t owner);
- int _setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep);
- int _flock(Fh *fh, int cmd, uint64_t owner);
+ int _setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep, void *fuse_req=NULL);
+ int _flock(Fh *fh, int cmd, uint64_t owner, void *fuse_req=NULL);
int get_or_create(Inode *dir, const char* name,
Dentry **pdn, bool expect_null=false);
inodeno_t _get_inodeno(Inode *in);
int _do_filelock(Inode *in, Fh *fh, int lock_type, int op, int sleep,
- struct flock *fl, uint64_t owner);
+ struct flock *fl, uint64_t owner, void *fuse_req=NULL);
+ int _interrupt_filelock(MetaRequest *req);
void _encode_filelocks(Inode *in, bufferlist& bl);
void _release_filelocks(Fh *fh);
void _update_lock_state(struct flock *fl, uint64_t owner, ceph_lock_state_t *lock_state);
int ll_fallocate(Fh *fh, int mode, loff_t offset, loff_t length);
int ll_release(Fh *fh);
int ll_getlk(Fh *fh, struct flock *fl, uint64_t owner);
- int ll_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep);
- int ll_flock(Fh *fh, int cmd, uint64_t owner);
+ int ll_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep, void *fuse_req);
+ int ll_flock(Fh *fh, int cmd, uint64_t owner, void *fuse_req);
void ll_interrupt(void *d);
int ll_get_stripe_osd(struct Inode *in, uint64_t blockno,
ceph_file_layout* layout);
dout(0) << "handle_client_file_setlock: " << set_lock << dendl;
ceph_lock_state_t *lock_state = NULL;
+ bool interrupt = false;
// get the appropriate lock state
switch (req->head.args.filelock_change.rule) {
+ case CEPH_LOCK_FLOCK_INTR:
+ interrupt = true;
+ // fall-thru
case CEPH_LOCK_FLOCK:
lock_state = &cur->flock_locks;
break;
+ case CEPH_LOCK_FCNTL_INTR:
+ interrupt = true;
+ // fall-thru
case CEPH_LOCK_FCNTL:
lock_state = &cur->fcntl_locks;
break;
if (lock_state->is_waiting(set_lock)) {
dout(10) << " unlock removing waiting lock " << set_lock << dendl;
lock_state->remove_waiting(set_lock);
- } else {
+ cur->take_waiting(CInode::WAIT_FLOCK, waiters);
+ } else if (!interrupt) {
dout(10) << " unlock attempt on " << set_lock << dendl;
lock_state->remove_lock(set_lock, activated_locks);
cur->take_waiting(CInode::WAIT_FLOCK, waiters);
}
- reply_request(mdr, 0);
- /* For now we're ignoring the activated locks because their responses
- * will be sent when the lock comes up again in rotation by the MDS.
- * It's a cheap hack, but it's easy to code. */
mds->queue_waiters(waiters);
+
+ reply_request(mdr, 0);
} else {
dout(10) << " lock attempt on " << set_lock << dendl;
if (mdr->more()->flock_was_waiting &&