From: Greg Farnum Date: Thu, 29 Apr 2010 19:02:40 +0000 (-0700) Subject: mds: Implement file lock message handling. X-Git-Tag: v0.22~346^2~29 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4ea76e8df626c107d23529766c1888ac0a40d812;p=ceph.git mds: Implement file lock message handling. --- diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 213b335958c..09851fcb859 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -137,6 +137,7 @@ public: static const uint64_t WAIT_UNANCHORED = (1<<2); static const uint64_t WAIT_FROZEN = (1<<3); static const uint64_t WAIT_TRUNC = (1<<4); + static const uint64_t WAIT_FLOCK = (1<<5); static const uint64_t WAIT_ANY_MASK = (uint64_t)(-1); @@ -272,6 +273,8 @@ protected: int replica_caps_wanted; // [replica] what i've requested from auth utime_t replica_caps_wanted_keep_until; + ceph_lock_state_t fcntl_locks; + ceph_lock_state_t flock_locks; // LogSegment dlists i (may) belong to public: diff --git a/src/mds/Server.cc b/src/mds/Server.cc index b1da59550d8..dc7bd2aa3b3 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -1122,6 +1122,14 @@ void Server::dispatch_client_request(MDRequest *mdr) handle_client_readdir(mdr); break; + case CEPH_MDS_OP_SETFILELOCK: + handle_client_file_setlock(mdr); + break; + + case CEPH_MDS_OP_GETFILELOCK: + handle_client_file_readlock(mdr); + break; + // funky. case CEPH_MDS_OP_CREATE: if (req->get_retry_attempt() && @@ -2546,6 +2554,109 @@ public: } }; +void Server::handle_client_file_setlock(MDRequest *mdr) +{ + MClientRequest *req = mdr->client_request; + set rdlocks, wrlocks, xlocks; + //get the inode to operate on, and set up any locks needed for that + CInode *cur = rdlock_path_pin_ref(mdr, 0, rdlocks, true); + if (!cur) return; + wrlocks.insert(&cur->flocklock); + /* acquire_locks will return true if it gets the locks. If it fails, + it will redeliver this request at a later date, so drop the request. + */ + if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) return; + + //copy the lock change into a ceph_filelock so we can store/apply it + ceph_filelock set_lock; + set_lock.start = req->head.args.filelock_change.start; + set_lock.length = req->head.args.filelock_change.length; + set_lock.client = req->get_orig_source().num(); + set_lock.pid = req->head.args.filelock_change.pid; + set_lock.type = req->head.args.filelock_change.type; + bool will_wait = req->head.args.filelock_change.wait; + + ceph_lock_state_t *lock_state = NULL; + //get the appropriate lock state + switch(req->head.args.filelock_change.rule) { + case CEPH_LOCK_FLOCK: + lock_state = &cur->flock_locks; + break; + + case CEPH_LOCK_FCNTL: + lock_state = &cur->fcntl_locks; + break; + + default: + dout(0) << "got unknown lock type " << set_lock.type + << ", dropping request!" << dendl; + return; + } + + if (CEPH_LOCK_UNLOCK == set_lock.type) { + list activated_locks; + lock_state->remove_lock(set_lock, activated_locks); + 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. */ + } else { + if (lock_state->add_lock(set_lock, will_wait)) { //lock set successfully + reply_request(mdr, 0); + } else { //couldn't set lock right now + if (!will_wait) reply_request(mdr, -1); + else { + cur->add_waiter(CInode::WAIT_FLOCK, new C_MDS_RetryRequest(mdcache, mdr)); + } + } + } +} + +void Server::handle_client_file_readlock(MDRequest *mdr) +{ + MClientRequest *req = mdr->client_request; + set rdlocks, wrlocks, xlocks; + //get the inode to operate on, and set up any locks needed for that + CInode *cur = rdlock_path_pin_ref(mdr, 0, rdlocks, true); + if (!cur) return; + /* acquire_locks will return true if it gets the locks. If it fails, + it will redeliver this request at a later date, so drop the request. + */ + if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) return; + + //copy the lock change into a ceph_filelock so we can store/apply it + ceph_filelock checking_lock; + checking_lock.start = req->head.args.filelock_change.start; + checking_lock.length = req->head.args.filelock_change.length; + checking_lock.client = req->get_orig_source().num(); + checking_lock.pid = req->head.args.filelock_change.pid; + checking_lock.type = req->head.args.filelock_change.type; + + ceph_lock_state_t *lock_state = NULL; + //get the appropriate lock state + switch(req->head.args.filelock_change.rule) { + case CEPH_LOCK_FLOCK: + lock_state = &cur->flock_locks; + break; + + case CEPH_LOCK_FCNTL: + lock_state = &cur->fcntl_locks; + break; + + default: + dout(0) << "got unknown lock type " << checking_lock.type + << ", dropping request!" << dendl; + return; + } + lock_state->add_lock(checking_lock, false, false); + + bufferlist lock_bl; + ::encode(lock_state, lock_bl); + + MClientReply *reply = new MClientReply(req); + reply->set_extra_bl(lock_bl); + reply_request(mdr, reply); +} void Server::handle_client_setattr(MDRequest *mdr) { diff --git a/src/mds/Server.h b/src/mds/Server.h index 2eeb000db4d..0d4a0c1db5b 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -134,6 +134,8 @@ public: void handle_client_lookup_parent(MDRequest *mdr); void handle_client_lookup_hash(MDRequest *mdr); void handle_client_readdir(MDRequest *mdr); + void handle_client_file_setlock(MDRequest *mdr); + void handle_client_file_readlock(MDRequest *mdr); void handle_client_setattr(MDRequest *mdr); void handle_client_setlayout(MDRequest *mdr);