]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: Implement file lock message handling.
authorGreg Farnum <gregf@hq.newdream.net>
Thu, 29 Apr 2010 19:02:40 +0000 (12:02 -0700)
committerGreg Farnum <gregf@hq.newdream.net>
Mon, 2 Aug 2010 17:39:55 +0000 (10:39 -0700)
src/mds/CInode.h
src/mds/Server.cc
src/mds/Server.h

index 213b335958cd3a3a19ce6f1ec343f4b941435337..09851fcb8591cb29a42678b78916a58f4539a6a4 100644 (file)
@@ -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:
index b1da59550d8cd2cb19f205399f6b85eb455a7a33..dc7bd2aa3b3fefecbdf0df776fcaed195d946e8e 100644 (file)
@@ -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<SimpleLock*> 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<ceph_filelock> 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<SimpleLock*> 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)
 {
index 2eeb000db4d17ed9862014c12c2c8945440d9fc8..0d4a0c1db5b42fee4f5e5b1b0699236ecc0cb6a8 100644 (file)
@@ -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);