Merge tag 'mac80211-next-for-davem-2015-01-19' of git://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / fs / ceph / locks.c
index fbc39c4..c35c5c6 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,11 +235,6 @@ 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;
 }