NSM: convert printk(KERN_DEBUG) to a dprintk()
[safe/jmp/linux-2.6] / fs / lockd / mon.c
1 /*
2  * linux/fs/lockd/mon.c
3  *
4  * The kernel statd client.
5  *
6  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #include <linux/types.h>
10 #include <linux/utsname.h>
11 #include <linux/kernel.h>
12 #include <linux/sunrpc/clnt.h>
13 #include <linux/sunrpc/xprtsock.h>
14 #include <linux/sunrpc/svc.h>
15 #include <linux/lockd/lockd.h>
16 #include <linux/lockd/sm_inter.h>
17
18
19 #define NLMDBG_FACILITY         NLMDBG_MONITOR
20
21 #define XDR_ADDRBUF_LEN         (20)
22
23 static struct rpc_clnt *        nsm_create(void);
24
25 static struct rpc_program       nsm_program;
26
27 /*
28  * Local NSM state
29  */
30 int                             nsm_local_state;
31
32 /*
33  * Common procedure for SM_MON/SM_UNMON calls
34  */
35 static int
36 nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
37 {
38         struct rpc_clnt *clnt;
39         int             status;
40         struct nsm_args args = {
41                 .addr           = nsm_addr_in(nsm)->sin_addr.s_addr,
42                 .prog           = NLM_PROGRAM,
43                 .vers           = 3,
44                 .proc           = NLMPROC_NSM_NOTIFY,
45                 .mon_name       = nsm->sm_name,
46         };
47         struct rpc_message msg = {
48                 .rpc_argp       = &args,
49                 .rpc_resp       = res,
50         };
51
52         clnt = nsm_create();
53         if (IS_ERR(clnt)) {
54                 status = PTR_ERR(clnt);
55                 dprintk("lockd: failed to create NSM upcall transport, "
56                                 "status=%d\n", status);
57                 goto out;
58         }
59
60         memset(res, 0, sizeof(*res));
61
62         msg.rpc_proc = &clnt->cl_procinfo[proc];
63         status = rpc_call_sync(clnt, &msg, 0);
64         if (status < 0)
65                 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
66                                 status);
67         else
68                 status = 0;
69         rpc_shutdown_client(clnt);
70  out:
71         return status;
72 }
73
74 /*
75  * Set up monitoring of a remote host
76  */
77 int
78 nsm_monitor(struct nlm_host *host)
79 {
80         struct nsm_handle *nsm = host->h_nsmhandle;
81         struct nsm_res  res;
82         int             status;
83
84         dprintk("lockd: nsm_monitor(%s)\n", host->h_name);
85         BUG_ON(nsm == NULL);
86
87         if (nsm->sm_monitored)
88                 return 0;
89
90         status = nsm_mon_unmon(nsm, SM_MON, &res);
91
92         if (status < 0 || res.status != 0)
93                 printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name);
94         else
95                 nsm->sm_monitored = 1;
96         return status;
97 }
98
99 /*
100  * Cease to monitor remote host
101  */
102 int
103 nsm_unmonitor(struct nlm_host *host)
104 {
105         struct nsm_handle *nsm = host->h_nsmhandle;
106         struct nsm_res  res;
107         int             status = 0;
108
109         if (nsm == NULL)
110                 return 0;
111         host->h_nsmhandle = NULL;
112
113         if (atomic_read(&nsm->sm_count) == 1
114          && nsm->sm_monitored && !nsm->sm_sticky) {
115                 dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name);
116
117                 status = nsm_mon_unmon(nsm, SM_UNMON, &res);
118                 if (status < 0)
119                         printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
120                                         host->h_name);
121                 else
122                         nsm->sm_monitored = 0;
123         }
124         nsm_release(nsm);
125         return status;
126 }
127
128 /*
129  * Create NSM client for the local host
130  */
131 static struct rpc_clnt *
132 nsm_create(void)
133 {
134         struct sockaddr_in      sin = {
135                 .sin_family     = AF_INET,
136                 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
137                 .sin_port       = 0,
138         };
139         struct rpc_create_args args = {
140                 .protocol       = XPRT_TRANSPORT_UDP,
141                 .address        = (struct sockaddr *)&sin,
142                 .addrsize       = sizeof(sin),
143                 .servername     = "localhost",
144                 .program        = &nsm_program,
145                 .version        = SM_VERSION,
146                 .authflavor     = RPC_AUTH_NULL,
147         };
148
149         return rpc_create(&args);
150 }
151
152 /*
153  * XDR functions for NSM.
154  *
155  * See http://www.opengroup.org/ for details on the Network
156  * Status Monitor wire protocol.
157  */
158
159 static __be32 *xdr_encode_nsm_string(__be32 *p, char *string)
160 {
161         size_t len = strlen(string);
162
163         if (len > SM_MAXSTRLEN)
164                 len = SM_MAXSTRLEN;
165         return xdr_encode_opaque(p, string, len);
166 }
167
168 /*
169  * "mon_name" specifies the host to be monitored.
170  *
171  * Linux uses a text version of the IP address of the remote
172  * host as the host identifier (the "mon_name" argument).
173  *
174  * Linux statd always looks up the canonical hostname first for
175  * whatever remote hostname it receives, so this works alright.
176  */
177 static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp)
178 {
179         char    buffer[XDR_ADDRBUF_LEN + 1];
180         char    *name = argp->mon_name;
181
182         if (!nsm_use_hostnames) {
183                 snprintf(buffer, XDR_ADDRBUF_LEN,
184                          "%pI4", &argp->addr);
185                 name = buffer;
186         }
187
188         return xdr_encode_nsm_string(p, name);
189 }
190
191 /*
192  * The "my_id" argument specifies the hostname and RPC procedure
193  * to be called when the status manager receives notification
194  * (via the SM_NOTIFY call) that the state of host "mon_name"
195  * has changed.
196  */
197 static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp)
198 {
199         p = xdr_encode_nsm_string(p, utsname()->nodename);
200         if (!p)
201                 return ERR_PTR(-EIO);
202
203         *p++ = htonl(argp->prog);
204         *p++ = htonl(argp->vers);
205         *p++ = htonl(argp->proc);
206
207         return p;
208 }
209
210 /*
211  * The "mon_id" argument specifies the non-private arguments
212  * of an SM_MON or SM_UNMON call.
213  */
214 static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp)
215 {
216         p = xdr_encode_mon_name(p, argp);
217         if (!p)
218                 return ERR_PTR(-EIO);
219
220         return xdr_encode_my_id(p, argp);
221 }
222
223 /*
224  * The "priv" argument may contain private information required
225  * by the SM_MON call. This information will be supplied in the
226  * SM_NOTIFY call.
227  *
228  * Linux provides the raw IP address of the monitored host,
229  * left in network byte order.
230  */
231 static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp)
232 {
233         *p++ = argp->addr;
234         *p++ = 0;
235         *p++ = 0;
236         *p++ = 0;
237
238         return p;
239 }
240
241 static int
242 xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
243 {
244         p = xdr_encode_mon_id(p, argp);
245         if (IS_ERR(p))
246                 return PTR_ERR(p);
247
248         p = xdr_encode_priv(p, argp);
249         if (IS_ERR(p))
250                 return PTR_ERR(p);
251
252         rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
253         return 0;
254 }
255
256 static int
257 xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
258 {
259         p = xdr_encode_mon_id(p, argp);
260         if (IS_ERR(p))
261                 return PTR_ERR(p);
262         rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
263         return 0;
264 }
265
266 static int
267 xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
268 {
269         resp->status = ntohl(*p++);
270         resp->state = ntohl(*p++);
271         dprintk("nsm: xdr_decode_stat_res status %d state %d\n",
272                         resp->status, resp->state);
273         return 0;
274 }
275
276 static int
277 xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
278 {
279         resp->state = ntohl(*p++);
280         return 0;
281 }
282
283 #define SM_my_name_sz   (1+XDR_QUADLEN(SM_MAXSTRLEN))
284 #define SM_my_id_sz     (SM_my_name_sz+3)
285 #define SM_mon_name_sz  (1+XDR_QUADLEN(SM_MAXSTRLEN))
286 #define SM_mon_id_sz    (SM_mon_name_sz+SM_my_id_sz)
287 #define SM_priv_sz      (XDR_QUADLEN(SM_PRIV_SIZE))
288 #define SM_mon_sz       (SM_mon_id_sz+SM_priv_sz)
289 #define SM_monres_sz    2
290 #define SM_unmonres_sz  1
291
292 static struct rpc_procinfo      nsm_procedures[] = {
293 [SM_MON] = {
294                 .p_proc         = SM_MON,
295                 .p_encode       = (kxdrproc_t) xdr_encode_mon,
296                 .p_decode       = (kxdrproc_t) xdr_decode_stat_res,
297                 .p_arglen       = SM_mon_sz,
298                 .p_replen       = SM_monres_sz,
299                 .p_statidx      = SM_MON,
300                 .p_name         = "MONITOR",
301         },
302 [SM_UNMON] = {
303                 .p_proc         = SM_UNMON,
304                 .p_encode       = (kxdrproc_t) xdr_encode_unmon,
305                 .p_decode       = (kxdrproc_t) xdr_decode_stat,
306                 .p_arglen       = SM_mon_id_sz,
307                 .p_replen       = SM_unmonres_sz,
308                 .p_statidx      = SM_UNMON,
309                 .p_name         = "UNMONITOR",
310         },
311 };
312
313 static struct rpc_version       nsm_version1 = {
314                 .number         = 1,
315                 .nrprocs        = ARRAY_SIZE(nsm_procedures),
316                 .procs          = nsm_procedures
317 };
318
319 static struct rpc_version *     nsm_version[] = {
320         [1] = &nsm_version1,
321 };
322
323 static struct rpc_stat          nsm_stats;
324
325 static struct rpc_program       nsm_program = {
326                 .name           = "statd",
327                 .number         = SM_PROGRAM,
328                 .nrvers         = ARRAY_SIZE(nsm_version),
329                 .version        = nsm_version,
330                 .stats          = &nsm_stats
331 };