aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2008-12-05 19:02:45 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-01-06 11:53:53 -0500
commit67c6d107a689243979a2b5f15244b5261634a924 (patch)
tree36e2093df96a449c284640c9cc329fc251e98bd0
parent03eb1dcbb799304b58730f4dba65812f49fb305e (diff)
NSM: Move nsm_find() to fs/lockd/mon.c
The nsm_find() function sets up fresh nsm_handle entries. This is where we will store the "priv" cookie used to lookup nsm_handles during reboot recovery. The cookie will be constructed when nsm_find() creates a new nsm_handle. As much as possible, I would like to keep everything that handles a "priv" cookie in fs/lockd/mon.c so that all the smarts are in one source file. That organization should make it pretty simple to see how all this works. To me, it makes more sense than the current arrangement to keep nsm_find() with nsm_monitor() and nsm_unmonitor(). So, start reorganizing by moving nsm_find() into fs/lockd/mon.c. The nsm_release() function comes along too, since it shares the nsm_lock global variable. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/lockd/host.c128
-rw-r--r--fs/lockd/mon.c133
-rw-r--r--include/linux/lockd/lockd.h6
3 files changed, 139 insertions, 128 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 1d523c1a7b62..dbdeaa88d2fa 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -32,12 +32,6 @@ static int nrhosts;
32static DEFINE_MUTEX(nlm_host_mutex); 32static DEFINE_MUTEX(nlm_host_mutex);
33 33
34static void nlm_gc_hosts(void); 34static void nlm_gc_hosts(void);
35static struct nsm_handle *nsm_find(const struct sockaddr *sap,
36 const size_t salen,
37 const char *hostname,
38 const size_t hostname_len,
39 const int create);
40static void nsm_release(struct nsm_handle *nsm);
41 35
42struct nlm_lookup_host_info { 36struct nlm_lookup_host_info {
43 const int server; /* search for server|client */ 37 const int server; /* search for server|client */
@@ -106,43 +100,6 @@ static void nlm_clear_port(struct sockaddr *sap)
106 } 100 }
107} 101}
108 102
109static void nlm_display_ipv4_address(const struct sockaddr *sap, char *buf,
110 const size_t len)
111{
112 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
113 snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
114}
115
116static void nlm_display_ipv6_address(const struct sockaddr *sap, char *buf,
117 const size_t len)
118{
119 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
120
121 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
122 snprintf(buf, len, "%pI4", &sin6->sin6_addr.s6_addr32[3]);
123 else if (sin6->sin6_scope_id != 0)
124 snprintf(buf, len, "%pI6%%%u", &sin6->sin6_addr,
125 sin6->sin6_scope_id);
126 else
127 snprintf(buf, len, "%pI6", &sin6->sin6_addr);
128}
129
130static void nlm_display_address(const struct sockaddr *sap,
131 char *buf, const size_t len)
132{
133 switch (sap->sa_family) {
134 case AF_INET:
135 nlm_display_ipv4_address(sap, buf, len);
136 break;
137 case AF_INET6:
138 nlm_display_ipv6_address(sap, buf, len);
139 break;
140 default:
141 snprintf(buf, len, "unsupported address family");
142 break;
143 }
144}
145
146/* 103/*
147 * Common host lookup routine for server & client 104 * Common host lookup routine for server & client
148 */ 105 */
@@ -635,88 +592,3 @@ nlm_gc_hosts(void)
635 592
636 next_gc = jiffies + NLM_HOST_COLLECT; 593 next_gc = jiffies + NLM_HOST_COLLECT;
637} 594}
638
639
640/*
641 * Manage NSM handles
642 */
643static LIST_HEAD(nsm_handles);
644static DEFINE_SPINLOCK(nsm_lock);
645
646static struct nsm_handle *nsm_find(const struct sockaddr *sap,
647 const size_t salen,
648 const char *hostname,
649 const size_t hostname_len,
650 const int create)
651{
652 struct nsm_handle *nsm = NULL;
653 struct nsm_handle *pos;
654
655 if (!sap)
656 return NULL;
657
658 if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
659 if (printk_ratelimit()) {
660 printk(KERN_WARNING "Invalid hostname \"%.*s\" "
661 "in NFS lock request\n",
662 (int)hostname_len, hostname);
663 }
664 return NULL;
665 }
666
667retry:
668 spin_lock(&nsm_lock);
669 list_for_each_entry(pos, &nsm_handles, sm_link) {
670
671 if (hostname && nsm_use_hostnames) {
672 if (strlen(pos->sm_name) != hostname_len
673 || memcmp(pos->sm_name, hostname, hostname_len))
674 continue;
675 } else if (!nlm_cmp_addr(nsm_addr(pos), sap))
676 continue;
677 atomic_inc(&pos->sm_count);
678 kfree(nsm);
679 nsm = pos;
680 goto found;
681 }
682 if (nsm) {
683 list_add(&nsm->sm_link, &nsm_handles);
684 goto found;
685 }
686 spin_unlock(&nsm_lock);
687
688 if (!create)
689 return NULL;
690
691 nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
692 if (nsm == NULL)
693 return NULL;
694
695 memcpy(nsm_addr(nsm), sap, salen);
696 nsm->sm_addrlen = salen;
697 nsm->sm_name = (char *) (nsm + 1);
698 memcpy(nsm->sm_name, hostname, hostname_len);
699 nsm->sm_name[hostname_len] = '\0';
700 nlm_display_address((struct sockaddr *)&nsm->sm_addr,
701 nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf));
702 atomic_set(&nsm->sm_count, 1);
703 goto retry;
704
705found:
706 spin_unlock(&nsm_lock);
707 return nsm;
708}
709
710/*
711 * Release an NSM handle
712 */
713static void nsm_release(struct nsm_handle *nsm)
714{
715 if (!nsm)
716 return;
717 if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
718 list_del(&nsm->sm_link);
719 spin_unlock(&nsm_lock);
720 kfree(nsm);
721 }
722}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 81e1cc14246f..8e68e799293c 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -47,12 +47,51 @@ struct nsm_res {
47static struct rpc_clnt * nsm_create(void); 47static struct rpc_clnt * nsm_create(void);
48 48
49static struct rpc_program nsm_program; 49static struct rpc_program nsm_program;
50static LIST_HEAD(nsm_handles);
51static DEFINE_SPINLOCK(nsm_lock);
50 52
51/* 53/*
52 * Local NSM state 54 * Local NSM state
53 */ 55 */
54int nsm_local_state; 56int nsm_local_state;
55 57
58static void nsm_display_ipv4_address(const struct sockaddr *sap, char *buf,
59 const size_t len)
60{
61 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
62 snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
63}
64
65static void nsm_display_ipv6_address(const struct sockaddr *sap, char *buf,
66 const size_t len)
67{
68 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
69
70 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
71 snprintf(buf, len, "%pI4", &sin6->sin6_addr.s6_addr32[3]);
72 else if (sin6->sin6_scope_id != 0)
73 snprintf(buf, len, "%pI6%%%u", &sin6->sin6_addr,
74 sin6->sin6_scope_id);
75 else
76 snprintf(buf, len, "%pI6", &sin6->sin6_addr);
77}
78
79static void nsm_display_address(const struct sockaddr *sap,
80 char *buf, const size_t len)
81{
82 switch (sap->sa_family) {
83 case AF_INET:
84 nsm_display_ipv4_address(sap, buf, len);
85 break;
86 case AF_INET6:
87 nsm_display_ipv6_address(sap, buf, len);
88 break;
89 default:
90 snprintf(buf, len, "unsupported address family");
91 break;
92 }
93}
94
56/* 95/*
57 * Common procedure for NSMPROC_MON/NSMPROC_UNMON calls 96 * Common procedure for NSMPROC_MON/NSMPROC_UNMON calls
58 */ 97 */
@@ -162,6 +201,100 @@ void nsm_unmonitor(const struct nlm_host *host)
162 } 201 }
163} 202}
164 203
204/**
205 * nsm_find - Find or create a cached nsm_handle
206 * @sap: pointer to socket address of handle to find
207 * @salen: length of socket address
208 * @hostname: pointer to C string containing hostname to find
209 * @hostname_len: length of C string
210 * @create: one means create new handle if not found in cache
211 *
212 * Behavior is modulated by the global nsm_use_hostnames variable
213 * and by the @create argument.
214 *
215 * Returns a cached nsm_handle after bumping its ref count, or if
216 * @create is set, returns a fresh nsm_handle if a handle that
217 * matches @sap and/or @hostname cannot be found in the handle cache.
218 * Returns NULL if an error occurs.
219 */
220struct nsm_handle *nsm_find(const struct sockaddr *sap, const size_t salen,
221 const char *hostname, const size_t hostname_len,
222 const int create)
223{
224 struct nsm_handle *nsm = NULL;
225 struct nsm_handle *pos;
226
227 if (!sap)
228 return NULL;
229
230 if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
231 if (printk_ratelimit()) {
232 printk(KERN_WARNING "Invalid hostname \"%.*s\" "
233 "in NFS lock request\n",
234 (int)hostname_len, hostname);
235 }
236 return NULL;
237 }
238
239retry:
240 spin_lock(&nsm_lock);
241 list_for_each_entry(pos, &nsm_handles, sm_link) {
242
243 if (hostname && nsm_use_hostnames) {
244 if (strlen(pos->sm_name) != hostname_len
245 || memcmp(pos->sm_name, hostname, hostname_len))
246 continue;
247 } else if (!nlm_cmp_addr(nsm_addr(pos), sap))
248 continue;
249 atomic_inc(&pos->sm_count);
250 kfree(nsm);
251 nsm = pos;
252 goto found;
253 }
254 if (nsm) {
255 list_add(&nsm->sm_link, &nsm_handles);
256 goto found;
257 }
258 spin_unlock(&nsm_lock);
259
260 if (!create)
261 return NULL;
262
263 nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
264 if (nsm == NULL)
265 return NULL;
266
267 memcpy(nsm_addr(nsm), sap, salen);
268 nsm->sm_addrlen = salen;
269 nsm->sm_name = (char *) (nsm + 1);
270 memcpy(nsm->sm_name, hostname, hostname_len);
271 nsm->sm_name[hostname_len] = '\0';
272 nsm_display_address((struct sockaddr *)&nsm->sm_addr,
273 nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf));
274 atomic_set(&nsm->sm_count, 1);
275 goto retry;
276
277found:
278 spin_unlock(&nsm_lock);
279 return nsm;
280}
281
282/**
283 * nsm_release - Release an NSM handle
284 * @nsm: pointer to handle to be released
285 *
286 */
287void nsm_release(struct nsm_handle *nsm)
288{
289 if (!nsm)
290 return;
291 if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
292 list_del(&nsm->sm_link);
293 spin_unlock(&nsm_lock);
294 kfree(nsm);
295 }
296}
297
165/* 298/*
166 * Create NSM client for the local host 299 * Create NSM client for the local host
167 */ 300 */
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 38344bfb814a..8d715363c6ac 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -247,6 +247,12 @@ extern void nlm_host_rebooted(const struct sockaddr_in *, const char *,
247int nsm_monitor(const struct nlm_host *host); 247int nsm_monitor(const struct nlm_host *host);
248void nsm_unmonitor(const struct nlm_host *host); 248void nsm_unmonitor(const struct nlm_host *host);
249 249
250struct nsm_handle *nsm_find(const struct sockaddr *sap, const size_t salen,
251 const char *hostname,
252 const size_t hostname_len,
253 const int create);
254void nsm_release(struct nsm_handle *nsm);
255
250/* 256/*
251 * This is used in garbage collection and resource reclaim 257 * This is used in garbage collection and resource reclaim
252 * A return value != 0 means destroy the lock/block/share 258 * A return value != 0 means destroy the lock/block/share