lockd: Introduce nlmclnt_operations
[sfrench/cifs-2.6.git] / fs / lockd / clntproc.c
index 112952037933b79fa36dbea67579c576ee19be58..066ac313ae5c0fff15188d3123079acd9a7180f3 100644 (file)
@@ -150,17 +150,22 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
  * @host: address of a valid nlm_host context representing the NLM server
  * @cmd: fcntl-style file lock operation to perform
  * @fl: address of arguments for the lock operation
+ * @data: address of data to be sent to callback operations
  *
  */
-int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl, void *data)
 {
        struct nlm_rqst         *call;
        int                     status;
+       const struct nlmclnt_operations *nlmclnt_ops = host->h_nlmclnt_ops;
 
        call = nlm_alloc_call(host);
        if (call == NULL)
                return -ENOMEM;
 
+       if (nlmclnt_ops && nlmclnt_ops->nlmclnt_alloc_call)
+               nlmclnt_ops->nlmclnt_alloc_call(data);
+
        nlmclnt_locks_init_private(fl, host);
        if (!fl->fl_u.nfs_fl.owner) {
                /* lockowner allocation has failed */
@@ -169,6 +174,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
        }
        /* Set up the argument struct */
        nlmclnt_setlockargs(call, fl);
+       call->a_callback_data = data;
 
        if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
                if (fl->fl_type != F_UNLCK) {
@@ -214,8 +220,12 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
 
 void nlmclnt_release_call(struct nlm_rqst *call)
 {
+       const struct nlmclnt_operations *nlmclnt_ops = call->a_host->h_nlmclnt_ops;
+
        if (!atomic_dec_and_test(&call->a_count))
                return;
+       if (nlmclnt_ops && nlmclnt_ops->nlmclnt_release_call)
+               nlmclnt_ops->nlmclnt_release_call(call->a_callback_data);
        nlmclnt_release_host(call->a_host);
        nlmclnt_release_lockargs(call);
        kfree(call);
@@ -687,6 +697,19 @@ out:
        return status;
 }
 
+static void nlmclnt_unlock_prepare(struct rpc_task *task, void *data)
+{
+       struct nlm_rqst *req = data;
+       const struct nlmclnt_operations *nlmclnt_ops = req->a_host->h_nlmclnt_ops;
+       bool defer_call = false;
+
+       if (nlmclnt_ops && nlmclnt_ops->nlmclnt_unlock_prepare)
+               defer_call = nlmclnt_ops->nlmclnt_unlock_prepare(task, req->a_callback_data);
+
+       if (!defer_call)
+               rpc_call_start(task);
+}
+
 static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
 {
        struct nlm_rqst *req = data;
@@ -720,6 +743,7 @@ die:
 }
 
 static const struct rpc_call_ops nlmclnt_unlock_ops = {
+       .rpc_call_prepare = nlmclnt_unlock_prepare,
        .rpc_call_done = nlmclnt_unlock_callback,
        .rpc_release = nlmclnt_rpc_release,
 };