summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/host.c46
-rw-r--r--fs/lockd/lockd_syms.c1
-rw-r--r--fs/lockd/mon.c5
-rw-r--r--fs/lockd/svc.c14
-rw-r--r--fs/lockd/svc4proc.c38
-rw-r--r--fs/lockd/svcproc.c36
-rw-r--r--fs/lockd/svcsubs.c17
-rw-r--r--fs/lockd/xdr.c2
-rw-r--r--fs/nfsd/export.c1
-rw-r--r--fs/nfsd/lockd.c22
-rw-r--r--include/linux/lockd/bind.h4
-rw-r--r--include/linux/lockd/lockd.h5
-rw-r--r--include/linux/lockd/sm_inter.h1
-rw-r--r--include/linux/lockd/xdr.h2
14 files changed, 53 insertions, 141 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 7d714b7943be..211a3a282095 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -22,7 +22,6 @@
#define NLM_HOST_MAX 64
#define NLM_HOST_NRHASH 32
#define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1))
-#define NLM_PTRHASH(ptr) ((((u32)(unsigned long) ptr) / 32) & (NLM_HOST_NRHASH-1))
#define NLM_HOST_REBIND (60 * HZ)
#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ)
@@ -42,7 +41,7 @@ static void nlm_gc_hosts(void);
struct nlm_host *
nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version)
{
- return nlm_lookup_host(NULL, sin, proto, version);
+ return nlm_lookup_host(0, sin, proto, version);
}
/*
@@ -51,45 +50,25 @@ nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version)
struct nlm_host *
nlmsvc_lookup_host(struct svc_rqst *rqstp)
{
- return nlm_lookup_host(rqstp->rq_client, &rqstp->rq_addr,
+ return nlm_lookup_host(1, &rqstp->rq_addr,
rqstp->rq_prot, rqstp->rq_vers);
}
/*
- * Match the given host against client/address
- */
-static inline int
-nlm_match_host(struct nlm_host *host, struct svc_client *clnt,
- struct sockaddr_in *sin)
-{
- if (clnt)
- return host->h_exportent == clnt;
- return nlm_cmp_addr(&host->h_addr, sin);
-}
-
-/*
* Common host lookup routine for server & client
*/
struct nlm_host *
-nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
+nlm_lookup_host(int server, struct sockaddr_in *sin,
int proto, int version)
{
struct nlm_host *host, **hp;
u32 addr;
int hash;
- if (!clnt && !sin) {
- printk(KERN_NOTICE "lockd: no clnt or addr in lookup_host!\n");
- return NULL;
- }
-
dprintk("lockd: nlm_lookup_host(%08x, p=%d, v=%d)\n",
(unsigned)(sin? ntohl(sin->sin_addr.s_addr) : 0), proto, version);
- if (clnt)
- hash = NLM_PTRHASH(clnt);
- else
- hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
+ hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
/* Lock hash table */
down(&nlm_host_sema);
@@ -98,12 +77,14 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
nlm_gc_hosts();
for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) {
- if (proto && host->h_proto != proto)
+ if (host->h_proto != proto)
+ continue;
+ if (host->h_version != version)
continue;
- if (version && host->h_version != version)
+ if (host->h_server != server)
continue;
- if (nlm_match_host(host, clnt, sin)) {
+ if (nlm_cmp_addr(&host->h_addr, sin)) {
if (hp != nlm_hosts + hash) {
*hp = host->h_next;
host->h_next = nlm_hosts[hash];
@@ -115,10 +96,6 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
}
}
- /* special hack for nlmsvc_invalidate_client */
- if (sin == NULL)
- goto nohost;
-
/* Ooops, no host found, create it */
dprintk("lockd: creating host entry\n");
@@ -146,8 +123,7 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
init_waitqueue_head(&host->h_gracewait);
host->h_state = 0; /* pseudo NSM state */
host->h_nsmstate = 0; /* real NSM state */
- host->h_exportent = clnt;
-
+ host->h_server = server;
host->h_next = nlm_hosts[hash];
nlm_hosts[hash] = host;
@@ -170,7 +146,7 @@ nlm_find_client(void)
for (hash = 0 ; hash < NLM_HOST_NRHASH; hash++) {
struct nlm_host *host, **hp;
for (hp = &nlm_hosts[hash]; (host = *hp) ; hp = &host->h_next) {
- if (host->h_exportent != NULL &&
+ if (host->h_server &&
host->h_killed == 0) {
nlm_get_host(host);
up(&nlm_host_sema);
diff --git a/fs/lockd/lockd_syms.c b/fs/lockd/lockd_syms.c
index c8c4a603a5ce..490761e3d50a 100644
--- a/fs/lockd/lockd_syms.c
+++ b/fs/lockd/lockd_syms.c
@@ -32,7 +32,6 @@ EXPORT_SYMBOL(lockd_down);
EXPORT_SYMBOL(nlmclnt_proc);
/* NFS server entry points/hooks */
-EXPORT_SYMBOL(nlmsvc_invalidate_client);
EXPORT_SYMBOL(nlmsvc_ops);
#endif /* CONFIG_MODULES */
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 0fbb296581d3..213ef0a75fb7 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -42,6 +42,7 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
goto out;
args.addr = host->h_addr.sin_addr.s_addr;
+ args.proto= (host->h_proto<<1) | host->h_server;
args.prog = NLM_PROGRAM;
args.vers = host->h_version;
args.proc = NLMPROC_NSM_NOTIFY;
@@ -167,8 +168,8 @@ xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
/* This is the private part. Needed only for SM_MON call */
if (rqstp->rq_task->tk_msg.rpc_proc == SM_MON) {
*p++ = argp->addr;
- *p++ = 0;
- *p++ = 0;
+ *p++ = argp->vers;
+ *p++ = argp->proto;
*p++ = 0;
}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index ad342eb1ff22..65a5c3f9e000 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -163,22 +163,8 @@ lockd(struct svc_rqst *rqstp)
dprintk("lockd: request from %08x\n",
(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
- /*
- * Look up the NFS client handle. The handle is needed for
- * all but the GRANTED callback RPCs.
- */
- rqstp->rq_client = NULL;
- if (nlmsvc_ops) {
- nlmsvc_ops->exp_readlock();
- rqstp->rq_client =
- nlmsvc_ops->exp_getclient(&rqstp->rq_addr);
- }
-
svc_process(serv, rqstp);
- /* Unlock export hash tables */
- if (nlmsvc_ops)
- nlmsvc_ops->exp_unlock();
}
/*
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index d594ae1fdf4a..89df2ba47dd6 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -40,15 +40,6 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if (!nlmsvc_ops)
return nlm_lck_denied_nolocks;
- /* Obtain handle for client host */
- if (rqstp->rq_client == NULL) {
- printk(KERN_NOTICE
- "lockd: unauthenticated request from (%08x:%d)\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
- return nlm_lck_denied_nolocks;
- }
-
/* Obtain host handle */
if (!(host = nlmsvc_lookup_host(rqstp))
|| (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0))
@@ -420,8 +411,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
struct sockaddr_in saddr = rqstp->rq_addr;
- int vers = rqstp->rq_vers;
- int prot = rqstp->rq_prot;
+ int vers = argp->vers;
+ int prot = argp->proto >> 1;
+
struct nlm_host *host;
dprintk("lockd: SM_NOTIFY called\n");
@@ -438,24 +430,20 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
* reclaim all locks we hold on this server.
*/
saddr.sin_addr.s_addr = argp->addr;
- if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
- nlmclnt_recovery(host, argp->state);
- nlm_release_host(host);
- }
- /* If we run on an NFS server, delete all locks held by the client */
- if (nlmsvc_ops != NULL) {
- struct svc_client *clnt;
- saddr.sin_addr.s_addr = argp->addr;
- nlmsvc_ops->exp_readlock();
- if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL
- && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
+ if ((argp->proto & 1)==0) {
+ if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
+ nlmclnt_recovery(host, argp->state);
+ nlm_release_host(host);
+ }
+ } else {
+ /* If we run on an NFS server, delete all locks held by the client */
+
+ if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) {
nlmsvc_free_host_resources(host);
+ nlm_release_host(host);
}
- nlm_release_host(host);
- nlmsvc_ops->exp_unlock();
}
-
return rpc_success;
}
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 3643873fc0e7..3d8a9a416ce0 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -69,15 +69,6 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if (!nlmsvc_ops)
return nlm_lck_denied_nolocks;
- /* Obtain handle for client host */
- if (rqstp->rq_client == NULL) {
- printk(KERN_NOTICE
- "lockd: unauthenticated request from (%08x:%d)\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
- return nlm_lck_denied_nolocks;
- }
-
/* Obtain host handle */
if (!(host = nlmsvc_lookup_host(rqstp))
|| (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0))
@@ -448,8 +439,8 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
struct sockaddr_in saddr = rqstp->rq_addr;
- int vers = rqstp->rq_vers;
- int prot = rqstp->rq_prot;
+ int vers = argp->vers;
+ int prot = argp->proto >> 1;
struct nlm_host *host;
dprintk("lockd: SM_NOTIFY called\n");
@@ -466,22 +457,17 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
* reclaim all locks we hold on this server.
*/
saddr.sin_addr.s_addr = argp->addr;
- if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
- nlmclnt_recovery(host, argp->state);
- nlm_release_host(host);
- }
-
- /* If we run on an NFS server, delete all locks held by the client */
- if (nlmsvc_ops != NULL) {
- struct svc_client *clnt;
- saddr.sin_addr.s_addr = argp->addr;
- nlmsvc_ops->exp_readlock();
- if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL
- && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
+ if ((argp->proto & 1)==0) {
+ if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
+ nlmclnt_recovery(host, argp->state);
+ nlm_release_host(host);
+ }
+ } else {
+ /* If we run on an NFS server, delete all locks held by the client */
+ if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) {
nlmsvc_free_host_resources(host);
+ nlm_release_host(host);
}
- nlm_release_host(host);
- nlmsvc_ops->exp_unlock();
}
return rpc_success;
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 6c6d52453a2d..0be7f080eb8a 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -294,23 +294,6 @@ nlmsvc_free_host_resources(struct nlm_host *host)
}
/*
- * Delete a client when the nfsd entry is removed.
- */
-void
-nlmsvc_invalidate_client(struct svc_client *clnt)
-{
- struct nlm_host *host;
-
- if ((host = nlm_lookup_host(clnt, NULL, 0, 0)) != NULL) {
- dprintk("lockd: invalidating client for %s\n", host->h_name);
- nlmsvc_free_host_resources(host);
- host->h_expires = 0;
- host->h_killed = 1;
- nlm_release_host(host);
- }
-}
-
-/*
* delete all hosts structs for clients
*/
void
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index b80d0eecf017..5e87dd2fa59f 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -369,6 +369,8 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
argp->state = ntohl(*p++);
/* Preserve the address in network byte order */
argp->addr = *p++;
+ argp->vers = *p++;
+ argp->proto = *p++;
return xdr_argsize_check(rqstp, p);
}
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 43adb434ea3c..c45b67a2a65b 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -840,7 +840,6 @@ exp_freeclient(svc_client *clp)
/* umap_free(&(clp->cl_umap)); */
exp_unexport_all(clp);
- nfsd_lockd_unexport(clp);
kfree (clp);
}
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 5c21dd94f6ec..1cc7a45c16a9 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -31,12 +31,19 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
fh.fh_export = NULL;
- nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
+ exp_readlock();
+ rqstp->rq_client = exp_getclient(&rqstp->rq_addr);
+ if (rqstp->rq_client == NULL)
+ nfserr = nfserr_stale;
+ else
+ nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
if (!nfserr) {
dget(filp->f_dentry);
mntget(filp->f_vfsmnt);
}
fh_put(&fh);
+ rqstp->rq_client = NULL;
+ exp_readunlock();
/* nlm and nfsd don't share error codes.
* we invent: 0 = no error
* 1 = stale file handle
@@ -61,23 +68,10 @@ nlm_fclose(struct file *filp)
}
struct nlmsvc_binding nfsd_nlm_ops = {
- .exp_readlock = exp_readlock, /* lock export table for reading */
- .exp_unlock = exp_readunlock, /* unlock export table */
- .exp_getclient = exp_getclient, /* look up NFS client */
.fopen = nlm_fopen, /* open file for locking */
.fclose = nlm_fclose, /* close file */
};
-/*
- * When removing an NFS client entry, notify lockd that it is gone.
- * FIXME: We should do the same when unexporting an NFS volume.
- */
-void
-nfsd_lockd_unexport(struct svc_client *clnt)
-{
- nlmsvc_invalidate_client(clnt);
-}
-
void
nfsd_lockd_init(void)
{
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index e40554349b2a..820faee16a9b 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -19,9 +19,6 @@ struct svc_client; /* opaque type */
* This is the set of functions for lockd->nfsd communication
*/
struct nlmsvc_binding {
- void (*exp_readlock)(void);
- void (*exp_unlock)(void);
- struct svc_client * (*exp_getclient)(struct sockaddr_in *);
u32 (*fopen)(struct svc_rqst *,
struct nfs_fh *,
struct file *);
@@ -33,7 +30,6 @@ extern struct nlmsvc_binding * nlmsvc_ops;
/*
* Functions exported by the lockd module
*/
-extern void nlmsvc_invalidate_client(struct svc_client *clnt);
extern int nlmclnt_proc(struct inode *, int, struct file_lock *);
extern int lockd_up(void);
extern void lockd_down(void);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index dbf013c3d890..556153082cd0 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -39,13 +39,13 @@
struct nlm_host {
struct nlm_host * h_next; /* linked list (hash table) */
struct sockaddr_in h_addr; /* peer address */
- struct svc_client * h_exportent; /* NFS client */
struct rpc_clnt * h_rpcclnt; /* RPC client to talk to peer */
char h_name[20]; /* remote hostname */
u32 h_version; /* interface version */
unsigned short h_proto; /* transport proto */
unsigned short h_authflavor; /* RPC authentication type */
unsigned short h_reclaiming : 1,
+ h_server : 1, /* server side, not client side */
h_inuse : 1,
h_killed : 1,
h_monitored : 1;
@@ -143,8 +143,7 @@ void nlmclnt_freegrantargs(struct nlm_rqst *);
*/
struct nlm_host * nlmclnt_lookup_host(struct sockaddr_in *, int, int);
struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *);
-struct nlm_host * nlm_lookup_host(struct svc_client *,
- struct sockaddr_in *, int, int);
+struct nlm_host * nlm_lookup_host(int server, struct sockaddr_in *, int, int);
struct rpc_clnt * nlm_bind_host(struct nlm_host *);
void nlm_rebind_host(struct nlm_host *);
struct nlm_host * nlm_get_host(struct nlm_host *);
diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h
index d93b074668ce..1080bb6ae315 100644
--- a/include/linux/lockd/sm_inter.h
+++ b/include/linux/lockd/sm_inter.h
@@ -28,6 +28,7 @@ struct nsm_args {
u32 prog; /* RPC callback info */
u32 vers;
u32 proc;
+ u32 proto; /* protocol (udp/tcp) plus server/client flag */
};
/*
diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h
index 51657ceffa2d..ef14dbd2a67c 100644
--- a/include/linux/lockd/xdr.h
+++ b/include/linux/lockd/xdr.h
@@ -76,6 +76,8 @@ struct nlm_reboot {
int len;
u32 state;
u32 addr;
+ u32 vers;
+ u32 proto;
};
/*