]> Git Repo - linux.git/blobdiff - fs/ceph/locks.c
locks: convert lease handling to file_lock_context
[linux.git] / fs / ceph / locks.c
index fbc39c47bacd17150581e2741531c610e5e89f56..19beeed832337838fd72b8c0e67e28cd5227ed76 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/ceph/pagelist.h>
 
 static u64 lock_secret;
+static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
+                                         struct ceph_mds_request *req);
 
 static inline u64 secure_addr(void *addr)
 {
@@ -40,6 +42,9 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
        u64 length = 0;
        u64 owner;
 
+       if (operation != CEPH_MDS_OP_SETFILELOCK || cmd == CEPH_LOCK_UNLOCK)
+               wait = 0;
+
        req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
@@ -68,6 +73,9 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
        req->r_args.filelock_change.length = cpu_to_le64(length);
        req->r_args.filelock_change.wait = wait;
 
+       if (wait)
+               req->r_wait_for_completion = ceph_lock_wait_for_completion;
+
        err = ceph_mdsc_do_request(mdsc, inode, req);
 
        if (operation == CEPH_MDS_OP_GETFILELOCK) {
@@ -96,6 +104,52 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
        return err;
 }
 
+static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
+                                         struct ceph_mds_request *req)
+{
+       struct ceph_mds_request *intr_req;
+       struct inode *inode = req->r_inode;
+       int err, lock_type;
+
+       BUG_ON(req->r_op != CEPH_MDS_OP_SETFILELOCK);
+       if (req->r_args.filelock_change.rule == CEPH_LOCK_FCNTL)
+               lock_type = CEPH_LOCK_FCNTL_INTR;
+       else if (req->r_args.filelock_change.rule == CEPH_LOCK_FLOCK)
+               lock_type = CEPH_LOCK_FLOCK_INTR;
+       else
+               BUG_ON(1);
+       BUG_ON(req->r_args.filelock_change.type == CEPH_LOCK_UNLOCK);
+
+       err = wait_for_completion_interruptible(&req->r_completion);
+       if (!err)
+               return 0;
+
+       dout("ceph_lock_wait_for_completion: request %llu was interrupted\n",
+            req->r_tid);
+
+       intr_req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETFILELOCK,
+                                           USE_AUTH_MDS);
+       if (IS_ERR(intr_req))
+               return PTR_ERR(intr_req);
+
+       intr_req->r_inode = inode;
+       ihold(inode);
+       intr_req->r_num_caps = 1;
+
+       intr_req->r_args.filelock_change = req->r_args.filelock_change;
+       intr_req->r_args.filelock_change.rule = lock_type;
+       intr_req->r_args.filelock_change.type = CEPH_LOCK_UNLOCK;
+
+       err = ceph_mdsc_do_request(mdsc, inode, intr_req);
+       ceph_mdsc_put_request(intr_req);
+
+       if (err && err != -ERESTARTSYS)
+               return err;
+
+       wait_for_completion(&req->r_completion);
+       return 0;
+}
+
 /**
  * Attempt to set an fcntl lock.
  * For now, this just goes away to the server. Later it may be more awesome.
@@ -143,11 +197,6 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
                                     err);
                        }
                }
-
-       } else if (err == -ERESTARTSYS) {
-               dout("undoing lock\n");
-               ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                                 CEPH_LOCK_UNLOCK, 0, fl);
        }
        return err;
 }
@@ -186,32 +235,32 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
                                          file, CEPH_LOCK_UNLOCK, 0, fl);
                        dout("got %d on flock_lock_file_wait, undid lock", err);
                }
-       } else if (err == -ERESTARTSYS) {
-               dout("undoing lock\n");
-               ceph_lock_message(CEPH_LOCK_FLOCK,
-                                 CEPH_MDS_OP_SETFILELOCK,
-                                 file, CEPH_LOCK_UNLOCK, 0, fl);
        }
        return err;
 }
 
-/**
- * Must be called with lock_flocks() already held. Fills in the passed
- * counter variables, so you can prepare pagelist metadata before calling
- * ceph_encode_locks.
+/*
+ * Fills in the passed counter variables, so you can prepare pagelist metadata
+ * before calling ceph_encode_locks.
+ *
+ * FIXME: add counters to struct file_lock_context so we don't need to do this?
  */
 void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
 {
        struct file_lock *lock;
+       struct file_lock_context *ctx;
 
        *fcntl_count = 0;
        *flock_count = 0;
 
-       for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
-               if (lock->fl_flags & FL_POSIX)
+       ctx = inode->i_flctx;
+       if (ctx) {
+               spin_lock(&inode->i_lock);
+               list_for_each_entry(lock, &ctx->flc_posix, fl_list)
                        ++(*fcntl_count);
-               else if (lock->fl_flags & FL_FLOCK)
+               list_for_each_entry(lock, &ctx->flc_flock, fl_list)
                        ++(*flock_count);
+               spin_unlock(&inode->i_lock);
        }
        dout("counted %d flock locks and %d fcntl locks",
             *flock_count, *fcntl_count);
@@ -227,6 +276,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
                                int num_fcntl_locks, int num_flock_locks)
 {
        struct file_lock *lock;
+       struct file_lock_context *ctx = inode->i_flctx;
        int err = 0;
        int seen_fcntl = 0;
        int seen_flock = 0;
@@ -235,33 +285,34 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
        dout("encoding %d flock and %d fcntl locks", num_flock_locks,
             num_fcntl_locks);
 
-       for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
-               if (lock->fl_flags & FL_POSIX) {
-                       ++seen_fcntl;
-                       if (seen_fcntl > num_fcntl_locks) {
-                               err = -ENOSPC;
-                               goto fail;
-                       }
-                       err = lock_to_ceph_filelock(lock, &flocks[l]);
-                       if (err)
-                               goto fail;
-                       ++l;
+       if (!ctx)
+               return 0;
+
+       spin_lock(&inode->i_lock);
+       list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
+               ++seen_fcntl;
+               if (seen_fcntl > num_fcntl_locks) {
+                       err = -ENOSPC;
+                       goto fail;
                }
+               err = lock_to_ceph_filelock(lock, &flocks[l]);
+               if (err)
+                       goto fail;
+               ++l;
        }
-       for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
-               if (lock->fl_flags & FL_FLOCK) {
-                       ++seen_flock;
-                       if (seen_flock > num_flock_locks) {
-                               err = -ENOSPC;
-                               goto fail;
-                       }
-                       err = lock_to_ceph_filelock(lock, &flocks[l]);
-                       if (err)
-                               goto fail;
-                       ++l;
+       list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
+               ++seen_flock;
+               if (seen_flock > num_flock_locks) {
+                       err = -ENOSPC;
+                       goto fail;
                }
+               err = lock_to_ceph_filelock(lock, &flocks[l]);
+               if (err)
+                       goto fail;
+               ++l;
        }
 fail:
+       spin_unlock(&inode->i_lock);
        return err;
 }
 
This page took 0.036768 seconds and 4 git commands to generate.