1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/fs/lockd/svc4proc.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Lockd server procedures. We don't implement the NLM_*_RES
6*4882a593Smuzhiyun * procedures because we don't use the async procedures.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/types.h>
12*4882a593Smuzhiyun #include <linux/time.h>
13*4882a593Smuzhiyun #include <linux/lockd/lockd.h>
14*4882a593Smuzhiyun #include <linux/lockd/share.h>
15*4882a593Smuzhiyun #include <linux/sunrpc/svc_xprt.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define NLMDBG_FACILITY NLMDBG_CLIENT
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun * Obtain client and file from arguments
21*4882a593Smuzhiyun */
22*4882a593Smuzhiyun static __be32
nlm4svc_retrieve_args(struct svc_rqst * rqstp,struct nlm_args * argp,struct nlm_host ** hostp,struct nlm_file ** filp)23*4882a593Smuzhiyun nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
24*4882a593Smuzhiyun struct nlm_host **hostp, struct nlm_file **filp)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun struct nlm_host *host = NULL;
27*4882a593Smuzhiyun struct nlm_file *file = NULL;
28*4882a593Smuzhiyun struct nlm_lock *lock = &argp->lock;
29*4882a593Smuzhiyun __be32 error = 0;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* nfsd callbacks must have been installed for this procedure */
32*4882a593Smuzhiyun if (!nlmsvc_ops)
33*4882a593Smuzhiyun return nlm_lck_denied_nolocks;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* Obtain host handle */
36*4882a593Smuzhiyun if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
37*4882a593Smuzhiyun || (argp->monitor && nsm_monitor(host) < 0))
38*4882a593Smuzhiyun goto no_locks;
39*4882a593Smuzhiyun *hostp = host;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /* Obtain file pointer. Not used by FREE_ALL call. */
42*4882a593Smuzhiyun if (filp != NULL) {
43*4882a593Smuzhiyun if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
44*4882a593Smuzhiyun goto no_locks;
45*4882a593Smuzhiyun *filp = file;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* Set up the missing parts of the file_lock structure */
48*4882a593Smuzhiyun lock->fl.fl_file = file->f_file;
49*4882a593Smuzhiyun lock->fl.fl_pid = current->tgid;
50*4882a593Smuzhiyun lock->fl.fl_lmops = &nlmsvc_lock_operations;
51*4882a593Smuzhiyun nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid);
52*4882a593Smuzhiyun if (!lock->fl.fl_owner) {
53*4882a593Smuzhiyun /* lockowner allocation has failed */
54*4882a593Smuzhiyun nlmsvc_release_host(host);
55*4882a593Smuzhiyun return nlm_lck_denied_nolocks;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun return 0;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun no_locks:
62*4882a593Smuzhiyun nlmsvc_release_host(host);
63*4882a593Smuzhiyun if (error)
64*4882a593Smuzhiyun return error;
65*4882a593Smuzhiyun return nlm_lck_denied_nolocks;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /*
69*4882a593Smuzhiyun * NULL: Test for presence of service
70*4882a593Smuzhiyun */
71*4882a593Smuzhiyun static __be32
nlm4svc_proc_null(struct svc_rqst * rqstp)72*4882a593Smuzhiyun nlm4svc_proc_null(struct svc_rqst *rqstp)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun dprintk("lockd: NULL called\n");
75*4882a593Smuzhiyun return rpc_success;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun * TEST: Check for conflicting lock
80*4882a593Smuzhiyun */
81*4882a593Smuzhiyun static __be32
__nlm4svc_proc_test(struct svc_rqst * rqstp,struct nlm_res * resp)82*4882a593Smuzhiyun __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
85*4882a593Smuzhiyun struct nlm_host *host;
86*4882a593Smuzhiyun struct nlm_file *file;
87*4882a593Smuzhiyun __be32 rc = rpc_success;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun dprintk("lockd: TEST4 called\n");
90*4882a593Smuzhiyun resp->cookie = argp->cookie;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* Obtain client and file */
93*4882a593Smuzhiyun if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
94*4882a593Smuzhiyun return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /* Now check for conflicting locks */
97*4882a593Smuzhiyun resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
98*4882a593Smuzhiyun if (resp->status == nlm_drop_reply)
99*4882a593Smuzhiyun rc = rpc_drop_reply;
100*4882a593Smuzhiyun else
101*4882a593Smuzhiyun dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun nlmsvc_release_lockowner(&argp->lock);
104*4882a593Smuzhiyun nlmsvc_release_host(host);
105*4882a593Smuzhiyun nlm_release_file(file);
106*4882a593Smuzhiyun return rc;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun static __be32
nlm4svc_proc_test(struct svc_rqst * rqstp)110*4882a593Smuzhiyun nlm4svc_proc_test(struct svc_rqst *rqstp)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun return __nlm4svc_proc_test(rqstp, rqstp->rq_resp);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static __be32
__nlm4svc_proc_lock(struct svc_rqst * rqstp,struct nlm_res * resp)116*4882a593Smuzhiyun __nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
119*4882a593Smuzhiyun struct nlm_host *host;
120*4882a593Smuzhiyun struct nlm_file *file;
121*4882a593Smuzhiyun __be32 rc = rpc_success;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun dprintk("lockd: LOCK called\n");
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun resp->cookie = argp->cookie;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* Obtain client and file */
128*4882a593Smuzhiyun if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
129*4882a593Smuzhiyun return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun #if 0
132*4882a593Smuzhiyun /* If supplied state doesn't match current state, we assume it's
133*4882a593Smuzhiyun * an old request that time-warped somehow. Any error return would
134*4882a593Smuzhiyun * do in this case because it's irrelevant anyway.
135*4882a593Smuzhiyun *
136*4882a593Smuzhiyun * NB: We don't retrieve the remote host's state yet.
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun if (host->h_nsmstate && host->h_nsmstate != argp->state) {
139*4882a593Smuzhiyun resp->status = nlm_lck_denied_nolocks;
140*4882a593Smuzhiyun } else
141*4882a593Smuzhiyun #endif
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* Now try to lock the file */
144*4882a593Smuzhiyun resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
145*4882a593Smuzhiyun argp->block, &argp->cookie,
146*4882a593Smuzhiyun argp->reclaim);
147*4882a593Smuzhiyun if (resp->status == nlm_drop_reply)
148*4882a593Smuzhiyun rc = rpc_drop_reply;
149*4882a593Smuzhiyun else
150*4882a593Smuzhiyun dprintk("lockd: LOCK status %d\n", ntohl(resp->status));
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun nlmsvc_release_lockowner(&argp->lock);
153*4882a593Smuzhiyun nlmsvc_release_host(host);
154*4882a593Smuzhiyun nlm_release_file(file);
155*4882a593Smuzhiyun return rc;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun static __be32
nlm4svc_proc_lock(struct svc_rqst * rqstp)159*4882a593Smuzhiyun nlm4svc_proc_lock(struct svc_rqst *rqstp)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun return __nlm4svc_proc_lock(rqstp, rqstp->rq_resp);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun static __be32
__nlm4svc_proc_cancel(struct svc_rqst * rqstp,struct nlm_res * resp)165*4882a593Smuzhiyun __nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
168*4882a593Smuzhiyun struct nlm_host *host;
169*4882a593Smuzhiyun struct nlm_file *file;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun dprintk("lockd: CANCEL called\n");
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun resp->cookie = argp->cookie;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* Don't accept requests during grace period */
176*4882a593Smuzhiyun if (locks_in_grace(SVC_NET(rqstp))) {
177*4882a593Smuzhiyun resp->status = nlm_lck_denied_grace_period;
178*4882a593Smuzhiyun return rpc_success;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Obtain client and file */
182*4882a593Smuzhiyun if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
183*4882a593Smuzhiyun return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* Try to cancel request. */
186*4882a593Smuzhiyun resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
189*4882a593Smuzhiyun nlmsvc_release_lockowner(&argp->lock);
190*4882a593Smuzhiyun nlmsvc_release_host(host);
191*4882a593Smuzhiyun nlm_release_file(file);
192*4882a593Smuzhiyun return rpc_success;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun static __be32
nlm4svc_proc_cancel(struct svc_rqst * rqstp)196*4882a593Smuzhiyun nlm4svc_proc_cancel(struct svc_rqst *rqstp)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun return __nlm4svc_proc_cancel(rqstp, rqstp->rq_resp);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /*
202*4882a593Smuzhiyun * UNLOCK: release a lock
203*4882a593Smuzhiyun */
204*4882a593Smuzhiyun static __be32
__nlm4svc_proc_unlock(struct svc_rqst * rqstp,struct nlm_res * resp)205*4882a593Smuzhiyun __nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
208*4882a593Smuzhiyun struct nlm_host *host;
209*4882a593Smuzhiyun struct nlm_file *file;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun dprintk("lockd: UNLOCK called\n");
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun resp->cookie = argp->cookie;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* Don't accept new lock requests during grace period */
216*4882a593Smuzhiyun if (locks_in_grace(SVC_NET(rqstp))) {
217*4882a593Smuzhiyun resp->status = nlm_lck_denied_grace_period;
218*4882a593Smuzhiyun return rpc_success;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* Obtain client and file */
222*4882a593Smuzhiyun if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
223*4882a593Smuzhiyun return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* Now try to remove the lock */
226*4882a593Smuzhiyun resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
229*4882a593Smuzhiyun nlmsvc_release_lockowner(&argp->lock);
230*4882a593Smuzhiyun nlmsvc_release_host(host);
231*4882a593Smuzhiyun nlm_release_file(file);
232*4882a593Smuzhiyun return rpc_success;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun static __be32
nlm4svc_proc_unlock(struct svc_rqst * rqstp)236*4882a593Smuzhiyun nlm4svc_proc_unlock(struct svc_rqst *rqstp)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun return __nlm4svc_proc_unlock(rqstp, rqstp->rq_resp);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun /*
242*4882a593Smuzhiyun * GRANTED: A server calls us to tell that a process' lock request
243*4882a593Smuzhiyun * was granted
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun static __be32
__nlm4svc_proc_granted(struct svc_rqst * rqstp,struct nlm_res * resp)246*4882a593Smuzhiyun __nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun resp->cookie = argp->cookie;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun dprintk("lockd: GRANTED called\n");
253*4882a593Smuzhiyun resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
254*4882a593Smuzhiyun dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
255*4882a593Smuzhiyun return rpc_success;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun static __be32
nlm4svc_proc_granted(struct svc_rqst * rqstp)259*4882a593Smuzhiyun nlm4svc_proc_granted(struct svc_rqst *rqstp)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun return __nlm4svc_proc_granted(rqstp, rqstp->rq_resp);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /*
265*4882a593Smuzhiyun * This is the generic lockd callback for async RPC calls
266*4882a593Smuzhiyun */
nlm4svc_callback_exit(struct rpc_task * task,void * data)267*4882a593Smuzhiyun static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
270*4882a593Smuzhiyun -task->tk_status);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
nlm4svc_callback_release(void * data)273*4882a593Smuzhiyun static void nlm4svc_callback_release(void *data)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun nlmsvc_release_call(data);
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun static const struct rpc_call_ops nlm4svc_callback_ops = {
279*4882a593Smuzhiyun .rpc_call_done = nlm4svc_callback_exit,
280*4882a593Smuzhiyun .rpc_release = nlm4svc_callback_release,
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun * `Async' versions of the above service routines. They aren't really,
285*4882a593Smuzhiyun * because we send the callback before the reply proper. I hope this
286*4882a593Smuzhiyun * doesn't break any clients.
287*4882a593Smuzhiyun */
nlm4svc_callback(struct svc_rqst * rqstp,u32 proc,__be32 (* func)(struct svc_rqst *,struct nlm_res *))288*4882a593Smuzhiyun static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc,
289*4882a593Smuzhiyun __be32 (*func)(struct svc_rqst *, struct nlm_res *))
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
292*4882a593Smuzhiyun struct nlm_host *host;
293*4882a593Smuzhiyun struct nlm_rqst *call;
294*4882a593Smuzhiyun __be32 stat;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun host = nlmsvc_lookup_host(rqstp,
297*4882a593Smuzhiyun argp->lock.caller,
298*4882a593Smuzhiyun argp->lock.len);
299*4882a593Smuzhiyun if (host == NULL)
300*4882a593Smuzhiyun return rpc_system_err;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun call = nlm_alloc_call(host);
303*4882a593Smuzhiyun nlmsvc_release_host(host);
304*4882a593Smuzhiyun if (call == NULL)
305*4882a593Smuzhiyun return rpc_system_err;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun stat = func(rqstp, &call->a_res);
308*4882a593Smuzhiyun if (stat != 0) {
309*4882a593Smuzhiyun nlmsvc_release_call(call);
310*4882a593Smuzhiyun return stat;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun call->a_flags = RPC_TASK_ASYNC;
314*4882a593Smuzhiyun if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0)
315*4882a593Smuzhiyun return rpc_system_err;
316*4882a593Smuzhiyun return rpc_success;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
nlm4svc_proc_test_msg(struct svc_rqst * rqstp)319*4882a593Smuzhiyun static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun dprintk("lockd: TEST_MSG called\n");
322*4882a593Smuzhiyun return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, __nlm4svc_proc_test);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
nlm4svc_proc_lock_msg(struct svc_rqst * rqstp)325*4882a593Smuzhiyun static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun dprintk("lockd: LOCK_MSG called\n");
328*4882a593Smuzhiyun return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, __nlm4svc_proc_lock);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
nlm4svc_proc_cancel_msg(struct svc_rqst * rqstp)331*4882a593Smuzhiyun static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun dprintk("lockd: CANCEL_MSG called\n");
334*4882a593Smuzhiyun return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, __nlm4svc_proc_cancel);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
nlm4svc_proc_unlock_msg(struct svc_rqst * rqstp)337*4882a593Smuzhiyun static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun dprintk("lockd: UNLOCK_MSG called\n");
340*4882a593Smuzhiyun return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlm4svc_proc_unlock);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
nlm4svc_proc_granted_msg(struct svc_rqst * rqstp)343*4882a593Smuzhiyun static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun dprintk("lockd: GRANTED_MSG called\n");
346*4882a593Smuzhiyun return nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, __nlm4svc_proc_granted);
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /*
350*4882a593Smuzhiyun * SHARE: create a DOS share or alter existing share.
351*4882a593Smuzhiyun */
352*4882a593Smuzhiyun static __be32
nlm4svc_proc_share(struct svc_rqst * rqstp)353*4882a593Smuzhiyun nlm4svc_proc_share(struct svc_rqst *rqstp)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
356*4882a593Smuzhiyun struct nlm_res *resp = rqstp->rq_resp;
357*4882a593Smuzhiyun struct nlm_host *host;
358*4882a593Smuzhiyun struct nlm_file *file;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun dprintk("lockd: SHARE called\n");
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun resp->cookie = argp->cookie;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Don't accept new lock requests during grace period */
365*4882a593Smuzhiyun if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
366*4882a593Smuzhiyun resp->status = nlm_lck_denied_grace_period;
367*4882a593Smuzhiyun return rpc_success;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun /* Obtain client and file */
371*4882a593Smuzhiyun if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
372*4882a593Smuzhiyun return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun /* Now try to create the share */
375*4882a593Smuzhiyun resp->status = nlmsvc_share_file(host, file, argp);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun dprintk("lockd: SHARE status %d\n", ntohl(resp->status));
378*4882a593Smuzhiyun nlmsvc_release_lockowner(&argp->lock);
379*4882a593Smuzhiyun nlmsvc_release_host(host);
380*4882a593Smuzhiyun nlm_release_file(file);
381*4882a593Smuzhiyun return rpc_success;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /*
385*4882a593Smuzhiyun * UNSHARE: Release a DOS share.
386*4882a593Smuzhiyun */
387*4882a593Smuzhiyun static __be32
nlm4svc_proc_unshare(struct svc_rqst * rqstp)388*4882a593Smuzhiyun nlm4svc_proc_unshare(struct svc_rqst *rqstp)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
391*4882a593Smuzhiyun struct nlm_res *resp = rqstp->rq_resp;
392*4882a593Smuzhiyun struct nlm_host *host;
393*4882a593Smuzhiyun struct nlm_file *file;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun dprintk("lockd: UNSHARE called\n");
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun resp->cookie = argp->cookie;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* Don't accept requests during grace period */
400*4882a593Smuzhiyun if (locks_in_grace(SVC_NET(rqstp))) {
401*4882a593Smuzhiyun resp->status = nlm_lck_denied_grace_period;
402*4882a593Smuzhiyun return rpc_success;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun /* Obtain client and file */
406*4882a593Smuzhiyun if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
407*4882a593Smuzhiyun return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun /* Now try to lock the file */
410*4882a593Smuzhiyun resp->status = nlmsvc_unshare_file(host, file, argp);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status));
413*4882a593Smuzhiyun nlmsvc_release_lockowner(&argp->lock);
414*4882a593Smuzhiyun nlmsvc_release_host(host);
415*4882a593Smuzhiyun nlm_release_file(file);
416*4882a593Smuzhiyun return rpc_success;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /*
420*4882a593Smuzhiyun * NM_LOCK: Create an unmonitored lock
421*4882a593Smuzhiyun */
422*4882a593Smuzhiyun static __be32
nlm4svc_proc_nm_lock(struct svc_rqst * rqstp)423*4882a593Smuzhiyun nlm4svc_proc_nm_lock(struct svc_rqst *rqstp)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun dprintk("lockd: NM_LOCK called\n");
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun argp->monitor = 0; /* just clean the monitor flag */
430*4882a593Smuzhiyun return nlm4svc_proc_lock(rqstp);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun /*
434*4882a593Smuzhiyun * FREE_ALL: Release all locks and shares held by client
435*4882a593Smuzhiyun */
436*4882a593Smuzhiyun static __be32
nlm4svc_proc_free_all(struct svc_rqst * rqstp)437*4882a593Smuzhiyun nlm4svc_proc_free_all(struct svc_rqst *rqstp)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct nlm_args *argp = rqstp->rq_argp;
440*4882a593Smuzhiyun struct nlm_host *host;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun /* Obtain client */
443*4882a593Smuzhiyun if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL))
444*4882a593Smuzhiyun return rpc_success;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun nlmsvc_free_host_resources(host);
447*4882a593Smuzhiyun nlmsvc_release_host(host);
448*4882a593Smuzhiyun return rpc_success;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /*
452*4882a593Smuzhiyun * SM_NOTIFY: private callback from statd (not part of official NLM proto)
453*4882a593Smuzhiyun */
454*4882a593Smuzhiyun static __be32
nlm4svc_proc_sm_notify(struct svc_rqst * rqstp)455*4882a593Smuzhiyun nlm4svc_proc_sm_notify(struct svc_rqst *rqstp)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun struct nlm_reboot *argp = rqstp->rq_argp;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun dprintk("lockd: SM_NOTIFY called\n");
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun if (!nlm_privileged_requester(rqstp)) {
462*4882a593Smuzhiyun char buf[RPC_MAX_ADDRBUFLEN];
463*4882a593Smuzhiyun printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
464*4882a593Smuzhiyun svc_print_addr(rqstp, buf, sizeof(buf)));
465*4882a593Smuzhiyun return rpc_system_err;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun nlm_host_rebooted(SVC_NET(rqstp), argp);
469*4882a593Smuzhiyun return rpc_success;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun /*
473*4882a593Smuzhiyun * client sent a GRANTED_RES, let's remove the associated block
474*4882a593Smuzhiyun */
475*4882a593Smuzhiyun static __be32
nlm4svc_proc_granted_res(struct svc_rqst * rqstp)476*4882a593Smuzhiyun nlm4svc_proc_granted_res(struct svc_rqst *rqstp)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun struct nlm_res *argp = rqstp->rq_argp;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun if (!nlmsvc_ops)
481*4882a593Smuzhiyun return rpc_success;
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun dprintk("lockd: GRANTED_RES called\n");
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun nlmsvc_grant_reply(&argp->cookie, argp->status);
486*4882a593Smuzhiyun return rpc_success;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun static __be32
nlm4svc_proc_unused(struct svc_rqst * rqstp)490*4882a593Smuzhiyun nlm4svc_proc_unused(struct svc_rqst *rqstp)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun return rpc_proc_unavail;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun /*
497*4882a593Smuzhiyun * NLM Server procedures.
498*4882a593Smuzhiyun */
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun struct nlm_void { int dummy; };
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */
503*4882a593Smuzhiyun #define No (1+1024/4) /* netobj */
504*4882a593Smuzhiyun #define St 1 /* status */
505*4882a593Smuzhiyun #define Rg 4 /* range (offset + length) */
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun const struct svc_procedure nlmsvc_procedures4[24] = {
508*4882a593Smuzhiyun [NLMPROC_NULL] = {
509*4882a593Smuzhiyun .pc_func = nlm4svc_proc_null,
510*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
511*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
512*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_void),
513*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
514*4882a593Smuzhiyun .pc_xdrressize = St,
515*4882a593Smuzhiyun },
516*4882a593Smuzhiyun [NLMPROC_TEST] = {
517*4882a593Smuzhiyun .pc_func = nlm4svc_proc_test,
518*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_testargs,
519*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_testres,
520*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
521*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
522*4882a593Smuzhiyun .pc_xdrressize = Ck+St+2+No+Rg,
523*4882a593Smuzhiyun },
524*4882a593Smuzhiyun [NLMPROC_LOCK] = {
525*4882a593Smuzhiyun .pc_func = nlm4svc_proc_lock,
526*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_lockargs,
527*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_res,
528*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
529*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
530*4882a593Smuzhiyun .pc_xdrressize = Ck+St,
531*4882a593Smuzhiyun },
532*4882a593Smuzhiyun [NLMPROC_CANCEL] = {
533*4882a593Smuzhiyun .pc_func = nlm4svc_proc_cancel,
534*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_cancargs,
535*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_res,
536*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
537*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
538*4882a593Smuzhiyun .pc_xdrressize = Ck+St,
539*4882a593Smuzhiyun },
540*4882a593Smuzhiyun [NLMPROC_UNLOCK] = {
541*4882a593Smuzhiyun .pc_func = nlm4svc_proc_unlock,
542*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_unlockargs,
543*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_res,
544*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
545*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
546*4882a593Smuzhiyun .pc_xdrressize = Ck+St,
547*4882a593Smuzhiyun },
548*4882a593Smuzhiyun [NLMPROC_GRANTED] = {
549*4882a593Smuzhiyun .pc_func = nlm4svc_proc_granted,
550*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_testargs,
551*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_res,
552*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
553*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
554*4882a593Smuzhiyun .pc_xdrressize = Ck+St,
555*4882a593Smuzhiyun },
556*4882a593Smuzhiyun [NLMPROC_TEST_MSG] = {
557*4882a593Smuzhiyun .pc_func = nlm4svc_proc_test_msg,
558*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_testargs,
559*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
560*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
561*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
562*4882a593Smuzhiyun .pc_xdrressize = St,
563*4882a593Smuzhiyun },
564*4882a593Smuzhiyun [NLMPROC_LOCK_MSG] = {
565*4882a593Smuzhiyun .pc_func = nlm4svc_proc_lock_msg,
566*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_lockargs,
567*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
568*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
569*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
570*4882a593Smuzhiyun .pc_xdrressize = St,
571*4882a593Smuzhiyun },
572*4882a593Smuzhiyun [NLMPROC_CANCEL_MSG] = {
573*4882a593Smuzhiyun .pc_func = nlm4svc_proc_cancel_msg,
574*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_cancargs,
575*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
576*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
577*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
578*4882a593Smuzhiyun .pc_xdrressize = St,
579*4882a593Smuzhiyun },
580*4882a593Smuzhiyun [NLMPROC_UNLOCK_MSG] = {
581*4882a593Smuzhiyun .pc_func = nlm4svc_proc_unlock_msg,
582*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_unlockargs,
583*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
584*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
585*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
586*4882a593Smuzhiyun .pc_xdrressize = St,
587*4882a593Smuzhiyun },
588*4882a593Smuzhiyun [NLMPROC_GRANTED_MSG] = {
589*4882a593Smuzhiyun .pc_func = nlm4svc_proc_granted_msg,
590*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_testargs,
591*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
592*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
593*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
594*4882a593Smuzhiyun .pc_xdrressize = St,
595*4882a593Smuzhiyun },
596*4882a593Smuzhiyun [NLMPROC_TEST_RES] = {
597*4882a593Smuzhiyun .pc_func = nlm4svc_proc_null,
598*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
599*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
600*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_res),
601*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
602*4882a593Smuzhiyun .pc_xdrressize = St,
603*4882a593Smuzhiyun },
604*4882a593Smuzhiyun [NLMPROC_LOCK_RES] = {
605*4882a593Smuzhiyun .pc_func = nlm4svc_proc_null,
606*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
607*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
608*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_res),
609*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
610*4882a593Smuzhiyun .pc_xdrressize = St,
611*4882a593Smuzhiyun },
612*4882a593Smuzhiyun [NLMPROC_CANCEL_RES] = {
613*4882a593Smuzhiyun .pc_func = nlm4svc_proc_null,
614*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
615*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
616*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_res),
617*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
618*4882a593Smuzhiyun .pc_xdrressize = St,
619*4882a593Smuzhiyun },
620*4882a593Smuzhiyun [NLMPROC_UNLOCK_RES] = {
621*4882a593Smuzhiyun .pc_func = nlm4svc_proc_null,
622*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
623*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
624*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_res),
625*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
626*4882a593Smuzhiyun .pc_xdrressize = St,
627*4882a593Smuzhiyun },
628*4882a593Smuzhiyun [NLMPROC_GRANTED_RES] = {
629*4882a593Smuzhiyun .pc_func = nlm4svc_proc_granted_res,
630*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_res,
631*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
632*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_res),
633*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
634*4882a593Smuzhiyun .pc_xdrressize = St,
635*4882a593Smuzhiyun },
636*4882a593Smuzhiyun [NLMPROC_NSM_NOTIFY] = {
637*4882a593Smuzhiyun .pc_func = nlm4svc_proc_sm_notify,
638*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_reboot,
639*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
640*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_reboot),
641*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
642*4882a593Smuzhiyun .pc_xdrressize = St,
643*4882a593Smuzhiyun },
644*4882a593Smuzhiyun [17] = {
645*4882a593Smuzhiyun .pc_func = nlm4svc_proc_unused,
646*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
647*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
648*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_void),
649*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
650*4882a593Smuzhiyun .pc_xdrressize = 0,
651*4882a593Smuzhiyun },
652*4882a593Smuzhiyun [18] = {
653*4882a593Smuzhiyun .pc_func = nlm4svc_proc_unused,
654*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
655*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
656*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_void),
657*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
658*4882a593Smuzhiyun .pc_xdrressize = 0,
659*4882a593Smuzhiyun },
660*4882a593Smuzhiyun [19] = {
661*4882a593Smuzhiyun .pc_func = nlm4svc_proc_unused,
662*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_void,
663*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
664*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_void),
665*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
666*4882a593Smuzhiyun .pc_xdrressize = 0,
667*4882a593Smuzhiyun },
668*4882a593Smuzhiyun [NLMPROC_SHARE] = {
669*4882a593Smuzhiyun .pc_func = nlm4svc_proc_share,
670*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_shareargs,
671*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_shareres,
672*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
673*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
674*4882a593Smuzhiyun .pc_xdrressize = Ck+St+1,
675*4882a593Smuzhiyun },
676*4882a593Smuzhiyun [NLMPROC_UNSHARE] = {
677*4882a593Smuzhiyun .pc_func = nlm4svc_proc_unshare,
678*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_shareargs,
679*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_shareres,
680*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
681*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
682*4882a593Smuzhiyun .pc_xdrressize = Ck+St+1,
683*4882a593Smuzhiyun },
684*4882a593Smuzhiyun [NLMPROC_NM_LOCK] = {
685*4882a593Smuzhiyun .pc_func = nlm4svc_proc_nm_lock,
686*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_lockargs,
687*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_res,
688*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
689*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_res),
690*4882a593Smuzhiyun .pc_xdrressize = Ck+St,
691*4882a593Smuzhiyun },
692*4882a593Smuzhiyun [NLMPROC_FREE_ALL] = {
693*4882a593Smuzhiyun .pc_func = nlm4svc_proc_free_all,
694*4882a593Smuzhiyun .pc_decode = nlm4svc_decode_notify,
695*4882a593Smuzhiyun .pc_encode = nlm4svc_encode_void,
696*4882a593Smuzhiyun .pc_argsize = sizeof(struct nlm_args),
697*4882a593Smuzhiyun .pc_ressize = sizeof(struct nlm_void),
698*4882a593Smuzhiyun .pc_xdrressize = St,
699*4882a593Smuzhiyun },
700*4882a593Smuzhiyun };
701