[PATCH] knfsd: lockd: optionally use hostnames for identifying peers
This patch adds the nsm_use_hostnames sysctl and module param. If set, lockd
will use the client's name (as given in the NLM arguments) to find the NSM
handle. This makes recovery work when the NFS peer is multi-homed, and the
reboot notification arrives from a different IP than the original lock calls.
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 1bf3843..a1423c6 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -462,7 +462,11 @@
list_for_each(pos, &nsm_handles) {
nsm = list_entry(pos, struct nsm_handle, sm_link);
- if (!nlm_cmp_addr(&nsm->sm_addr, sin))
+ if (hostname && nsm_use_hostnames) {
+ if (strlen(nsm->sm_name) != hostname_len
+ || memcmp(nsm->sm_name, hostname, hostname_len))
+ continue;
+ } else if (!nlm_cmp_addr(&nsm->sm_addr, sin))
continue;
atomic_inc(&nsm->sm_count);
goto out;
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 626b6c11..709cf7c 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -47,6 +47,7 @@
}
memset(&args, 0, sizeof(args));
+ args.mon_name = nsm->sm_name;
args.addr = nsm->sm_addr.sin_addr.s_addr;
args.prog = NLM_PROGRAM;
args.vers = 3;
@@ -150,7 +151,7 @@
static u32 *
xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
{
- char buffer[20];
+ char buffer[20], *name;
/*
* Use the dotted-quad IP address of the remote host as
@@ -158,8 +159,13 @@
* hostname first for whatever remote hostname it receives,
* so this works alright.
*/
- sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr));
- if (!(p = xdr_encode_string(p, buffer))
+ if (nsm_use_hostnames) {
+ name = argp->mon_name;
+ } else {
+ sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr));
+ name = buffer;
+ }
+ if (!(p = xdr_encode_string(p, name))
|| !(p = xdr_encode_string(p, utsname()->nodename)))
return ERR_PTR(-EIO);
*p++ = htonl(argp->prog);
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 3cc369e..a3b7602 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -61,6 +61,7 @@
static unsigned long nlm_grace_period;
static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
static int nlm_udpport, nlm_tcpport;
+int nsm_use_hostnames = 0;
/*
* Constants needed for the sysctl interface.
@@ -395,6 +396,14 @@
.extra1 = (int *) &nlm_port_min,
.extra2 = (int *) &nlm_port_max,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nsm_use_hostnames",
+ .data = &nsm_use_hostnames,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
{ .ctl_name = 0 }
};
@@ -483,6 +492,7 @@
&nlm_udpport, 0644);
module_param_call(nlm_tcpport, param_set_port, param_get_int,
&nlm_tcpport, 0644);
+module_param(nsm_use_hostnames, bool, 0644);
/*
* Initialising and terminating the module.
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 1fcf936..7be7aea 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -142,6 +142,7 @@
#endif
extern int nlmsvc_grace_period;
extern unsigned long nlmsvc_timeout;
+extern int nsm_use_hostnames;
/*
* Lockd client functions
diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h
index d93b074..daef509 100644
--- a/include/linux/lockd/sm_inter.h
+++ b/include/linux/lockd/sm_inter.h
@@ -28,6 +28,8 @@
u32 prog; /* RPC callback info */
u32 vers;
u32 proc;
+
+ char * mon_name;
};
/*