#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)
 {
        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);
        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) {
        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.
                                     err);
                        }
                }
-
-       } else if (err == -ERESTARTSYS) {
-               dout("undoing lock\n");
-               ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                                 CEPH_LOCK_UNLOCK, 0, fl);
        }
        return err;
 }
                                          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;
 }
 
  */
 typedef void (*ceph_mds_request_callback_t) (struct ceph_mds_client *mdsc,
                                             struct ceph_mds_request *req);
+/*
+ * wait for request completion callback
+ */
+typedef int (*ceph_mds_request_wait_callback_t) (struct ceph_mds_client *mdsc,
+                                                struct ceph_mds_request *req);
 
 /*
  * an in-flight mds request
        struct completion r_completion;
        struct completion r_safe_completion;
        ceph_mds_request_callback_t r_callback;
+       ceph_mds_request_wait_callback_t r_wait_for_completion;
        struct list_head  r_unsafe_item;  /* per-session unsafe list item */
        bool              r_got_unsafe, r_got_safe, r_got_result;