lockd: Clean up nlmsvc_lookup_host()
[linux-2.6.git] / fs / lockd / svcproc.c
index 75b2c81..d27aab1 100644 (file)
@@ -9,21 +9,14 @@
 
 #include <linux/types.h>
 #include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/in.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/nfsd/nfsd.h>
 #include <linux/lockd/lockd.h>
 #include <linux/lockd/share.h>
-#include <linux/lockd/sm_inter.h>
-
 
 #define NLMDBG_FACILITY                NLMDBG_CLIENT
 
 #ifdef CONFIG_LOCKD_V4
-static u32
-cast_to_nlm(u32 status, u32 vers)
+static __be32
+cast_to_nlm(__be32 status, u32 vers)
 {
        /* Note: status is assumed to be in network byte order !!! */
        if (vers != 4){
@@ -33,6 +26,7 @@ cast_to_nlm(u32 status, u32 vers)
                case nlm_lck_denied_nolocks:
                case nlm_lck_blocked:
                case nlm_lck_denied_grace_period:
+               case nlm_drop_reply:
                        break;
                case nlm4_deadlock:
                        status = nlm_lck_denied;
@@ -52,14 +46,14 @@ cast_to_nlm(u32 status, u32 vers)
 /*
  * Obtain client and file from arguments
  */
-static u32
+static __be32
 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
                        struct nlm_host **hostp, struct nlm_file **filp)
 {
        struct nlm_host         *host = NULL;
        struct nlm_file         *file = NULL;
        struct nlm_lock         *lock = &argp->lock;
-       u32                     error;
+       __be32                  error = 0;
 
        /* nfsd callbacks must have been installed for this procedure */
        if (!nlmsvc_ops)
@@ -86,15 +80,16 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
        return 0;
 
 no_locks:
-       if (host)
-               nlm_release_host(host);
+       nlmsvc_release_host(host);
+       if (error)
+               return error;
        return nlm_lck_denied_nolocks;
 }
 
 /*
  * NULL: Test for presence of service
  */
-static int
+static __be32
 nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
        dprintk("lockd: NULL          called\n");
@@ -104,56 +99,49 @@ nlmsvc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 /*
  * TEST: Check for conflicting lock
  */
-static int
+static __be32
 nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
                                         struct nlm_res  *resp)
 {
        struct nlm_host *host;
        struct nlm_file *file;
+       __be32 rc = rpc_success;
 
        dprintk("lockd: TEST          called\n");
        resp->cookie = argp->cookie;
 
-       /* Don't accept test requests during grace period */
-       if (nlmsvc_grace_period) {
-               resp->status = nlm_lck_denied_grace_period;
-               return rpc_success;
-       }
-
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-               return rpc_success;
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
        /* Now check for conflicting locks */
-       resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock));
-
-       dprintk("lockd: TEST          status %d vers %d\n",
-               ntohl(resp->status), rqstp->rq_vers);
-       nlm_release_host(host);
+       resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
+       if (resp->status == nlm_drop_reply)
+               rc = rpc_drop_reply;
+       else
+               dprintk("lockd: TEST          status %d vers %d\n",
+                       ntohl(resp->status), rqstp->rq_vers);
+
+       nlmsvc_release_host(host);
        nlm_release_file(file);
-       return rpc_success;
+       return rc;
 }
 
-static int
+static __be32
 nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
                                         struct nlm_res  *resp)
 {
        struct nlm_host *host;
        struct nlm_file *file;
+       __be32 rc = rpc_success;
 
        dprintk("lockd: LOCK          called\n");
 
        resp->cookie = argp->cookie;
 
-       /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period && !argp->reclaim) {
-               resp->status = nlm_lck_denied_grace_period;
-               return rpc_success;
-       }
-
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-               return rpc_success;
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
 #if 0
        /* If supplied state doesn't match current state, we assume it's
@@ -168,16 +156,20 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 #endif
 
        /* Now try to lock the file */
-       resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock,
-                                              argp->block, &argp->cookie));
-
-       dprintk("lockd: LOCK          status %d\n", ntohl(resp->status));
-       nlm_release_host(host);
+       resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
+                                              argp->block, &argp->cookie,
+                                              argp->reclaim));
+       if (resp->status == nlm_drop_reply)
+               rc = rpc_drop_reply;
+       else
+               dprintk("lockd: LOCK         status %d\n", ntohl(resp->status));
+
+       nlmsvc_release_host(host);
        nlm_release_file(file);
-       return rpc_success;
+       return rc;
 }
 
-static int
+static __be32
 nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
                                           struct nlm_res  *resp)
 {
@@ -189,20 +181,20 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
 
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-               return rpc_success;
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
        /* Try to cancel request. */
        resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock));
 
        dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
-       nlm_release_host(host);
+       nlmsvc_release_host(host);
        nlm_release_file(file);
        return rpc_success;
 }
@@ -210,7 +202,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
 /*
  * UNLOCK: release a lock
  */
-static int
+static __be32
 nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
                                           struct nlm_res  *resp)
 {
@@ -222,20 +214,20 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
 
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-               return rpc_success;
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
        /* Now try to remove the lock */
        resp->status = cast_status(nlmsvc_unlock(file, &argp->lock));
 
        dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
-       nlm_release_host(host);
+       nlmsvc_release_host(host);
        nlm_release_file(file);
        return rpc_success;
 }
@@ -244,14 +236,14 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
  * GRANTED: A server calls us to tell that a process' lock request
  * was granted
  */
-static int
+static __be32
 nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
                                            struct nlm_res  *resp)
 {
        resp->cookie = argp->cookie;
 
        dprintk("lockd: GRANTED       called\n");
-       resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+       resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
        dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
        return rpc_success;
 }
@@ -261,13 +253,21 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
  */
 static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
 {
-       dprintk("lockd: %4d callback returned %d\n", task->tk_pid,
+       dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
                        -task->tk_status);
 }
 
+void nlmsvc_release_call(struct nlm_rqst *call)
+{
+       if (!atomic_dec_and_test(&call->a_count))
+               return;
+       nlmsvc_release_host(call->a_host);
+       kfree(call);
+}
+
 static void nlmsvc_callback_release(void *data)
 {
-       nlm_release_call(data);
+       nlmsvc_release_call(data);
 }
 
 static const struct rpc_call_ops nlmsvc_callback_ops = {
@@ -280,12 +280,12 @@ static const struct rpc_call_ops nlmsvc_callback_ops = {
  * because we send the callback before the reply proper. I hope this
  * doesn't break any clients.
  */
-static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
-               int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
+static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
+               __be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
 {
        struct nlm_host *host;
        struct nlm_rqst *call;
-       int stat;
+       __be32 stat;
 
        host = nlmsvc_lookup_host(rqstp,
                                  argp->lock.caller,
@@ -299,7 +299,7 @@ static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *ar
 
        stat = func(rqstp, argp, &call->a_res);
        if (stat != 0) {
-               nlm_release_call(call);
+               nlmsvc_release_call(call);
                return stat;
        }
 
@@ -309,28 +309,28 @@ static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *ar
        return rpc_success;
 }
 
-static int nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                             void            *resp)
 {
        dprintk("lockd: TEST_MSG      called\n");
        return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test);
 }
 
-static int nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                             void            *resp)
 {
        dprintk("lockd: LOCK_MSG      called\n");
        return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock);
 }
 
-static int nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                               void            *resp)
 {
        dprintk("lockd: CANCEL_MSG    called\n");
        return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel);
 }
 
-static int
+static __be32
 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                                void            *resp)
 {
@@ -338,7 +338,7 @@ nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
        return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock);
 }
 
-static int
+static __be32
 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
                                                 void            *resp)
 {
@@ -349,7 +349,7 @@ nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
 /*
  * SHARE: create a DOS share or alter existing share.
  */
-static int
+static __be32
 nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
                                          struct nlm_res  *resp)
 {
@@ -361,20 +361,20 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period && !argp->reclaim) {
+       if (locks_in_grace() && !argp->reclaim) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
 
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-               return rpc_success;
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
        /* Now try to create the share */
        resp->status = cast_status(nlmsvc_share_file(host, file, argp));
 
        dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
-       nlm_release_host(host);
+       nlmsvc_release_host(host);
        nlm_release_file(file);
        return rpc_success;
 }
@@ -382,7 +382,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
 /*
  * UNSHARE: Release a DOS share.
  */
-static int
+static __be32
 nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
                                            struct nlm_res  *resp)
 {
@@ -394,20 +394,20 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
 
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
-               return rpc_success;
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 
        /* Now try to unshare the file */
        resp->status = cast_status(nlmsvc_unshare_file(host, file, argp));
 
        dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
-       nlm_release_host(host);
+       nlmsvc_release_host(host);
        nlm_release_file(file);
        return rpc_success;
 }
@@ -415,7 +415,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
 /*
  * NM_LOCK: Create an unmonitored lock
  */
-static int
+static __be32
 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
                                            struct nlm_res  *resp)
 {
@@ -428,7 +428,7 @@ nlmsvc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 /*
  * FREE_ALL: Release all locks and shares held by client
  */
-static int
+static __be32
 nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
                                             void            *resp)
 {
@@ -439,43 +439,34 @@ nlmsvc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
                return rpc_success;
 
        nlmsvc_free_host_resources(host);
-       nlm_release_host(host);
+       nlmsvc_release_host(host);
        return rpc_success;
 }
 
 /*
  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
  */
-static int
+static __be32
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
                                              void              *resp)
 {
-       struct sockaddr_in      saddr = rqstp->rq_addr;
-
        dprintk("lockd: SM_NOTIFY     called\n");
-       if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-        || ntohs(saddr.sin_port) >= 1024) {
-               printk(KERN_WARNING
-                       "lockd: rejected NSM callback from %08x:%d\n",
-                       ntohl(rqstp->rq_addr.sin_addr.s_addr),
-                       ntohs(rqstp->rq_addr.sin_port));
+
+       if (!nlm_privileged_requester(rqstp)) {
+               char buf[RPC_MAX_ADDRBUFLEN];
+               printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+                               svc_print_addr(rqstp, buf, sizeof(buf)));
                return rpc_system_err;
        }
 
-       /* Obtain the host pointer for this NFS server and try to
-        * reclaim all locks we hold on this server.
-        */
-       memset(&saddr, 0, sizeof(saddr));
-       saddr.sin_addr.s_addr = argp->addr;
-       nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state);
-
+       nlm_host_rebooted(argp);
        return rpc_success;
 }
 
 /*
  * client sent a GRANTED_RES, let's remove the associated block
  */
-static int
+static __be32
 nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res  *argp,
                                                 void            *resp)
 {