* [PATCH 0/6] First set of patches for 2.6.29
@ 2008-12-01 18:57 Chuck Lever
[not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
0 siblings, 1 reply; 20+ messages in thread
From: Chuck Lever @ 2008-12-01 18:57 UTC (permalink / raw)
To: bfields, trond.myklebust; +Cc: linux-nfs
These patches add some IPv6 support to the Linux kernel's NSM upcall
implementation, and address a couple of shortcomings in the existing
NLM/NSM implementation.
I'd like you to consider these for 2.6.29.
There are 40 more patches I have queued for 2.6.29 that finish IPv6
support in the NSM upcall implementation, enable IPv6 for lockd, and
finish and enable IPv6 support in NFSD.
---
Chuck Lever (6):
NSM: Serialize SM_MON and SM_UNMON upcalls
NLM: Clean up nsm_monitor() call
NLM: Clean up nsm_monitor() call
NSM: Support IPv6 version of mon_name
NLM: Support IPv6 scope IDs in nlm_display_address()
NLM: Remove address eye-catcher buffers from nlm_host
fs/lockd/host.c | 53 ++++++++++--------
fs/lockd/mon.c | 120 +++++++++++++++++++++-------------------
include/linux/lockd/lockd.h | 21 ++++++-
include/linux/lockd/sm_inter.h | 2 -
4 files changed, 109 insertions(+), 87 deletions(-)
--
Chuck Lever
^ permalink raw reply [flat|nested] 20+ messages in thread[parent not found: <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>]
* [PATCH 1/6] NLM: Remove address eye-catcher buffers from nlm_host [not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> @ 2008-12-01 18:57 ` Chuck Lever [not found] ` <20081201185734.10600.88841.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 2008-12-01 18:57 ` [PATCH 2/6] NLM: Support IPv6 scope IDs in nlm_display_address() Chuck Lever ` (4 subsequent siblings) 5 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-01 18:57 UTC (permalink / raw) To: bfields, trond.myklebust; +Cc: linux-nfs The h_name field in struct nlm_host is a just copy of h_nsmhandle->sm_name. Likewise, the contents of the h_addrbuf field should be identical to the sm_addrbuf field. The h_srcaddrbuf field is used only in one place for debugging. We can live without this until we get %pI formatting for printk(). Currently these buffers are 48 bytes, but we need to support scope IDs in IPv6 presentation addresses, which means making the buffers even larger. Instead, let's find ways to eliminate them to save space. Finally, AF_UNSPEC support is no longer needed in nlm_display_address() now that it is not used for the h_srcaddr field. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/lockd/host.c | 14 +++----------- include/linux/lockd/lockd.h | 3 --- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/fs/lockd/host.c b/fs/lockd/host.c index acc2aa5..68e00c0 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -112,9 +112,6 @@ static void nlm_display_address(const struct sockaddr *sap, const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; switch (sap->sa_family) { - case AF_UNSPEC: - snprintf(buf, len, "unspecified"); - break; case AF_INET: snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); break; @@ -178,7 +175,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) nlm_get_host(host); dprintk("lockd: nlm_lookup_host found host %s (%s)\n", - host->h_name, host->h_addrbuf); + host->h_name, nsm->sm_addrbuf); goto out; } @@ -232,11 +229,6 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) nrhosts++; - nlm_display_address((struct sockaddr *)&host->h_addr, - host->h_addrbuf, sizeof(host->h_addrbuf)); - nlm_display_address((struct sockaddr *)&host->h_srcaddr, - host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf)); - dprintk("lockd: nlm_lookup_host created host %s\n", host->h_name); @@ -378,8 +370,8 @@ nlm_bind_host(struct nlm_host *host) { struct rpc_clnt *clnt; - dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", - host->h_name, host->h_addrbuf, host->h_srcaddrbuf); + dprintk("lockd: nlm_bind_host %s (%s)\n", + host->h_name, host->h_nsmhandle->sm_addrbuf); /* Lock host handle */ mutex_lock(&host->h_mutex); diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 23da3fa..4467b83 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -65,9 +65,6 @@ struct nlm_host { struct list_head h_granted; /* Locks in GRANTED state */ struct list_head h_reclaim; /* Locks in RECLAIM state */ struct nsm_handle * h_nsmhandle; /* NSM status handle */ - - char h_addrbuf[48], /* address eyecatchers */ - h_srcaddrbuf[48]; }; struct nsm_handle { ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20081201185734.10600.88841.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>]
* Re: [PATCH 1/6] NLM: Remove address eye-catcher buffers from nlm_host [not found] ` <20081201185734.10600.88841.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> @ 2008-12-03 19:03 ` J. Bruce Fields 2008-12-03 19:10 ` Chuck Lever 0 siblings, 1 reply; 20+ messages in thread From: J. Bruce Fields @ 2008-12-03 19:03 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Mon, Dec 01, 2008 at 01:57:34PM -0500, Chuck Lever wrote: > The h_name field in struct nlm_host is a just copy of > h_nsmhandle->sm_name. Likewise, the contents of the h_addrbuf field > should be identical to the sm_addrbuf field. > > The h_srcaddrbuf field is used only in one place for debugging. We can > live without this until we get %pI formatting for printk(). > > Currently these buffers are 48 bytes, but we need to support scope IDs > in IPv6 presentation addresses, which means making the buffers even > larger. Instead, let's find ways to eliminate them to save space. > > Finally, AF_UNSPEC support is no longer needed in nlm_display_address() > now that it is not used for the h_srcaddr field. As usual, whenever there's a "finally, ..." or "next, ..." I'd like a separate patch. Though this is distinct enough it's not really a problem to read. Leave it as is, OK. > @@ -232,11 +229,6 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni) > > nrhosts++; > > - nlm_display_address((struct sockaddr *)&host->h_addr, > - host->h_addrbuf, sizeof(host->h_addrbuf)); > - nlm_display_address((struct sockaddr *)&host->h_srcaddr, > - host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf)); > - > dprintk("lockd: nlm_lookup_host created host %s\n", > host->h_name); > > @@ -378,8 +370,8 @@ nlm_bind_host(struct nlm_host *host) > { > struct rpc_clnt *clnt; > > - dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", > - host->h_name, host->h_addrbuf, host->h_srcaddrbuf); > + dprintk("lockd: nlm_bind_host %s (%s)\n", > + host->h_name, host->h_nsmhandle->sm_addrbuf); Hm, just checking: so the only place I can see h_nsmhandle set NULL is in nsm_unmonitor(), which is called only from nlm_destroy_host(), shortly before a kfree(host), but before a possible rpc_shutdown_client()--and doesn't look like an rpc task could be calling rpc_bind_host()? OK. And on the creation end, looks like h_nsmhandle is set on host creation. So that won't be a NULL deference. OK, looks fine. Applied. --b. > > /* Lock host handle */ > mutex_lock(&host->h_mutex); > diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h > index 23da3fa..4467b83 100644 > --- a/include/linux/lockd/lockd.h > +++ b/include/linux/lockd/lockd.h > @@ -65,9 +65,6 @@ struct nlm_host { > struct list_head h_granted; /* Locks in GRANTED state */ > struct list_head h_reclaim; /* Locks in RECLAIM state */ > struct nsm_handle * h_nsmhandle; /* NSM status handle */ > - > - char h_addrbuf[48], /* address eyecatchers */ > - h_srcaddrbuf[48]; > }; > > struct nsm_handle { > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/6] NLM: Remove address eye-catcher buffers from nlm_host 2008-12-03 19:03 ` J. Bruce Fields @ 2008-12-03 19:10 ` Chuck Lever 0 siblings, 0 replies; 20+ messages in thread From: Chuck Lever @ 2008-12-03 19:10 UTC (permalink / raw) To: J. Bruce Fields; +Cc: trond.myklebust, linux-nfs On Dec 3, 2008, at 2:03 PM, J. Bruce Fields wrote: > On Mon, Dec 01, 2008 at 01:57:34PM -0500, Chuck Lever wrote: >> The h_name field in struct nlm_host is a just copy of >> h_nsmhandle->sm_name. Likewise, the contents of the h_addrbuf field >> should be identical to the sm_addrbuf field. >> >> The h_srcaddrbuf field is used only in one place for debugging. We >> can >> live without this until we get %pI formatting for printk(). >> >> Currently these buffers are 48 bytes, but we need to support scope >> IDs >> in IPv6 presentation addresses, which means making the buffers even >> larger. Instead, let's find ways to eliminate them to save space. >> >> Finally, AF_UNSPEC support is no longer needed in >> nlm_display_address() >> now that it is not used for the h_srcaddr field. > > As usual, whenever there's a "finally, ..." or "next, ..." I'd like a > separate patch. > > Though this is distinct enough it's not really a problem to read. > Leave > it as is, OK. It seemed like a small change (one chunk) and is tightly related to what this patch does, so I left it in. >> @@ -232,11 +229,6 @@ static struct nlm_host *nlm_lookup_host(struct >> nlm_lookup_host_info *ni) >> >> nrhosts++; >> >> - nlm_display_address((struct sockaddr *)&host->h_addr, >> - host->h_addrbuf, sizeof(host->h_addrbuf)); >> - nlm_display_address((struct sockaddr *)&host->h_srcaddr, >> - host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf)); >> - >> dprintk("lockd: nlm_lookup_host created host %s\n", >> host->h_name); >> >> @@ -378,8 +370,8 @@ nlm_bind_host(struct nlm_host *host) >> { >> struct rpc_clnt *clnt; >> >> - dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", >> - host->h_name, host->h_addrbuf, host->h_srcaddrbuf); >> + dprintk("lockd: nlm_bind_host %s (%s)\n", >> + host->h_name, host->h_nsmhandle->sm_addrbuf); > > Hm, just checking: so the only place I can see h_nsmhandle set NULL is > in nsm_unmonitor(), which is called only from nlm_destroy_host(), > shortly before a kfree(host), but before a possible > rpc_shutdown_client()--and doesn't look like an rpc task could be > calling rpc_bind_host()? OK. nsm_handles live longer than the nlm_hosts that reference them, so this shouldn't be a problem. > And on the creation end, looks like h_nsmhandle is set on host > creation. > So that won't be a NULL deference. OK, looks fine. Applied. > > > --b. > >> >> /* Lock host handle */ >> mutex_lock(&host->h_mutex); >> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/ >> lockd.h >> index 23da3fa..4467b83 100644 >> --- a/include/linux/lockd/lockd.h >> +++ b/include/linux/lockd/lockd.h >> @@ -65,9 +65,6 @@ struct nlm_host { >> struct list_head h_granted; /* Locks in GRANTED state */ >> struct list_head h_reclaim; /* Locks in RECLAIM state */ >> struct nsm_handle * h_nsmhandle; /* NSM status handle */ >> - >> - char h_addrbuf[48], /* address eyecatchers */ >> - h_srcaddrbuf[48]; >> }; >> >> struct nsm_handle { >> -- Chuck Lever chuck[dot]lever[at]oracle[dot]com ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 2/6] NLM: Support IPv6 scope IDs in nlm_display_address() [not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 2008-12-01 18:57 ` [PATCH 1/6] NLM: Remove address eye-catcher buffers from nlm_host Chuck Lever @ 2008-12-01 18:57 ` Chuck Lever [not found] ` <20081201185741.10600.7375.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 2008-12-01 18:57 ` [PATCH 3/6] NSM: Support IPv6 version of mon_name Chuck Lever ` (3 subsequent siblings) 5 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-01 18:57 UTC (permalink / raw) To: bfields, trond.myklebust; +Cc: linux-nfs Scope ID support is needed since the kernel's NSM implementation is about to use these displayed addresses as a mon_name in some cases. If nsm_use_hostnames is zero, NSM will fail to handle peers that contact us via a link-local address without scope ID support. Link- local addresses do not work without an interface ID, which is stored in the sockaddr's sin6_scope_id field. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/lockd/host.c | 31 +++++++++++++++++++++++-------- include/linux/lockd/lockd.h | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 68e00c0..cd7edc3 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -105,22 +105,37 @@ static void nlm_clear_port(struct sockaddr *sap) } } -static void nlm_display_address(const struct sockaddr *sap, - char *buf, const size_t len) +static void nlm_display_ipv4_address(const struct sockaddr *sap, char *buf, + const size_t len) { const struct sockaddr_in *sin = (struct sockaddr_in *)sap; + snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); +} + +static void nlm_display_ipv6_address(const struct sockaddr *sap, char *buf, + const size_t len) +{ const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; + if (ipv6_addr_v4mapped(&sin6->sin6_addr)) + snprintf(buf, len, NIPQUAD_FMT, + NIPQUAD(sin6->sin6_addr.s6_addr32[3])); + else if (sin6->sin6_scope_id != 0) + snprintf(buf, len, NIP6_FMT "%%%u", NIP6(sin6->sin6_addr), + sin6->sin6_scope_id); + else + snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr)); +} + +static void nlm_display_address(const struct sockaddr *sap, + char *buf, const size_t len) +{ switch (sap->sa_family) { case AF_INET: - snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); + nlm_display_ipv4_address(sap, buf, len); break; case AF_INET6: - if (ipv6_addr_v4mapped(&sin6->sin6_addr)) - snprintf(buf, len, NIPQUAD_FMT, - NIPQUAD(sin6->sin6_addr.s6_addr32[3])); - else - snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr)); + nlm_display_ipv6_address(sap, buf, len); break; default: snprintf(buf, len, "unsupported address family"); diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 4467b83..307a8f0 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -75,7 +75,7 @@ struct nsm_handle { size_t sm_addrlen; unsigned int sm_monitored : 1, sm_sticky : 1; /* don't unmonitor */ - char sm_addrbuf[48]; /* address eyecatcher */ + char sm_addrbuf[63]; /* presentation address */ }; /* ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20081201185741.10600.7375.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>]
* Re: [PATCH 2/6] NLM: Support IPv6 scope IDs in nlm_display_address() [not found] ` <20081201185741.10600.7375.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> @ 2008-12-03 19:34 ` J. Bruce Fields 2008-12-03 19:46 ` J. Bruce Fields 0 siblings, 1 reply; 20+ messages in thread From: J. Bruce Fields @ 2008-12-03 19:34 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Mon, Dec 01, 2008 at 01:57:42PM -0500, Chuck Lever wrote: > Scope ID support is needed since the kernel's NSM implementation is > about to use these displayed addresses as a mon_name in some cases. > > If nsm_use_hostnames is zero, NSM will fail to handle peers that > contact us via a link-local address without scope ID support. Link- > local addresses do not work without an interface ID, which is stored > in the sockaddr's sin6_scope_id field. As always: what's the latest progress on getting this ipv6-address-display stuff into the core networking code? Anyway, looks fine, but looking forward to be able to delete some of this one day.... Just one more question below: > Signed-off-by: Chuck Lever <chuck.lever@oracle.com> > --- > > fs/lockd/host.c | 31 +++++++++++++++++++++++-------- > include/linux/lockd/lockd.h | 2 +- > 2 files changed, 24 insertions(+), 9 deletions(-) > > diff --git a/fs/lockd/host.c b/fs/lockd/host.c > index 68e00c0..cd7edc3 100644 > --- a/fs/lockd/host.c > +++ b/fs/lockd/host.c > @@ -105,22 +105,37 @@ static void nlm_clear_port(struct sockaddr *sap) > } > } > > -static void nlm_display_address(const struct sockaddr *sap, > - char *buf, const size_t len) > +static void nlm_display_ipv4_address(const struct sockaddr *sap, char *buf, > + const size_t len) > { > const struct sockaddr_in *sin = (struct sockaddr_in *)sap; > + snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); > +} > + > +static void nlm_display_ipv6_address(const struct sockaddr *sap, char *buf, > + const size_t len) > +{ > const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; > > + if (ipv6_addr_v4mapped(&sin6->sin6_addr)) > + snprintf(buf, len, NIPQUAD_FMT, > + NIPQUAD(sin6->sin6_addr.s6_addr32[3])); > + else if (sin6->sin6_scope_id != 0) > + snprintf(buf, len, NIP6_FMT "%%%u", NIP6(sin6->sin6_addr), > + sin6->sin6_scope_id); > + else > + snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr)); > +} > + > +static void nlm_display_address(const struct sockaddr *sap, > + char *buf, const size_t len) > +{ > switch (sap->sa_family) { > case AF_INET: > - snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); > + nlm_display_ipv4_address(sap, buf, len); > break; > case AF_INET6: > - if (ipv6_addr_v4mapped(&sin6->sin6_addr)) > - snprintf(buf, len, NIPQUAD_FMT, > - NIPQUAD(sin6->sin6_addr.s6_addr32[3])); > - else > - snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr)); > + nlm_display_ipv6_address(sap, buf, len); > break; > default: > snprintf(buf, len, "unsupported address family"); > diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h > index 4467b83..307a8f0 100644 > --- a/include/linux/lockd/lockd.h > +++ b/include/linux/lockd/lockd.h > @@ -75,7 +75,7 @@ struct nsm_handle { > size_t sm_addrlen; > unsigned int sm_monitored : 1, > sm_sticky : 1; /* don't unmonitor */ > - char sm_addrbuf[48]; /* address eyecatcher */ > + char sm_addrbuf[63]; /* presentation address */ > }; Could you add a brief (1-line?) comment justifying the choice of 63? --b. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/6] NLM: Support IPv6 scope IDs in nlm_display_address() 2008-12-03 19:34 ` J. Bruce Fields @ 2008-12-03 19:46 ` J. Bruce Fields 0 siblings, 0 replies; 20+ messages in thread From: J. Bruce Fields @ 2008-12-03 19:46 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Wed, Dec 03, 2008 at 02:34:04PM -0500, bfields wrote: > On Mon, Dec 01, 2008 at 01:57:42PM -0500, Chuck Lever wrote: > > --- a/include/linux/lockd/lockd.h > > +++ b/include/linux/lockd/lockd.h > > @@ -75,7 +75,7 @@ struct nsm_handle { > > size_t sm_addrlen; > > unsigned int sm_monitored : 1, > > sm_sticky : 1; /* don't unmonitor */ > > - char sm_addrbuf[48]; /* address eyecatcher */ > > + char sm_addrbuf[63]; /* presentation address */ > > }; > > Could you add a brief (1-line?) comment justifying the choice of 63? So something like just: sm_sticky : 1; /* don't unmonitor */ unsigned int sm_monitored : 1, sm_sticky : 1; /* don't unmonitor */ /* * This can hold 8 groups of colon-separated 4-hex-digit numbers, a * percent sign, and a scope id (at most 32 bits, in decimal, so): * 63 == 8*4 + 7 colons + 1 percent sign + at most 10 digits + padding: */ char sm_addrbuf[63]; /* presentation address */ ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 3/6] NSM: Support IPv6 version of mon_name [not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 2008-12-01 18:57 ` [PATCH 1/6] NLM: Remove address eye-catcher buffers from nlm_host Chuck Lever 2008-12-01 18:57 ` [PATCH 2/6] NLM: Support IPv6 scope IDs in nlm_display_address() Chuck Lever @ 2008-12-01 18:57 ` Chuck Lever [not found] ` <20081201185749.10600.38468.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 2008-12-01 18:57 ` [PATCH 4/6] NLM: Clean up nsm_monitor() call Chuck Lever ` (2 subsequent siblings) 5 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-01 18:57 UTC (permalink / raw) To: bfields, trond.myklebust; +Cc: linux-nfs The "mon_name" argument of the NSMPROC_MON and NSMPROC_UNMON upcalls is a string that contains the hostname or IP address of the remote peer to be notified when this host has rebooted. The sm-notify command uses this identifier to contact the peer when we reboot, so it must be either a well-qualified DNS hostname or a presentation format IP address string. When the "nsm_use_hostnames" sysctl is set to zero, the kernel's NSM provides a presentation format IP address in the "mon_name" argument. Otherwise, the "caller_name" argument from NLM requests is used, which is usually just the DNS hostname of the peer. To support IPv6 addresses for the mon_name argument, we use the nsm_handle's address eye-catcher, which already contains an appropriate presentation format address string. Using the eye-catcher string obviates the need to use a large buffer on the stack to form the presentation address string for the upcall. This patch also addresses a subtle bug. An NSMPROC_MON request and the subsequent NSMPROC_UNMON request for the same peer are required to use the same value for the "mon_name" argument. Otherwise, rpc.statd's NSMPROC_UNMON processing cannot locate the database entry for that peer and remove it. If the setting of nsm_use_hostnames is changed between the time the kernel sends an NSMPROC_MON request and the time it sends the NSMPROC_UNMON request for the same peer, the "mon_name" argument for these two requests may not be the same. This is because the value of "mon_name" is currently chosen at the moment the call is made based on the setting of nsm_use_hostnames To ensure both requests pass identical contents in the "mon_name" argument, we now select which string to use for the argument in the nsm_monitor() function. A pointer to this string is saved in the nsm_handle so it can be used for the subsequent NSMPROC_UNMON upcall. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/lockd/mon.c | 45 +++++++++++++++++-------------------------- include/linux/lockd/lockd.h | 1 + 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 4e7e958..a606fbb 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -18,8 +18,6 @@ #define NLMDBG_FACILITY NLMDBG_MONITOR -#define XDR_ADDRBUF_LEN (20) - static struct rpc_clnt * nsm_create(void); static struct rpc_program nsm_program; @@ -37,7 +35,13 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) { struct rpc_clnt *clnt; int status; - struct nsm_args args; + struct nsm_args args = { + .addr = nsm_addr_in(nsm)->sin_addr.s_addr, + .prog = NLM_PROGRAM, + .vers = 3, + .proc = NLMPROC_NSM_NOTIFY, + .mon_name = nsm->sm_mon_name, + }; struct rpc_message msg = { .rpc_argp = &args, .rpc_resp = res, @@ -46,22 +50,18 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) clnt = nsm_create(); if (IS_ERR(clnt)) { status = PTR_ERR(clnt); + dprintk("lockd: failed to create NSM upcall transport, " + "status=%d\n", status); goto out; } - memset(&args, 0, sizeof(args)); - args.mon_name = nsm->sm_name; - args.addr = nsm_addr_in(nsm)->sin_addr.s_addr; - args.prog = NLM_PROGRAM; - args.vers = 3; - args.proc = NLMPROC_NSM_NOTIFY; memset(res, 0, sizeof(*res)); msg.rpc_proc = &clnt->cl_procinfo[proc]; status = rpc_call_sync(clnt, &msg, 0); if (status < 0) - printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", - status); + dprintk("lockd: NSM upcall RPC failed, status=%d\n", + status); else status = 0; rpc_shutdown_client(clnt); @@ -85,6 +85,12 @@ nsm_monitor(struct nlm_host *host) if (nsm->sm_monitored) return 0; + /* + * Choose whether to record the caller_name or IP address of + * this peer in the local rpc.statd's database. + */ + nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; + status = nsm_mon_unmon(nsm, SM_MON, &res); if (status < 0 || res.status != 0) @@ -165,25 +171,10 @@ static __be32 *xdr_encode_nsm_string(__be32 *p, char *string) /* * "mon_name" specifies the host to be monitored. - * - * Linux uses a text version of the IP address of the remote - * host as the host identifier (the "mon_name" argument). - * - * Linux statd always looks up the canonical hostname first for - * whatever remote hostname it receives, so this works alright. */ static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) { - char buffer[XDR_ADDRBUF_LEN + 1]; - char *name = argp->mon_name; - - if (!nsm_use_hostnames) { - snprintf(buffer, XDR_ADDRBUF_LEN, - NIPQUAD_FMT, NIPQUAD(argp->addr)); - name = buffer; - } - - return xdr_encode_nsm_string(p, name); + return xdr_encode_nsm_string(p, argp->mon_name); } /* diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 307a8f0..de9ea7b 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -73,6 +73,7 @@ struct nsm_handle { char * sm_name; struct sockaddr_storage sm_addr; size_t sm_addrlen; + char * sm_mon_name; unsigned int sm_monitored : 1, sm_sticky : 1; /* don't unmonitor */ char sm_addrbuf[63]; /* presentation address */ ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20081201185749.10600.38468.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>]
* Re: [PATCH 3/6] NSM: Support IPv6 version of mon_name [not found] ` <20081201185749.10600.38468.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> @ 2008-12-03 21:01 ` J. Bruce Fields 2008-12-03 21:19 ` Chuck Lever 0 siblings, 1 reply; 20+ messages in thread From: J. Bruce Fields @ 2008-12-03 21:01 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Mon, Dec 01, 2008 at 01:57:50PM -0500, Chuck Lever wrote: > The "mon_name" argument of the NSMPROC_MON and NSMPROC_UNMON upcalls > is a string that contains the hostname or IP address of the remote peer > to be notified when this host has rebooted. The sm-notify command uses > this identifier to contact the peer when we reboot, so it must be > either a well-qualified DNS hostname or a presentation format IP > address string. > > When the "nsm_use_hostnames" sysctl is set to zero, the kernel's NSM > provides a presentation format IP address in the "mon_name" argument. > Otherwise, the "caller_name" argument from NLM requests is used, > which is usually just the DNS hostname of the peer. > > To support IPv6 addresses for the mon_name argument, we use the > nsm_handle's address eye-catcher, which already contains an appropriate > presentation format address string. Using the eye-catcher string > obviates the need to use a large buffer on the stack to form the > presentation address string for the upcall. > > This patch also addresses a subtle bug. > > An NSMPROC_MON request and the subsequent NSMPROC_UNMON request for the > same peer are required to use the same value for the "mon_name" > argument. Otherwise, rpc.statd's NSMPROC_UNMON processing cannot > locate the database entry for that peer and remove it. At some point we need to grep for each read of nsm_use_hostnames and think about what would happen if it changed there. For example, the check of nsm_use_hostnames when searching for a match in nsm_find() could cause a spurious failure to find a host. If the nsm_find() came from nlm_host_rebooted(), we could fail to release locks from some dead host. Probably we should just forbid changing nsm_use_hostnames while the server is running or an nfs filesystem is mounted. Or, if that's not possible, allow changing the sysctl at any time, but only actually look at it (and store it) once on server startup or first mount (whichever comes first). As this requires a root user doing something wrong, fixing this bug probably isn't high priority enough to block the rest of the ipv6 patches, so we could make a note of the problem and move on for now. --b. > If the setting of nsm_use_hostnames is changed between the time the > kernel sends an NSMPROC_MON request and the time it sends the > NSMPROC_UNMON request for the same peer, the "mon_name" argument for > these two requests may not be the same. This is because the value of > "mon_name" is currently chosen at the moment the call is made based on > the setting of nsm_use_hostnames > > To ensure both requests pass identical contents in the "mon_name" > argument, we now select which string to use for the argument in the > nsm_monitor() function. A pointer to this string is saved in the > nsm_handle so it can be used for the subsequent NSMPROC_UNMON upcall. > > Signed-off-by: Chuck Lever <chuck.lever@oracle.com> > --- > > fs/lockd/mon.c | 45 +++++++++++++++++-------------------------- > include/linux/lockd/lockd.h | 1 + > 2 files changed, 19 insertions(+), 27 deletions(-) > > diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c > index 4e7e958..a606fbb 100644 > --- a/fs/lockd/mon.c > +++ b/fs/lockd/mon.c > @@ -18,8 +18,6 @@ > > #define NLMDBG_FACILITY NLMDBG_MONITOR > > -#define XDR_ADDRBUF_LEN (20) > - > static struct rpc_clnt * nsm_create(void); > > static struct rpc_program nsm_program; > @@ -37,7 +35,13 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) > { > struct rpc_clnt *clnt; > int status; > - struct nsm_args args; > + struct nsm_args args = { > + .addr = nsm_addr_in(nsm)->sin_addr.s_addr, > + .prog = NLM_PROGRAM, > + .vers = 3, > + .proc = NLMPROC_NSM_NOTIFY, > + .mon_name = nsm->sm_mon_name, > + }; > struct rpc_message msg = { > .rpc_argp = &args, > .rpc_resp = res, > @@ -46,22 +50,18 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) > clnt = nsm_create(); > if (IS_ERR(clnt)) { > status = PTR_ERR(clnt); > + dprintk("lockd: failed to create NSM upcall transport, " > + "status=%d\n", status); > goto out; > } > > - memset(&args, 0, sizeof(args)); > - args.mon_name = nsm->sm_name; > - args.addr = nsm_addr_in(nsm)->sin_addr.s_addr; > - args.prog = NLM_PROGRAM; > - args.vers = 3; > - args.proc = NLMPROC_NSM_NOTIFY; > memset(res, 0, sizeof(*res)); > > msg.rpc_proc = &clnt->cl_procinfo[proc]; > status = rpc_call_sync(clnt, &msg, 0); > if (status < 0) > - printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", > - status); > + dprintk("lockd: NSM upcall RPC failed, status=%d\n", > + status); > else > status = 0; > rpc_shutdown_client(clnt); > @@ -85,6 +85,12 @@ nsm_monitor(struct nlm_host *host) > if (nsm->sm_monitored) > return 0; > > + /* > + * Choose whether to record the caller_name or IP address of > + * this peer in the local rpc.statd's database. > + */ > + nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; > + > status = nsm_mon_unmon(nsm, SM_MON, &res); > > if (status < 0 || res.status != 0) > @@ -165,25 +171,10 @@ static __be32 *xdr_encode_nsm_string(__be32 *p, char *string) > > /* > * "mon_name" specifies the host to be monitored. > - * > - * Linux uses a text version of the IP address of the remote > - * host as the host identifier (the "mon_name" argument). > - * > - * Linux statd always looks up the canonical hostname first for > - * whatever remote hostname it receives, so this works alright. > */ > static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) > { > - char buffer[XDR_ADDRBUF_LEN + 1]; > - char *name = argp->mon_name; > - > - if (!nsm_use_hostnames) { > - snprintf(buffer, XDR_ADDRBUF_LEN, > - NIPQUAD_FMT, NIPQUAD(argp->addr)); > - name = buffer; > - } > - > - return xdr_encode_nsm_string(p, name); > + return xdr_encode_nsm_string(p, argp->mon_name); > } > > /* > diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h > index 307a8f0..de9ea7b 100644 > --- a/include/linux/lockd/lockd.h > +++ b/include/linux/lockd/lockd.h > @@ -73,6 +73,7 @@ struct nsm_handle { > char * sm_name; > struct sockaddr_storage sm_addr; > size_t sm_addrlen; > + char * sm_mon_name; > unsigned int sm_monitored : 1, > sm_sticky : 1; /* don't unmonitor */ > char sm_addrbuf[63]; /* presentation address */ > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 3/6] NSM: Support IPv6 version of mon_name 2008-12-03 21:01 ` J. Bruce Fields @ 2008-12-03 21:19 ` Chuck Lever 2008-12-03 21:24 ` Chuck Lever 0 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-03 21:19 UTC (permalink / raw) To: J. Bruce Fields; +Cc: trond.myklebust, linux-nfs On Dec 3, 2008, at 4:01 PM, J. Bruce Fields wrote: > On Mon, Dec 01, 2008 at 01:57:50PM -0500, Chuck Lever wrote: >> The "mon_name" argument of the NSMPROC_MON and NSMPROC_UNMON upcalls >> is a string that contains the hostname or IP address of the remote >> peer >> to be notified when this host has rebooted. The sm-notify command >> uses >> this identifier to contact the peer when we reboot, so it must be >> either a well-qualified DNS hostname or a presentation format IP >> address string. >> >> When the "nsm_use_hostnames" sysctl is set to zero, the kernel's NSM >> provides a presentation format IP address in the "mon_name" argument. >> Otherwise, the "caller_name" argument from NLM requests is used, >> which is usually just the DNS hostname of the peer. >> >> To support IPv6 addresses for the mon_name argument, we use the >> nsm_handle's address eye-catcher, which already contains an >> appropriate >> presentation format address string. Using the eye-catcher string >> obviates the need to use a large buffer on the stack to form the >> presentation address string for the upcall. >> >> This patch also addresses a subtle bug. >> >> An NSMPROC_MON request and the subsequent NSMPROC_UNMON request for >> the >> same peer are required to use the same value for the "mon_name" >> argument. Otherwise, rpc.statd's NSMPROC_UNMON processing cannot >> locate the database entry for that peer and remove it. > > At some point we need to grep for each read of nsm_use_hostnames and > think about what would happen if it changed there. > > For example, the check of nsm_use_hostnames when searching for a match > in nsm_find() could cause a spurious failure to find a host. If the > nsm_find() came from nlm_host_rebooted(), we could fail to release > locks > from some dead host. Agreed. A subsequent patch in this series removes that particular use of nsm_use_hostnames. An audit of the other use(s) is a good future work item. > Probably we should just forbid changing nsm_use_hostnames while the > server is running or an nfs filesystem is mounted. Or, if that's not > possible, allow changing the sysctl at any time, but only actually > look > at it (and store it) once on server startup or first mount (whichever > comes first). Actually, "when lockd comes up" might be an appropriate moment to copy the value of this variable. > As this requires a root user doing something wrong, Or a bug in rpc.statd or sm-notify... > fixing this bug > probably isn't high priority enough to block the rest of the ipv6 > patches, so we could make a note of the problem and move on for now. > > --b. > >> If the setting of nsm_use_hostnames is changed between the time the >> kernel sends an NSMPROC_MON request and the time it sends the >> NSMPROC_UNMON request for the same peer, the "mon_name" argument for >> these two requests may not be the same. This is because the value of >> "mon_name" is currently chosen at the moment the call is made based >> on >> the setting of nsm_use_hostnames >> >> To ensure both requests pass identical contents in the "mon_name" >> argument, we now select which string to use for the argument in the >> nsm_monitor() function. A pointer to this string is saved in the >> nsm_handle so it can be used for the subsequent NSMPROC_UNMON upcall. >> >> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> >> --- >> >> fs/lockd/mon.c | 45 ++++++++++++++++ >> +-------------------------- >> include/linux/lockd/lockd.h | 1 + >> 2 files changed, 19 insertions(+), 27 deletions(-) >> >> diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c >> index 4e7e958..a606fbb 100644 >> --- a/fs/lockd/mon.c >> +++ b/fs/lockd/mon.c >> @@ -18,8 +18,6 @@ >> >> #define NLMDBG_FACILITY NLMDBG_MONITOR >> >> -#define XDR_ADDRBUF_LEN (20) >> - >> static struct rpc_clnt * nsm_create(void); >> >> static struct rpc_program nsm_program; >> @@ -37,7 +35,13 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, >> struct nsm_res *res) >> { >> struct rpc_clnt *clnt; >> int status; >> - struct nsm_args args; >> + struct nsm_args args = { >> + .addr = nsm_addr_in(nsm)->sin_addr.s_addr, >> + .prog = NLM_PROGRAM, >> + .vers = 3, >> + .proc = NLMPROC_NSM_NOTIFY, >> + .mon_name = nsm->sm_mon_name, >> + }; >> struct rpc_message msg = { >> .rpc_argp = &args, >> .rpc_resp = res, >> @@ -46,22 +50,18 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, >> struct nsm_res *res) >> clnt = nsm_create(); >> if (IS_ERR(clnt)) { >> status = PTR_ERR(clnt); >> + dprintk("lockd: failed to create NSM upcall transport, " >> + "status=%d\n", status); >> goto out; >> } >> >> - memset(&args, 0, sizeof(args)); >> - args.mon_name = nsm->sm_name; >> - args.addr = nsm_addr_in(nsm)->sin_addr.s_addr; >> - args.prog = NLM_PROGRAM; >> - args.vers = 3; >> - args.proc = NLMPROC_NSM_NOTIFY; >> memset(res, 0, sizeof(*res)); >> >> msg.rpc_proc = &clnt->cl_procinfo[proc]; >> status = rpc_call_sync(clnt, &msg, 0); >> if (status < 0) >> - printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", >> - status); >> + dprintk("lockd: NSM upcall RPC failed, status=%d\n", >> + status); >> else >> status = 0; >> rpc_shutdown_client(clnt); >> @@ -85,6 +85,12 @@ nsm_monitor(struct nlm_host *host) >> if (nsm->sm_monitored) >> return 0; >> >> + /* >> + * Choose whether to record the caller_name or IP address of >> + * this peer in the local rpc.statd's database. >> + */ >> + nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm- >> >sm_addrbuf; >> + >> status = nsm_mon_unmon(nsm, SM_MON, &res); >> >> if (status < 0 || res.status != 0) >> @@ -165,25 +171,10 @@ static __be32 *xdr_encode_nsm_string(__be32 >> *p, char *string) >> >> /* >> * "mon_name" specifies the host to be monitored. >> - * >> - * Linux uses a text version of the IP address of the remote >> - * host as the host identifier (the "mon_name" argument). >> - * >> - * Linux statd always looks up the canonical hostname first for >> - * whatever remote hostname it receives, so this works alright. >> */ >> static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) >> { >> - char buffer[XDR_ADDRBUF_LEN + 1]; >> - char *name = argp->mon_name; >> - >> - if (!nsm_use_hostnames) { >> - snprintf(buffer, XDR_ADDRBUF_LEN, >> - NIPQUAD_FMT, NIPQUAD(argp->addr)); >> - name = buffer; >> - } >> - >> - return xdr_encode_nsm_string(p, name); >> + return xdr_encode_nsm_string(p, argp->mon_name); >> } >> >> /* >> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/ >> lockd.h >> index 307a8f0..de9ea7b 100644 >> --- a/include/linux/lockd/lockd.h >> +++ b/include/linux/lockd/lockd.h >> @@ -73,6 +73,7 @@ struct nsm_handle { >> char * sm_name; >> struct sockaddr_storage sm_addr; >> size_t sm_addrlen; >> + char * sm_mon_name; >> unsigned int sm_monitored : 1, >> sm_sticky : 1; /* don't unmonitor */ >> char sm_addrbuf[63]; /* presentation address */ >> -- Chuck Lever chuck[dot]lever[at]oracle[dot]com ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 3/6] NSM: Support IPv6 version of mon_name 2008-12-03 21:19 ` Chuck Lever @ 2008-12-03 21:24 ` Chuck Lever 0 siblings, 0 replies; 20+ messages in thread From: Chuck Lever @ 2008-12-03 21:24 UTC (permalink / raw) To: J. Bruce Fields; +Cc: Trond Myklebust, Linux NFS Mailing list On Dec 3, 2008, at 4:19 PM, Chuck Lever wrote: > On Dec 3, 2008, at 4:01 PM, J. Bruce Fields wrote: >> On Mon, Dec 01, 2008 at 01:57:50PM -0500, Chuck Lever wrote: >>> The "mon_name" argument of the NSMPROC_MON and NSMPROC_UNMON upcalls >>> is a string that contains the hostname or IP address of the remote >>> peer >>> to be notified when this host has rebooted. The sm-notify command >>> uses >>> this identifier to contact the peer when we reboot, so it must be >>> either a well-qualified DNS hostname or a presentation format IP >>> address string. >>> >>> When the "nsm_use_hostnames" sysctl is set to zero, the kernel's NSM >>> provides a presentation format IP address in the "mon_name" >>> argument. >>> Otherwise, the "caller_name" argument from NLM requests is used, >>> which is usually just the DNS hostname of the peer. >>> >>> To support IPv6 addresses for the mon_name argument, we use the >>> nsm_handle's address eye-catcher, which already contains an >>> appropriate >>> presentation format address string. Using the eye-catcher string >>> obviates the need to use a large buffer on the stack to form the >>> presentation address string for the upcall. >>> >>> This patch also addresses a subtle bug. >>> >>> An NSMPROC_MON request and the subsequent NSMPROC_UNMON request >>> for the >>> same peer are required to use the same value for the "mon_name" >>> argument. Otherwise, rpc.statd's NSMPROC_UNMON processing cannot >>> locate the database entry for that peer and remove it. >> >> At some point we need to grep for each read of nsm_use_hostnames and >> think about what would happen if it changed there. >> >> For example, the check of nsm_use_hostnames when searching for a >> match >> in nsm_find() could cause a spurious failure to find a host. If the >> nsm_find() came from nlm_host_rebooted(), we could fail to release >> locks >> from some dead host. > > Agreed. A subsequent patch in this series removes that particular > use of nsm_use_hostnames. An audit of the other use(s) is a good > future work item. I'll clarify: a subsequent patch in my for-2.6.29 series that I haven't posted yet removes that use of nsm_use_hostnames. >> Probably we should just forbid changing nsm_use_hostnames while the >> server is running or an nfs filesystem is mounted. Or, if that's not >> possible, allow changing the sysctl at any time, but only actually >> look >> at it (and store it) once on server startup or first mount (whichever >> comes first). > > Actually, "when lockd comes up" might be an appropriate moment to > copy the value of this variable. > >> As this requires a root user doing something wrong, > > Or a bug in rpc.statd or sm-notify... > >> fixing this bug >> probably isn't high priority enough to block the rest of the ipv6 >> patches, so we could make a note of the problem and move on for now. >> >> --b. >> >>> If the setting of nsm_use_hostnames is changed between the time the >>> kernel sends an NSMPROC_MON request and the time it sends the >>> NSMPROC_UNMON request for the same peer, the "mon_name" argument for >>> these two requests may not be the same. This is because the value >>> of >>> "mon_name" is currently chosen at the moment the call is made >>> based on >>> the setting of nsm_use_hostnames >>> >>> To ensure both requests pass identical contents in the "mon_name" >>> argument, we now select which string to use for the argument in the >>> nsm_monitor() function. A pointer to this string is saved in the >>> nsm_handle so it can be used for the subsequent NSMPROC_UNMON >>> upcall. >>> >>> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> >>> --- >>> >>> fs/lockd/mon.c | 45 ++++++++++++++++ >>> +-------------------------- >>> include/linux/lockd/lockd.h | 1 + >>> 2 files changed, 19 insertions(+), 27 deletions(-) >>> >>> diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c >>> index 4e7e958..a606fbb 100644 >>> --- a/fs/lockd/mon.c >>> +++ b/fs/lockd/mon.c >>> @@ -18,8 +18,6 @@ >>> >>> #define NLMDBG_FACILITY NLMDBG_MONITOR >>> >>> -#define XDR_ADDRBUF_LEN (20) >>> - >>> static struct rpc_clnt * nsm_create(void); >>> >>> static struct rpc_program nsm_program; >>> @@ -37,7 +35,13 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, >>> struct nsm_res *res) >>> { >>> struct rpc_clnt *clnt; >>> int status; >>> - struct nsm_args args; >>> + struct nsm_args args = { >>> + .addr = nsm_addr_in(nsm)->sin_addr.s_addr, >>> + .prog = NLM_PROGRAM, >>> + .vers = 3, >>> + .proc = NLMPROC_NSM_NOTIFY, >>> + .mon_name = nsm->sm_mon_name, >>> + }; >>> struct rpc_message msg = { >>> .rpc_argp = &args, >>> .rpc_resp = res, >>> @@ -46,22 +50,18 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 >>> proc, struct nsm_res *res) >>> clnt = nsm_create(); >>> if (IS_ERR(clnt)) { >>> status = PTR_ERR(clnt); >>> + dprintk("lockd: failed to create NSM upcall transport, " >>> + "status=%d\n", status); >>> goto out; >>> } >>> >>> - memset(&args, 0, sizeof(args)); >>> - args.mon_name = nsm->sm_name; >>> - args.addr = nsm_addr_in(nsm)->sin_addr.s_addr; >>> - args.prog = NLM_PROGRAM; >>> - args.vers = 3; >>> - args.proc = NLMPROC_NSM_NOTIFY; >>> memset(res, 0, sizeof(*res)); >>> >>> msg.rpc_proc = &clnt->cl_procinfo[proc]; >>> status = rpc_call_sync(clnt, &msg, 0); >>> if (status < 0) >>> - printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", >>> - status); >>> + dprintk("lockd: NSM upcall RPC failed, status=%d\n", >>> + status); >>> else >>> status = 0; >>> rpc_shutdown_client(clnt); >>> @@ -85,6 +85,12 @@ nsm_monitor(struct nlm_host *host) >>> if (nsm->sm_monitored) >>> return 0; >>> >>> + /* >>> + * Choose whether to record the caller_name or IP address of >>> + * this peer in the local rpc.statd's database. >>> + */ >>> + nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm- >>> >sm_addrbuf; >>> + >>> status = nsm_mon_unmon(nsm, SM_MON, &res); >>> >>> if (status < 0 || res.status != 0) >>> @@ -165,25 +171,10 @@ static __be32 *xdr_encode_nsm_string(__be32 >>> *p, char *string) >>> >>> /* >>> * "mon_name" specifies the host to be monitored. >>> - * >>> - * Linux uses a text version of the IP address of the remote >>> - * host as the host identifier (the "mon_name" argument). >>> - * >>> - * Linux statd always looks up the canonical hostname first for >>> - * whatever remote hostname it receives, so this works alright. >>> */ >>> static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) >>> { >>> - char buffer[XDR_ADDRBUF_LEN + 1]; >>> - char *name = argp->mon_name; >>> - >>> - if (!nsm_use_hostnames) { >>> - snprintf(buffer, XDR_ADDRBUF_LEN, >>> - NIPQUAD_FMT, NIPQUAD(argp->addr)); >>> - name = buffer; >>> - } >>> - >>> - return xdr_encode_nsm_string(p, name); >>> + return xdr_encode_nsm_string(p, argp->mon_name); >>> } >>> >>> /* >>> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/ >>> lockd.h >>> index 307a8f0..de9ea7b 100644 >>> --- a/include/linux/lockd/lockd.h >>> +++ b/include/linux/lockd/lockd.h >>> @@ -73,6 +73,7 @@ struct nsm_handle { >>> char * sm_name; >>> struct sockaddr_storage sm_addr; >>> size_t sm_addrlen; >>> + char * sm_mon_name; >>> unsigned int sm_monitored : 1, >>> sm_sticky : 1; /* don't unmonitor */ >>> char sm_addrbuf[63]; /* presentation address */ >>> > > -- > Chuck Lever > chuck[dot]lever[at]oracle[dot]com > -- > To unsubscribe from this list: send the line "unsubscribe linux-nfs" > in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Chuck Lever chuck[dot]lever[at]oracle[dot]com ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 4/6] NLM: Clean up nsm_monitor() call [not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> ` (2 preceding siblings ...) 2008-12-01 18:57 ` [PATCH 3/6] NSM: Support IPv6 version of mon_name Chuck Lever @ 2008-12-01 18:57 ` Chuck Lever [not found] ` <20081201185757.10600.38854.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 2008-12-01 18:58 ` [PATCH 5/6] " Chuck Lever 2008-12-01 18:58 ` [PATCH 6/6] NSM: Serialize SM_MON and SM_UNMON upcalls Chuck Lever 5 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-01 18:57 UTC (permalink / raw) To: bfields, trond.myklebust; +Cc: linux-nfs Clean up: A few minor clean-ups for nsm_monitor(): o Make sure to return an error if the SM_MON call result is not zero. o Remove the BUG_ON() -- the code will die anyway if nsm is NULL. o Use nsm->sm_name instead of host->h_name to be consistent with other functions in fs/lockd/mon.c. o Collect the public declaration of nsm_monitor() in lockd.h with other NSM public function declarations (eg. nsm_release). o Add documenting comments. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/lockd/mon.c | 29 ++++++++++++++++++----------- include/linux/lockd/lockd.h | 4 ++++ include/linux/lockd/sm_inter.h | 1 - 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index a606fbb..78d5f59 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -69,18 +69,24 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) return status; } -/* - * Set up monitoring of a remote host +/** + * nsm_monitor - Notify a peer in case we reboot + * @host: pointer to nlm_host of peer to notify + * + * If this peer is not already monitored, this function sends an + * upcall to the local rpc.statd to record the name/address of + * the peer to notify in case we reboot. + * + * Returns zero if the peer is monitored by the local rpc.statd; + * otherwise a negative errno value is returned. */ -int -nsm_monitor(struct nlm_host *host) +int nsm_monitor(const struct nlm_host *host) { struct nsm_handle *nsm = host->h_nsmhandle; - struct nsm_res res; - int status; + struct nsm_res res; + int status; - dprintk("lockd: nsm_monitor(%s)\n", host->h_name); - BUG_ON(nsm == NULL); + dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); if (nsm->sm_monitored) return 0; @@ -92,9 +98,10 @@ nsm_monitor(struct nlm_host *host) nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; status = nsm_mon_unmon(nsm, SM_MON, &res); - - if (status < 0 || res.status != 0) - printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); + if (res.status != 0) + status = -EIO; + if (status < 0) + printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); else nsm->sm_monitored = 1; return status; diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index de9ea7b..4ca6f39 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -233,6 +233,10 @@ extern void nlm_host_rebooted(const struct sockaddr_in *, const char *, unsigned int, u32); void nsm_release(struct nsm_handle *); +/* + * Host monitoring + */ +int nsm_monitor(const struct nlm_host *host); /* * This is used in garbage collection and resource reclaim diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h index 5a5448b..546b610 100644 --- a/include/linux/lockd/sm_inter.h +++ b/include/linux/lockd/sm_inter.h @@ -41,7 +41,6 @@ struct nsm_res { u32 state; }; -int nsm_monitor(struct nlm_host *); int nsm_unmonitor(struct nlm_host *); extern int nsm_local_state; ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20081201185757.10600.38854.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>]
* Re: [PATCH 4/6] NLM: Clean up nsm_monitor() call [not found] ` <20081201185757.10600.38854.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> @ 2008-12-03 21:08 ` J. Bruce Fields 2008-12-03 21:20 ` Chuck Lever 0 siblings, 1 reply; 20+ messages in thread From: J. Bruce Fields @ 2008-12-03 21:08 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Mon, Dec 01, 2008 at 01:57:58PM -0500, Chuck Lever wrote: > Clean up: A few minor clean-ups for nsm_monitor(): All looks fine, thanks, however: > > o Make sure to return an error if the SM_MON call result is not zero. I'd prefer to have a change in behavior split out into a separate patch from pure cleanup. --b. > > o Remove the BUG_ON() -- the code will die anyway if nsm is NULL. > > o Use nsm->sm_name instead of host->h_name to be consistent with > other functions in fs/lockd/mon.c. > > o Collect the public declaration of nsm_monitor() in lockd.h with > other NSM public function declarations (eg. nsm_release). > > o Add documenting comments. > > Signed-off-by: Chuck Lever <chuck.lever@oracle.com> > --- > > fs/lockd/mon.c | 29 ++++++++++++++++++----------- > include/linux/lockd/lockd.h | 4 ++++ > include/linux/lockd/sm_inter.h | 1 - > 3 files changed, 22 insertions(+), 12 deletions(-) > > diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c > index a606fbb..78d5f59 100644 > --- a/fs/lockd/mon.c > +++ b/fs/lockd/mon.c > @@ -69,18 +69,24 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) > return status; > } > > -/* > - * Set up monitoring of a remote host > +/** > + * nsm_monitor - Notify a peer in case we reboot > + * @host: pointer to nlm_host of peer to notify > + * > + * If this peer is not already monitored, this function sends an > + * upcall to the local rpc.statd to record the name/address of > + * the peer to notify in case we reboot. > + * > + * Returns zero if the peer is monitored by the local rpc.statd; > + * otherwise a negative errno value is returned. > */ > -int > -nsm_monitor(struct nlm_host *host) > +int nsm_monitor(const struct nlm_host *host) > { > struct nsm_handle *nsm = host->h_nsmhandle; > - struct nsm_res res; > - int status; > + struct nsm_res res; > + int status; > > - dprintk("lockd: nsm_monitor(%s)\n", host->h_name); > - BUG_ON(nsm == NULL); > + dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); > > if (nsm->sm_monitored) > return 0; > @@ -92,9 +98,10 @@ nsm_monitor(struct nlm_host *host) > nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; > > status = nsm_mon_unmon(nsm, SM_MON, &res); > - > - if (status < 0 || res.status != 0) > - printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); > + if (res.status != 0) > + status = -EIO; > + if (status < 0) > + printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); > else > nsm->sm_monitored = 1; > return status; > diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h > index de9ea7b..4ca6f39 100644 > --- a/include/linux/lockd/lockd.h > +++ b/include/linux/lockd/lockd.h > @@ -233,6 +233,10 @@ extern void nlm_host_rebooted(const struct sockaddr_in *, const char *, > unsigned int, u32); > void nsm_release(struct nsm_handle *); > > +/* > + * Host monitoring > + */ > +int nsm_monitor(const struct nlm_host *host); > > /* > * This is used in garbage collection and resource reclaim > diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h > index 5a5448b..546b610 100644 > --- a/include/linux/lockd/sm_inter.h > +++ b/include/linux/lockd/sm_inter.h > @@ -41,7 +41,6 @@ struct nsm_res { > u32 state; > }; > > -int nsm_monitor(struct nlm_host *); > int nsm_unmonitor(struct nlm_host *); > extern int nsm_local_state; > > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 4/6] NLM: Clean up nsm_monitor() call 2008-12-03 21:08 ` J. Bruce Fields @ 2008-12-03 21:20 ` Chuck Lever 0 siblings, 0 replies; 20+ messages in thread From: Chuck Lever @ 2008-12-03 21:20 UTC (permalink / raw) To: J. Bruce Fields; +Cc: trond.myklebust, linux-nfs On Dec 3, 2008, at 4:08 PM, J. Bruce Fields wrote: > On Mon, Dec 01, 2008 at 01:57:58PM -0500, Chuck Lever wrote: >> Clean up: A few minor clean-ups for nsm_monitor(): > > All looks fine, thanks, however: > >> >> o Make sure to return an error if the SM_MON call result is not >> zero. > > I'd prefer to have a change in behavior split out into a separate > patch > from pure cleanup. That's fine. I will probably end up reposting this series with your comments addressed, so I will split this one out. > --b. > >> >> o Remove the BUG_ON() -- the code will die anyway if nsm is NULL. >> >> o Use nsm->sm_name instead of host->h_name to be consistent with >> other functions in fs/lockd/mon.c. >> >> o Collect the public declaration of nsm_monitor() in lockd.h with >> other NSM public function declarations (eg. nsm_release). >> >> o Add documenting comments. >> >> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> >> --- >> >> fs/lockd/mon.c | 29 ++++++++++++++++++----------- >> include/linux/lockd/lockd.h | 4 ++++ >> include/linux/lockd/sm_inter.h | 1 - >> 3 files changed, 22 insertions(+), 12 deletions(-) >> >> diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c >> index a606fbb..78d5f59 100644 >> --- a/fs/lockd/mon.c >> +++ b/fs/lockd/mon.c >> @@ -69,18 +69,24 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, >> struct nsm_res *res) >> return status; >> } >> >> -/* >> - * Set up monitoring of a remote host >> +/** >> + * nsm_monitor - Notify a peer in case we reboot >> + * @host: pointer to nlm_host of peer to notify >> + * >> + * If this peer is not already monitored, this function sends an >> + * upcall to the local rpc.statd to record the name/address of >> + * the peer to notify in case we reboot. >> + * >> + * Returns zero if the peer is monitored by the local rpc.statd; >> + * otherwise a negative errno value is returned. >> */ >> -int >> -nsm_monitor(struct nlm_host *host) >> +int nsm_monitor(const struct nlm_host *host) >> { >> struct nsm_handle *nsm = host->h_nsmhandle; >> - struct nsm_res res; >> - int status; >> + struct nsm_res res; >> + int status; >> >> - dprintk("lockd: nsm_monitor(%s)\n", host->h_name); >> - BUG_ON(nsm == NULL); >> + dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); >> >> if (nsm->sm_monitored) >> return 0; >> @@ -92,9 +98,10 @@ nsm_monitor(struct nlm_host *host) >> nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm- >> >sm_addrbuf; >> >> status = nsm_mon_unmon(nsm, SM_MON, &res); >> - >> - if (status < 0 || res.status != 0) >> - printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); >> + if (res.status != 0) >> + status = -EIO; >> + if (status < 0) >> + printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); >> else >> nsm->sm_monitored = 1; >> return status; >> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/ >> lockd.h >> index de9ea7b..4ca6f39 100644 >> --- a/include/linux/lockd/lockd.h >> +++ b/include/linux/lockd/lockd.h >> @@ -233,6 +233,10 @@ extern void nlm_host_rebooted(const struct >> sockaddr_in *, const char *, >> unsigned int, u32); >> void nsm_release(struct nsm_handle *); >> >> +/* >> + * Host monitoring >> + */ >> +int nsm_monitor(const struct nlm_host *host); >> >> /* >> * This is used in garbage collection and resource reclaim >> diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/ >> sm_inter.h >> index 5a5448b..546b610 100644 >> --- a/include/linux/lockd/sm_inter.h >> +++ b/include/linux/lockd/sm_inter.h >> @@ -41,7 +41,6 @@ struct nsm_res { >> u32 state; >> }; >> >> -int nsm_monitor(struct nlm_host *); >> int nsm_unmonitor(struct nlm_host *); >> extern int nsm_local_state; >> >> -- Chuck Lever chuck[dot]lever[at]oracle[dot]com ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 5/6] NLM: Clean up nsm_monitor() call [not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> ` (3 preceding siblings ...) 2008-12-01 18:57 ` [PATCH 4/6] NLM: Clean up nsm_monitor() call Chuck Lever @ 2008-12-01 18:58 ` Chuck Lever [not found] ` <20081201185805.10600.23630.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 2008-12-01 18:58 ` [PATCH 6/6] NSM: Serialize SM_MON and SM_UNMON upcalls Chuck Lever 5 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-01 18:58 UTC (permalink / raw) To: bfields, trond.myklebust; +Cc: linux-nfs Clean up: A few minor clean-ups for nsm_unmonitor(): o Arrange dprintk and check of sm_monitored consistently with nsm_monitor(). o nsm_unmonitor()'s only caller doesn't care about the return code, so eliminate it (thanks, Bruce). o The nsm_handle's reference count is bumped in nlm_lookup_host() so it should be decremented in nlm_destroy_host() to make it easier to see the balance of these two operations. For the moment we leave nsm_release() public. o Use nsm->sm_name instead of host->h_name to be consistent with other functions in fs/lockd/mon.c. o Collect the public declaration of nsm_unmonitor() in lockd.h with other NSM public function declarations. o Add documenting comments. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/lockd/host.c | 7 +++---- fs/lockd/mon.c | 33 +++++++++++++++------------------ include/linux/lockd/lockd.h | 1 + include/linux/lockd/sm_inter.h | 1 - 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/fs/lockd/host.c b/fs/lockd/host.c index cd7edc3..8d26d0c 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -263,10 +263,9 @@ nlm_destroy_host(struct nlm_host *host) BUG_ON(!list_empty(&host->h_lockowners)); BUG_ON(atomic_read(&host->h_count)); - /* - * Release NSM handle and unmonitor host. - */ - nsm_unmonitor(host); + nsm_unmonitor(host->h_nsmhandle); + nsm_release(host->h_nsmhandle); + host->h_nsmhandle = NULL; clnt = host->h_rpcclnt; if (clnt != NULL) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 78d5f59..b76d9b2 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -107,33 +107,30 @@ int nsm_monitor(const struct nlm_host *host) return status; } -/* - * Cease to monitor remote host +/** + * nsm_unmonitor - Unregister peer notification + * @nsm: pointer to nsm_handle of peer to stop monitoring + * + * If this peer is monitored, this function sends an upcall to + * tell the local rpc.statd not to send this peer a notification + * when we reboot. */ -int -nsm_unmonitor(struct nlm_host *host) +void nsm_unmonitor(struct nsm_handle *nsm) { - struct nsm_handle *nsm = host->h_nsmhandle; - struct nsm_res res; - int status = 0; + struct nsm_res res; - if (nsm == NULL) - return 0; - host->h_nsmhandle = NULL; + dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); - if (atomic_read(&nsm->sm_count) == 1 - && nsm->sm_monitored && !nsm->sm_sticky) { - dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); + if (!nsm->sm_monitored) + return; - status = nsm_mon_unmon(nsm, SM_UNMON, &res); - if (status < 0) + if (atomic_read(&nsm->sm_count) == 1 && !nsm->sm_sticky) { + if (nsm_mon_unmon(nsm, SM_UNMON, &res) < 0) printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", - host->h_name); + nsm->sm_name); else nsm->sm_monitored = 0; } - nsm_release(nsm); - return status; } /* diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 4ca6f39..e2fa968 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -237,6 +237,7 @@ void nsm_release(struct nsm_handle *); * Host monitoring */ int nsm_monitor(const struct nlm_host *host); +void nsm_unmonitor(struct nsm_handle *nsm); /* * This is used in garbage collection and resource reclaim diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h index 546b610..896a5e3 100644 --- a/include/linux/lockd/sm_inter.h +++ b/include/linux/lockd/sm_inter.h @@ -41,7 +41,6 @@ struct nsm_res { u32 state; }; -int nsm_unmonitor(struct nlm_host *); extern int nsm_local_state; #endif /* LINUX_LOCKD_SM_INTER_H */ ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20081201185805.10600.23630.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>]
* Re: [PATCH 5/6] NLM: Clean up nsm_monitor() call [not found] ` <20081201185805.10600.23630.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> @ 2008-12-03 21:28 ` J. Bruce Fields 0 siblings, 0 replies; 20+ messages in thread From: J. Bruce Fields @ 2008-12-03 21:28 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Mon, Dec 01, 2008 at 01:58:05PM -0500, Chuck Lever wrote: > Clean up: A few minor clean-ups for nsm_unmonitor(): Looks fine, but might prefer this slightly finer-grained: > > o Arrange dprintk and check of sm_monitored consistently with > nsm_monitor(). > > o nsm_unmonitor()'s only caller doesn't care about the return code, > so eliminate it (thanks, Bruce). > > o The nsm_handle's reference count is bumped in nlm_lookup_host() > so it should be decremented in nlm_destroy_host() to make it > easier to see the balance of these two operations. For the > moment we leave nsm_release() public. That might be a candidate to split out as a separate patch. > diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c > index 78d5f59..b76d9b2 100644 > --- a/fs/lockd/mon.c > +++ b/fs/lockd/mon.c > @@ -107,33 +107,30 @@ int nsm_monitor(const struct nlm_host *host) > return status; > } > > -/* > - * Cease to monitor remote host > +/** > + * nsm_unmonitor - Unregister peer notification > + * @nsm: pointer to nsm_handle of peer to stop monitoring > + * > + * If this peer is monitored, this function sends an upcall to > + * tell the local rpc.statd not to send this peer a notification > + * when we reboot. > */ > -int > -nsm_unmonitor(struct nlm_host *host) > +void nsm_unmonitor(struct nsm_handle *nsm) > { > - struct nsm_handle *nsm = host->h_nsmhandle; > - struct nsm_res res; > - int status = 0; > + struct nsm_res res; > > - if (nsm == NULL) > - return 0; Hm. Yeah, can't see how it could ever have been called with NULL--might be worth a changelog comment, though. --b. > - host->h_nsmhandle = NULL; > + dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); > > - if (atomic_read(&nsm->sm_count) == 1 > - && nsm->sm_monitored && !nsm->sm_sticky) { > - dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); > + if (!nsm->sm_monitored) > + return; > > - status = nsm_mon_unmon(nsm, SM_UNMON, &res); > - if (status < 0) > + if (atomic_read(&nsm->sm_count) == 1 && !nsm->sm_sticky) { > + if (nsm_mon_unmon(nsm, SM_UNMON, &res) < 0) > printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", > - host->h_name); > + nsm->sm_name); > else > nsm->sm_monitored = 0; > } > - nsm_release(nsm); > - return status; > } > > /* > diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h > index 4ca6f39..e2fa968 100644 > --- a/include/linux/lockd/lockd.h > +++ b/include/linux/lockd/lockd.h > @@ -237,6 +237,7 @@ void nsm_release(struct nsm_handle *); > * Host monitoring > */ > int nsm_monitor(const struct nlm_host *host); > +void nsm_unmonitor(struct nsm_handle *nsm); > > /* > * This is used in garbage collection and resource reclaim > diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h > index 546b610..896a5e3 100644 > --- a/include/linux/lockd/sm_inter.h > +++ b/include/linux/lockd/sm_inter.h > @@ -41,7 +41,6 @@ struct nsm_res { > u32 state; > }; > > -int nsm_unmonitor(struct nlm_host *); > extern int nsm_local_state; > > #endif /* LINUX_LOCKD_SM_INTER_H */ > ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 6/6] NSM: Serialize SM_MON and SM_UNMON upcalls [not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> ` (4 preceding siblings ...) 2008-12-01 18:58 ` [PATCH 5/6] " Chuck Lever @ 2008-12-01 18:58 ` Chuck Lever [not found] ` <20081201185812.10600.92501.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> 5 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-01 18:58 UTC (permalink / raw) To: bfields, trond.myklebust; +Cc: linux-nfs The Linux NSM implementation currently does nothing to prevent concurrent SM_MON and SM_UNMON upcalls regarding the same peer. Races could cause duplicate SM_MON upcalls for the same peer, or locking activity during server shutdown might cause SM_MON and SM_UNMON upcalls to occur in an arbitrary order. To avoid confusing rpc.statd, add a per-nsm_handle mutex to serialize the upcalls. To prevent duplicate upcalls, the mutex is held while the upcall is outstanding, and is not released until we can tell if the upcall succeeded. The nsm_monitor() function is called frequently. The extra inline function mitigates the overhead of taking the mutex. It is only taken if the nsm_handle is not already monitored. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/lockd/host.c | 1 + fs/lockd/mon.c | 23 ++++++++++++++++------- include/linux/lockd/lockd.h | 12 +++++++++++- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 8d26d0c..bf705d0 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -697,6 +697,7 @@ retry: nsm->sm_name = (char *) (nsm + 1); memcpy(nsm->sm_name, hostname, hostname_len); nsm->sm_name[hostname_len] = '\0'; + mutex_init(&nsm->sm_mutex); nlm_display_address((struct sockaddr *)&nsm->sm_addr, nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf)); atomic_set(&nsm->sm_count, 1); diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index b76d9b2..301aeb7 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -70,8 +70,8 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) } /** - * nsm_monitor - Notify a peer in case we reboot - * @host: pointer to nlm_host of peer to notify + * __nsm_monitor - Notify a peer in case we reboot + * @nsm: pointer to nsm_handle of peer to notify * * If this peer is not already monitored, this function sends an * upcall to the local rpc.statd to record the name/address of @@ -80,16 +80,17 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) * Returns zero if the peer is monitored by the local rpc.statd; * otherwise a negative errno value is returned. */ -int nsm_monitor(const struct nlm_host *host) +int __nsm_monitor(struct nsm_handle *nsm) { - struct nsm_handle *nsm = host->h_nsmhandle; struct nsm_res res; - int status; + int status = 0; dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); + mutex_lock(&nsm->sm_mutex); + if (nsm->sm_monitored) - return 0; + goto out; /* * Choose whether to record the caller_name or IP address of @@ -104,6 +105,9 @@ int nsm_monitor(const struct nlm_host *host) printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); else nsm->sm_monitored = 1; + +out: + mutex_unlock(&nsm->sm_mutex); return status; } @@ -121,8 +125,10 @@ void nsm_unmonitor(struct nsm_handle *nsm) dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); + mutex_lock(&nsm->sm_mutex); + if (!nsm->sm_monitored) - return; + goto out; if (atomic_read(&nsm->sm_count) == 1 && !nsm->sm_sticky) { if (nsm_mon_unmon(nsm, SM_UNMON, &res) < 0) @@ -131,6 +137,9 @@ void nsm_unmonitor(struct nsm_handle *nsm) else nsm->sm_monitored = 0; } + +out: + mutex_unlock(&nsm->sm_mutex); } /* diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index e2fa968..bf6c1c1 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -76,6 +76,7 @@ struct nsm_handle { char * sm_mon_name; unsigned int sm_monitored : 1, sm_sticky : 1; /* don't unmonitor */ + struct mutex sm_mutex; char sm_addrbuf[63]; /* presentation address */ }; @@ -236,9 +237,18 @@ void nsm_release(struct nsm_handle *); /* * Host monitoring */ -int nsm_monitor(const struct nlm_host *host); +int __nsm_monitor(struct nsm_handle *nsm); void nsm_unmonitor(struct nsm_handle *nsm); +static inline int nsm_monitor(const struct nlm_host *host) +{ + struct nsm_handle *nsm = host->h_nsmhandle; + + if (likely(nsm->sm_monitored)) + return 0; + return __nsm_monitor(nsm); +} + /* * This is used in garbage collection and resource reclaim * A return value != 0 means destroy the lock/block/share ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20081201185812.10600.92501.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>]
* Re: [PATCH 6/6] NSM: Serialize SM_MON and SM_UNMON upcalls [not found] ` <20081201185812.10600.92501.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org> @ 2008-12-03 21:41 ` J. Bruce Fields 2008-12-04 0:38 ` Chuck Lever 0 siblings, 1 reply; 20+ messages in thread From: J. Bruce Fields @ 2008-12-03 21:41 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Mon, Dec 01, 2008 at 01:58:13PM -0500, Chuck Lever wrote: > The Linux NSM implementation currently does nothing to prevent > concurrent SM_MON and SM_UNMON upcalls regarding the same peer. Races > could cause duplicate SM_MON upcalls for the same peer, or locking > activity during server shutdown might cause SM_MON and SM_UNMON upcalls > to occur in an arbitrary order. > > To avoid confusing rpc.statd, add a per-nsm_handle mutex to serialize > the upcalls. To prevent duplicate upcalls, the mutex is held while the > upcall is outstanding, and is not released until we can tell if the > upcall succeeded. > > The nsm_monitor() function is called frequently. The extra inline > function mitigates the overhead of taking the mutex. It is only taken > if the nsm_handle is not already monitored. > > Signed-off-by: Chuck Lever <chuck.lever@oracle.com> ... > diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h > index e2fa968..bf6c1c1 100644 > --- a/include/linux/lockd/lockd.h > +++ b/include/linux/lockd/lockd.h > @@ -76,6 +76,7 @@ struct nsm_handle { > char * sm_mon_name; > unsigned int sm_monitored : 1, > sm_sticky : 1; /* don't unmonitor */ > + struct mutex sm_mutex; > char sm_addrbuf[63]; /* presentation address */ > }; > > @@ -236,9 +237,18 @@ void nsm_release(struct nsm_handle *); > /* > * Host monitoring > */ > -int nsm_monitor(const struct nlm_host *host); > +int __nsm_monitor(struct nsm_handle *nsm); > void nsm_unmonitor(struct nsm_handle *nsm); > > +static inline int nsm_monitor(const struct nlm_host *host) > +{ > + struct nsm_handle *nsm = host->h_nsmhandle; > + > + if (likely(nsm->sm_monitored)) > + return 0; We also need to grep for places where sm_monitored is cleared, and think about what happens in a race between one of those cases and __nsm_monitor(). --b. > + return __nsm_monitor(nsm); > +} > + > /* > * This is used in garbage collection and resource reclaim > * A return value != 0 means destroy the lock/block/share > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 6/6] NSM: Serialize SM_MON and SM_UNMON upcalls 2008-12-03 21:41 ` J. Bruce Fields @ 2008-12-04 0:38 ` Chuck Lever 2008-12-04 3:55 ` J. Bruce Fields 0 siblings, 1 reply; 20+ messages in thread From: Chuck Lever @ 2008-12-04 0:38 UTC (permalink / raw) To: J. Bruce Fields; +Cc: trond.myklebust, linux-nfs On Dec 3, 2008, at Dec 3, 2008, 4:41 PM, J. Bruce Fields wrote: > On Mon, Dec 01, 2008 at 01:58:13PM -0500, Chuck Lever wrote: >> The Linux NSM implementation currently does nothing to prevent >> concurrent SM_MON and SM_UNMON upcalls regarding the same peer. >> Races >> could cause duplicate SM_MON upcalls for the same peer, or locking >> activity during server shutdown might cause SM_MON and SM_UNMON >> upcalls >> to occur in an arbitrary order. >> >> To avoid confusing rpc.statd, add a per-nsm_handle mutex to serialize >> the upcalls. To prevent duplicate upcalls, the mutex is held while >> the >> upcall is outstanding, and is not released until we can tell if the >> upcall succeeded. >> >> The nsm_monitor() function is called frequently. The extra inline >> function mitigates the overhead of taking the mutex. It is only >> taken >> if the nsm_handle is not already monitored. >> >> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> > ... >> diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/ >> lockd.h >> index e2fa968..bf6c1c1 100644 >> --- a/include/linux/lockd/lockd.h >> +++ b/include/linux/lockd/lockd.h >> @@ -76,6 +76,7 @@ struct nsm_handle { >> char * sm_mon_name; >> unsigned int sm_monitored : 1, >> sm_sticky : 1; /* don't unmonitor */ >> + struct mutex sm_mutex; >> char sm_addrbuf[63]; /* presentation address */ >> }; >> >> @@ -236,9 +237,18 @@ void nsm_release(struct nsm_handle *); >> /* >> * Host monitoring >> */ >> -int nsm_monitor(const struct nlm_host *host); >> +int __nsm_monitor(struct nsm_handle *nsm); >> void nsm_unmonitor(struct nsm_handle *nsm); >> >> +static inline int nsm_monitor(const struct nlm_host *host) >> +{ >> + struct nsm_handle *nsm = host->h_nsmhandle; >> + >> + if (likely(nsm->sm_monitored)) >> + return 0; > > We also need to grep for places where sm_monitored is cleared, and > think about what happens in a race between one of those cases and > __nsm_monitor(). It's cleared in nlm_host_rebooted(), and in nsm_unmonitor(). The nlm_host_mutex already provides much the same serialization that is added in this patch, and at least on the server, nlm_lookup_host() and nlm_destroy_host() both run under the BKL. The problem (if there is one) is really in nlm_host_rebooted(), which this patch does nothing about. Let's drop this one for now. I think there is a way to get rpc.statd to report duplicates instead of ignoring them as it does now. We should get an idea of how pervasive this problem really is. > --b. > >> + return __nsm_monitor(nsm); >> +} >> + >> /* >> * This is used in garbage collection and resource reclaim >> * A return value != 0 means destroy the lock/block/share >> -- Chuck Lever chuck[dot]lever[at]oracle[dot]com ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 6/6] NSM: Serialize SM_MON and SM_UNMON upcalls 2008-12-04 0:38 ` Chuck Lever @ 2008-12-04 3:55 ` J. Bruce Fields 0 siblings, 0 replies; 20+ messages in thread From: J. Bruce Fields @ 2008-12-04 3:55 UTC (permalink / raw) To: Chuck Lever; +Cc: trond.myklebust, linux-nfs On Wed, Dec 03, 2008 at 07:38:07PM -0500, Chuck Lever wrote: > It's cleared in nlm_host_rebooted(), and in nsm_unmonitor(). > > The nlm_host_mutex already provides much the same serialization that is > added in this patch, and at least on the server, nlm_lookup_host() and > nlm_destroy_host() both run under the BKL. > > The problem (if there is one) is really in nlm_host_rebooted(), which > this patch does nothing about. > > Let's drop this one for now. I think there is a way to get rpc.statd to > report duplicates instead of ignoring them as it does now. We should get > an idea of how pervasive this problem really is. OK, fair enough. I think it's a good catch, though, and one other motivation is that *someday* (after fixing a bunch of similar locking problems) it would be convenient if lockd could be made multithreaded. And if we haven't seen this particular problem in practice, part of the reason may be that lockd is single-threaded and entirely under the BKL. --b. ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2008-12-04 3:55 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-01 18:57 [PATCH 0/6] First set of patches for 2.6.29 Chuck Lever
[not found] ` <20081201185108.10600.21700.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-01 18:57 ` [PATCH 1/6] NLM: Remove address eye-catcher buffers from nlm_host Chuck Lever
[not found] ` <20081201185734.10600.88841.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-03 19:03 ` J. Bruce Fields
2008-12-03 19:10 ` Chuck Lever
2008-12-01 18:57 ` [PATCH 2/6] NLM: Support IPv6 scope IDs in nlm_display_address() Chuck Lever
[not found] ` <20081201185741.10600.7375.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-03 19:34 ` J. Bruce Fields
2008-12-03 19:46 ` J. Bruce Fields
2008-12-01 18:57 ` [PATCH 3/6] NSM: Support IPv6 version of mon_name Chuck Lever
[not found] ` <20081201185749.10600.38468.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-03 21:01 ` J. Bruce Fields
2008-12-03 21:19 ` Chuck Lever
2008-12-03 21:24 ` Chuck Lever
2008-12-01 18:57 ` [PATCH 4/6] NLM: Clean up nsm_monitor() call Chuck Lever
[not found] ` <20081201185757.10600.38854.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-03 21:08 ` J. Bruce Fields
2008-12-03 21:20 ` Chuck Lever
2008-12-01 18:58 ` [PATCH 5/6] " Chuck Lever
[not found] ` <20081201185805.10600.23630.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-03 21:28 ` J. Bruce Fields
2008-12-01 18:58 ` [PATCH 6/6] NSM: Serialize SM_MON and SM_UNMON upcalls Chuck Lever
[not found] ` <20081201185812.10600.92501.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-03 21:41 ` J. Bruce Fields
2008-12-04 0:38 ` Chuck Lever
2008-12-04 3:55 ` J. Bruce Fields
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.