1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/fs/lockd/svc4proc.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Lockd server procedures. We don't implement the NLM_*_RES 5*1da177e4SLinus Torvalds * procedures because we don't use the async procedures. 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 8*1da177e4SLinus Torvalds */ 9*1da177e4SLinus Torvalds 10*1da177e4SLinus Torvalds #include <linux/types.h> 11*1da177e4SLinus Torvalds #include <linux/time.h> 12*1da177e4SLinus Torvalds #include <linux/slab.h> 13*1da177e4SLinus Torvalds #include <linux/in.h> 14*1da177e4SLinus Torvalds #include <linux/sunrpc/svc.h> 15*1da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h> 16*1da177e4SLinus Torvalds #include <linux/nfsd/nfsd.h> 17*1da177e4SLinus Torvalds #include <linux/lockd/lockd.h> 18*1da177e4SLinus Torvalds #include <linux/lockd/share.h> 19*1da177e4SLinus Torvalds #include <linux/lockd/sm_inter.h> 20*1da177e4SLinus Torvalds 21*1da177e4SLinus Torvalds 22*1da177e4SLinus Torvalds #define NLMDBG_FACILITY NLMDBG_CLIENT 23*1da177e4SLinus Torvalds 24*1da177e4SLinus Torvalds static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *); 25*1da177e4SLinus Torvalds static void nlm4svc_callback_exit(struct rpc_task *); 26*1da177e4SLinus Torvalds 27*1da177e4SLinus Torvalds /* 28*1da177e4SLinus Torvalds * Obtain client and file from arguments 29*1da177e4SLinus Torvalds */ 30*1da177e4SLinus Torvalds static u32 31*1da177e4SLinus Torvalds nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, 32*1da177e4SLinus Torvalds struct nlm_host **hostp, struct nlm_file **filp) 33*1da177e4SLinus Torvalds { 34*1da177e4SLinus Torvalds struct nlm_host *host = NULL; 35*1da177e4SLinus Torvalds struct nlm_file *file = NULL; 36*1da177e4SLinus Torvalds struct nlm_lock *lock = &argp->lock; 37*1da177e4SLinus Torvalds u32 error = 0; 38*1da177e4SLinus Torvalds 39*1da177e4SLinus Torvalds /* nfsd callbacks must have been installed for this procedure */ 40*1da177e4SLinus Torvalds if (!nlmsvc_ops) 41*1da177e4SLinus Torvalds return nlm_lck_denied_nolocks; 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds /* Obtain host handle */ 44*1da177e4SLinus Torvalds if (!(host = nlmsvc_lookup_host(rqstp)) 45*1da177e4SLinus Torvalds || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0)) 46*1da177e4SLinus Torvalds goto no_locks; 47*1da177e4SLinus Torvalds *hostp = host; 48*1da177e4SLinus Torvalds 49*1da177e4SLinus Torvalds /* Obtain file pointer. Not used by FREE_ALL call. */ 50*1da177e4SLinus Torvalds if (filp != NULL) { 51*1da177e4SLinus Torvalds if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) 52*1da177e4SLinus Torvalds goto no_locks; 53*1da177e4SLinus Torvalds *filp = file; 54*1da177e4SLinus Torvalds 55*1da177e4SLinus Torvalds /* Set up the missing parts of the file_lock structure */ 56*1da177e4SLinus Torvalds lock->fl.fl_file = file->f_file; 57*1da177e4SLinus Torvalds lock->fl.fl_owner = (fl_owner_t) host; 58*1da177e4SLinus Torvalds lock->fl.fl_lmops = &nlmsvc_lock_operations; 59*1da177e4SLinus Torvalds } 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds return 0; 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds no_locks: 64*1da177e4SLinus Torvalds if (host) 65*1da177e4SLinus Torvalds nlm_release_host(host); 66*1da177e4SLinus Torvalds if (error) 67*1da177e4SLinus Torvalds return error; 68*1da177e4SLinus Torvalds return nlm_lck_denied_nolocks; 69*1da177e4SLinus Torvalds } 70*1da177e4SLinus Torvalds 71*1da177e4SLinus Torvalds /* 72*1da177e4SLinus Torvalds * NULL: Test for presence of service 73*1da177e4SLinus Torvalds */ 74*1da177e4SLinus Torvalds static int 75*1da177e4SLinus Torvalds nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) 76*1da177e4SLinus Torvalds { 77*1da177e4SLinus Torvalds dprintk("lockd: NULL called\n"); 78*1da177e4SLinus Torvalds return rpc_success; 79*1da177e4SLinus Torvalds } 80*1da177e4SLinus Torvalds 81*1da177e4SLinus Torvalds /* 82*1da177e4SLinus Torvalds * TEST: Check for conflicting lock 83*1da177e4SLinus Torvalds */ 84*1da177e4SLinus Torvalds static int 85*1da177e4SLinus Torvalds nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, 86*1da177e4SLinus Torvalds struct nlm_res *resp) 87*1da177e4SLinus Torvalds { 88*1da177e4SLinus Torvalds struct nlm_host *host; 89*1da177e4SLinus Torvalds struct nlm_file *file; 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds dprintk("lockd: TEST4 called\n"); 92*1da177e4SLinus Torvalds resp->cookie = argp->cookie; 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds /* Don't accept test requests during grace period */ 95*1da177e4SLinus Torvalds if (nlmsvc_grace_period) { 96*1da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 97*1da177e4SLinus Torvalds return rpc_success; 98*1da177e4SLinus Torvalds } 99*1da177e4SLinus Torvalds 100*1da177e4SLinus Torvalds /* Obtain client and file */ 101*1da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 102*1da177e4SLinus Torvalds return rpc_success; 103*1da177e4SLinus Torvalds 104*1da177e4SLinus Torvalds /* Now check for conflicting locks */ 105*1da177e4SLinus Torvalds resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); 106*1da177e4SLinus Torvalds 107*1da177e4SLinus Torvalds dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); 108*1da177e4SLinus Torvalds nlm_release_host(host); 109*1da177e4SLinus Torvalds nlm_release_file(file); 110*1da177e4SLinus Torvalds return rpc_success; 111*1da177e4SLinus Torvalds } 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds static int 114*1da177e4SLinus Torvalds nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, 115*1da177e4SLinus Torvalds struct nlm_res *resp) 116*1da177e4SLinus Torvalds { 117*1da177e4SLinus Torvalds struct nlm_host *host; 118*1da177e4SLinus Torvalds struct nlm_file *file; 119*1da177e4SLinus Torvalds 120*1da177e4SLinus Torvalds dprintk("lockd: LOCK called\n"); 121*1da177e4SLinus Torvalds 122*1da177e4SLinus Torvalds resp->cookie = argp->cookie; 123*1da177e4SLinus Torvalds 124*1da177e4SLinus Torvalds /* Don't accept new lock requests during grace period */ 125*1da177e4SLinus Torvalds if (nlmsvc_grace_period && !argp->reclaim) { 126*1da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 127*1da177e4SLinus Torvalds return rpc_success; 128*1da177e4SLinus Torvalds } 129*1da177e4SLinus Torvalds 130*1da177e4SLinus Torvalds /* Obtain client and file */ 131*1da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 132*1da177e4SLinus Torvalds return rpc_success; 133*1da177e4SLinus Torvalds 134*1da177e4SLinus Torvalds #if 0 135*1da177e4SLinus Torvalds /* If supplied state doesn't match current state, we assume it's 136*1da177e4SLinus Torvalds * an old request that time-warped somehow. Any error return would 137*1da177e4SLinus Torvalds * do in this case because it's irrelevant anyway. 138*1da177e4SLinus Torvalds * 139*1da177e4SLinus Torvalds * NB: We don't retrieve the remote host's state yet. 140*1da177e4SLinus Torvalds */ 141*1da177e4SLinus Torvalds if (host->h_nsmstate && host->h_nsmstate != argp->state) { 142*1da177e4SLinus Torvalds resp->status = nlm_lck_denied_nolocks; 143*1da177e4SLinus Torvalds } else 144*1da177e4SLinus Torvalds #endif 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds /* Now try to lock the file */ 147*1da177e4SLinus Torvalds resp->status = nlmsvc_lock(rqstp, file, &argp->lock, 148*1da177e4SLinus Torvalds argp->block, &argp->cookie); 149*1da177e4SLinus Torvalds 150*1da177e4SLinus Torvalds dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 151*1da177e4SLinus Torvalds nlm_release_host(host); 152*1da177e4SLinus Torvalds nlm_release_file(file); 153*1da177e4SLinus Torvalds return rpc_success; 154*1da177e4SLinus Torvalds } 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds static int 157*1da177e4SLinus Torvalds nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, 158*1da177e4SLinus Torvalds struct nlm_res *resp) 159*1da177e4SLinus Torvalds { 160*1da177e4SLinus Torvalds struct nlm_host *host; 161*1da177e4SLinus Torvalds struct nlm_file *file; 162*1da177e4SLinus Torvalds 163*1da177e4SLinus Torvalds dprintk("lockd: CANCEL called\n"); 164*1da177e4SLinus Torvalds 165*1da177e4SLinus Torvalds resp->cookie = argp->cookie; 166*1da177e4SLinus Torvalds 167*1da177e4SLinus Torvalds /* Don't accept requests during grace period */ 168*1da177e4SLinus Torvalds if (nlmsvc_grace_period) { 169*1da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 170*1da177e4SLinus Torvalds return rpc_success; 171*1da177e4SLinus Torvalds } 172*1da177e4SLinus Torvalds 173*1da177e4SLinus Torvalds /* Obtain client and file */ 174*1da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 175*1da177e4SLinus Torvalds return rpc_success; 176*1da177e4SLinus Torvalds 177*1da177e4SLinus Torvalds /* Try to cancel request. */ 178*1da177e4SLinus Torvalds resp->status = nlmsvc_cancel_blocked(file, &argp->lock); 179*1da177e4SLinus Torvalds 180*1da177e4SLinus Torvalds dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 181*1da177e4SLinus Torvalds nlm_release_host(host); 182*1da177e4SLinus Torvalds nlm_release_file(file); 183*1da177e4SLinus Torvalds return rpc_success; 184*1da177e4SLinus Torvalds } 185*1da177e4SLinus Torvalds 186*1da177e4SLinus Torvalds /* 187*1da177e4SLinus Torvalds * UNLOCK: release a lock 188*1da177e4SLinus Torvalds */ 189*1da177e4SLinus Torvalds static int 190*1da177e4SLinus Torvalds nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, 191*1da177e4SLinus Torvalds struct nlm_res *resp) 192*1da177e4SLinus Torvalds { 193*1da177e4SLinus Torvalds struct nlm_host *host; 194*1da177e4SLinus Torvalds struct nlm_file *file; 195*1da177e4SLinus Torvalds 196*1da177e4SLinus Torvalds dprintk("lockd: UNLOCK called\n"); 197*1da177e4SLinus Torvalds 198*1da177e4SLinus Torvalds resp->cookie = argp->cookie; 199*1da177e4SLinus Torvalds 200*1da177e4SLinus Torvalds /* Don't accept new lock requests during grace period */ 201*1da177e4SLinus Torvalds if (nlmsvc_grace_period) { 202*1da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 203*1da177e4SLinus Torvalds return rpc_success; 204*1da177e4SLinus Torvalds } 205*1da177e4SLinus Torvalds 206*1da177e4SLinus Torvalds /* Obtain client and file */ 207*1da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 208*1da177e4SLinus Torvalds return rpc_success; 209*1da177e4SLinus Torvalds 210*1da177e4SLinus Torvalds /* Now try to remove the lock */ 211*1da177e4SLinus Torvalds resp->status = nlmsvc_unlock(file, &argp->lock); 212*1da177e4SLinus Torvalds 213*1da177e4SLinus Torvalds dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 214*1da177e4SLinus Torvalds nlm_release_host(host); 215*1da177e4SLinus Torvalds nlm_release_file(file); 216*1da177e4SLinus Torvalds return rpc_success; 217*1da177e4SLinus Torvalds } 218*1da177e4SLinus Torvalds 219*1da177e4SLinus Torvalds /* 220*1da177e4SLinus Torvalds * GRANTED: A server calls us to tell that a process' lock request 221*1da177e4SLinus Torvalds * was granted 222*1da177e4SLinus Torvalds */ 223*1da177e4SLinus Torvalds static int 224*1da177e4SLinus Torvalds nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, 225*1da177e4SLinus Torvalds struct nlm_res *resp) 226*1da177e4SLinus Torvalds { 227*1da177e4SLinus Torvalds resp->cookie = argp->cookie; 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds dprintk("lockd: GRANTED called\n"); 230*1da177e4SLinus Torvalds resp->status = nlmclnt_grant(&argp->lock); 231*1da177e4SLinus Torvalds dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 232*1da177e4SLinus Torvalds return rpc_success; 233*1da177e4SLinus Torvalds } 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds /* 236*1da177e4SLinus Torvalds * `Async' versions of the above service routines. They aren't really, 237*1da177e4SLinus Torvalds * because we send the callback before the reply proper. I hope this 238*1da177e4SLinus Torvalds * doesn't break any clients. 239*1da177e4SLinus Torvalds */ 240*1da177e4SLinus Torvalds static int 241*1da177e4SLinus Torvalds nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 242*1da177e4SLinus Torvalds void *resp) 243*1da177e4SLinus Torvalds { 244*1da177e4SLinus Torvalds struct nlm_res res; 245*1da177e4SLinus Torvalds u32 stat; 246*1da177e4SLinus Torvalds 247*1da177e4SLinus Torvalds dprintk("lockd: TEST_MSG called\n"); 248*1da177e4SLinus Torvalds memset(&res, 0, sizeof(res)); 249*1da177e4SLinus Torvalds 250*1da177e4SLinus Torvalds if ((stat = nlm4svc_proc_test(rqstp, argp, &res)) == 0) 251*1da177e4SLinus Torvalds stat = nlm4svc_callback(rqstp, NLMPROC_TEST_RES, &res); 252*1da177e4SLinus Torvalds return stat; 253*1da177e4SLinus Torvalds } 254*1da177e4SLinus Torvalds 255*1da177e4SLinus Torvalds static int 256*1da177e4SLinus Torvalds nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 257*1da177e4SLinus Torvalds void *resp) 258*1da177e4SLinus Torvalds { 259*1da177e4SLinus Torvalds struct nlm_res res; 260*1da177e4SLinus Torvalds u32 stat; 261*1da177e4SLinus Torvalds 262*1da177e4SLinus Torvalds dprintk("lockd: LOCK_MSG called\n"); 263*1da177e4SLinus Torvalds memset(&res, 0, sizeof(res)); 264*1da177e4SLinus Torvalds 265*1da177e4SLinus Torvalds if ((stat = nlm4svc_proc_lock(rqstp, argp, &res)) == 0) 266*1da177e4SLinus Torvalds stat = nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, &res); 267*1da177e4SLinus Torvalds return stat; 268*1da177e4SLinus Torvalds } 269*1da177e4SLinus Torvalds 270*1da177e4SLinus Torvalds static int 271*1da177e4SLinus Torvalds nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 272*1da177e4SLinus Torvalds void *resp) 273*1da177e4SLinus Torvalds { 274*1da177e4SLinus Torvalds struct nlm_res res; 275*1da177e4SLinus Torvalds u32 stat; 276*1da177e4SLinus Torvalds 277*1da177e4SLinus Torvalds dprintk("lockd: CANCEL_MSG called\n"); 278*1da177e4SLinus Torvalds memset(&res, 0, sizeof(res)); 279*1da177e4SLinus Torvalds 280*1da177e4SLinus Torvalds if ((stat = nlm4svc_proc_cancel(rqstp, argp, &res)) == 0) 281*1da177e4SLinus Torvalds stat = nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, &res); 282*1da177e4SLinus Torvalds return stat; 283*1da177e4SLinus Torvalds } 284*1da177e4SLinus Torvalds 285*1da177e4SLinus Torvalds static int 286*1da177e4SLinus Torvalds nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 287*1da177e4SLinus Torvalds void *resp) 288*1da177e4SLinus Torvalds { 289*1da177e4SLinus Torvalds struct nlm_res res; 290*1da177e4SLinus Torvalds u32 stat; 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds dprintk("lockd: UNLOCK_MSG called\n"); 293*1da177e4SLinus Torvalds memset(&res, 0, sizeof(res)); 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds if ((stat = nlm4svc_proc_unlock(rqstp, argp, &res)) == 0) 296*1da177e4SLinus Torvalds stat = nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, &res); 297*1da177e4SLinus Torvalds return stat; 298*1da177e4SLinus Torvalds } 299*1da177e4SLinus Torvalds 300*1da177e4SLinus Torvalds static int 301*1da177e4SLinus Torvalds nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, 302*1da177e4SLinus Torvalds void *resp) 303*1da177e4SLinus Torvalds { 304*1da177e4SLinus Torvalds struct nlm_res res; 305*1da177e4SLinus Torvalds u32 stat; 306*1da177e4SLinus Torvalds 307*1da177e4SLinus Torvalds dprintk("lockd: GRANTED_MSG called\n"); 308*1da177e4SLinus Torvalds memset(&res, 0, sizeof(res)); 309*1da177e4SLinus Torvalds 310*1da177e4SLinus Torvalds if ((stat = nlm4svc_proc_granted(rqstp, argp, &res)) == 0) 311*1da177e4SLinus Torvalds stat = nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, &res); 312*1da177e4SLinus Torvalds return stat; 313*1da177e4SLinus Torvalds } 314*1da177e4SLinus Torvalds 315*1da177e4SLinus Torvalds /* 316*1da177e4SLinus Torvalds * SHARE: create a DOS share or alter existing share. 317*1da177e4SLinus Torvalds */ 318*1da177e4SLinus Torvalds static int 319*1da177e4SLinus Torvalds nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, 320*1da177e4SLinus Torvalds struct nlm_res *resp) 321*1da177e4SLinus Torvalds { 322*1da177e4SLinus Torvalds struct nlm_host *host; 323*1da177e4SLinus Torvalds struct nlm_file *file; 324*1da177e4SLinus Torvalds 325*1da177e4SLinus Torvalds dprintk("lockd: SHARE called\n"); 326*1da177e4SLinus Torvalds 327*1da177e4SLinus Torvalds resp->cookie = argp->cookie; 328*1da177e4SLinus Torvalds 329*1da177e4SLinus Torvalds /* Don't accept new lock requests during grace period */ 330*1da177e4SLinus Torvalds if (nlmsvc_grace_period && !argp->reclaim) { 331*1da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 332*1da177e4SLinus Torvalds return rpc_success; 333*1da177e4SLinus Torvalds } 334*1da177e4SLinus Torvalds 335*1da177e4SLinus Torvalds /* Obtain client and file */ 336*1da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 337*1da177e4SLinus Torvalds return rpc_success; 338*1da177e4SLinus Torvalds 339*1da177e4SLinus Torvalds /* Now try to create the share */ 340*1da177e4SLinus Torvalds resp->status = nlmsvc_share_file(host, file, argp); 341*1da177e4SLinus Torvalds 342*1da177e4SLinus Torvalds dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); 343*1da177e4SLinus Torvalds nlm_release_host(host); 344*1da177e4SLinus Torvalds nlm_release_file(file); 345*1da177e4SLinus Torvalds return rpc_success; 346*1da177e4SLinus Torvalds } 347*1da177e4SLinus Torvalds 348*1da177e4SLinus Torvalds /* 349*1da177e4SLinus Torvalds * UNSHARE: Release a DOS share. 350*1da177e4SLinus Torvalds */ 351*1da177e4SLinus Torvalds static int 352*1da177e4SLinus Torvalds nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, 353*1da177e4SLinus Torvalds struct nlm_res *resp) 354*1da177e4SLinus Torvalds { 355*1da177e4SLinus Torvalds struct nlm_host *host; 356*1da177e4SLinus Torvalds struct nlm_file *file; 357*1da177e4SLinus Torvalds 358*1da177e4SLinus Torvalds dprintk("lockd: UNSHARE called\n"); 359*1da177e4SLinus Torvalds 360*1da177e4SLinus Torvalds resp->cookie = argp->cookie; 361*1da177e4SLinus Torvalds 362*1da177e4SLinus Torvalds /* Don't accept requests during grace period */ 363*1da177e4SLinus Torvalds if (nlmsvc_grace_period) { 364*1da177e4SLinus Torvalds resp->status = nlm_lck_denied_grace_period; 365*1da177e4SLinus Torvalds return rpc_success; 366*1da177e4SLinus Torvalds } 367*1da177e4SLinus Torvalds 368*1da177e4SLinus Torvalds /* Obtain client and file */ 369*1da177e4SLinus Torvalds if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 370*1da177e4SLinus Torvalds return rpc_success; 371*1da177e4SLinus Torvalds 372*1da177e4SLinus Torvalds /* Now try to lock the file */ 373*1da177e4SLinus Torvalds resp->status = nlmsvc_unshare_file(host, file, argp); 374*1da177e4SLinus Torvalds 375*1da177e4SLinus Torvalds dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); 376*1da177e4SLinus Torvalds nlm_release_host(host); 377*1da177e4SLinus Torvalds nlm_release_file(file); 378*1da177e4SLinus Torvalds return rpc_success; 379*1da177e4SLinus Torvalds } 380*1da177e4SLinus Torvalds 381*1da177e4SLinus Torvalds /* 382*1da177e4SLinus Torvalds * NM_LOCK: Create an unmonitored lock 383*1da177e4SLinus Torvalds */ 384*1da177e4SLinus Torvalds static int 385*1da177e4SLinus Torvalds nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp, 386*1da177e4SLinus Torvalds struct nlm_res *resp) 387*1da177e4SLinus Torvalds { 388*1da177e4SLinus Torvalds dprintk("lockd: NM_LOCK called\n"); 389*1da177e4SLinus Torvalds 390*1da177e4SLinus Torvalds argp->monitor = 0; /* just clean the monitor flag */ 391*1da177e4SLinus Torvalds return nlm4svc_proc_lock(rqstp, argp, resp); 392*1da177e4SLinus Torvalds } 393*1da177e4SLinus Torvalds 394*1da177e4SLinus Torvalds /* 395*1da177e4SLinus Torvalds * FREE_ALL: Release all locks and shares held by client 396*1da177e4SLinus Torvalds */ 397*1da177e4SLinus Torvalds static int 398*1da177e4SLinus Torvalds nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp, 399*1da177e4SLinus Torvalds void *resp) 400*1da177e4SLinus Torvalds { 401*1da177e4SLinus Torvalds struct nlm_host *host; 402*1da177e4SLinus Torvalds 403*1da177e4SLinus Torvalds /* Obtain client */ 404*1da177e4SLinus Torvalds if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL)) 405*1da177e4SLinus Torvalds return rpc_success; 406*1da177e4SLinus Torvalds 407*1da177e4SLinus Torvalds nlmsvc_free_host_resources(host); 408*1da177e4SLinus Torvalds nlm_release_host(host); 409*1da177e4SLinus Torvalds return rpc_success; 410*1da177e4SLinus Torvalds } 411*1da177e4SLinus Torvalds 412*1da177e4SLinus Torvalds /* 413*1da177e4SLinus Torvalds * SM_NOTIFY: private callback from statd (not part of official NLM proto) 414*1da177e4SLinus Torvalds */ 415*1da177e4SLinus Torvalds static int 416*1da177e4SLinus Torvalds nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, 417*1da177e4SLinus Torvalds void *resp) 418*1da177e4SLinus Torvalds { 419*1da177e4SLinus Torvalds struct sockaddr_in saddr = rqstp->rq_addr; 420*1da177e4SLinus Torvalds int vers = argp->vers; 421*1da177e4SLinus Torvalds int prot = argp->proto >> 1; 422*1da177e4SLinus Torvalds 423*1da177e4SLinus Torvalds struct nlm_host *host; 424*1da177e4SLinus Torvalds 425*1da177e4SLinus Torvalds dprintk("lockd: SM_NOTIFY called\n"); 426*1da177e4SLinus Torvalds if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) 427*1da177e4SLinus Torvalds || ntohs(saddr.sin_port) >= 1024) { 428*1da177e4SLinus Torvalds printk(KERN_WARNING 429*1da177e4SLinus Torvalds "lockd: rejected NSM callback from %08x:%d\n", 430*1da177e4SLinus Torvalds ntohl(rqstp->rq_addr.sin_addr.s_addr), 431*1da177e4SLinus Torvalds ntohs(rqstp->rq_addr.sin_port)); 432*1da177e4SLinus Torvalds return rpc_system_err; 433*1da177e4SLinus Torvalds } 434*1da177e4SLinus Torvalds 435*1da177e4SLinus Torvalds /* Obtain the host pointer for this NFS server and try to 436*1da177e4SLinus Torvalds * reclaim all locks we hold on this server. 437*1da177e4SLinus Torvalds */ 438*1da177e4SLinus Torvalds saddr.sin_addr.s_addr = argp->addr; 439*1da177e4SLinus Torvalds 440*1da177e4SLinus Torvalds if ((argp->proto & 1)==0) { 441*1da177e4SLinus Torvalds if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) { 442*1da177e4SLinus Torvalds nlmclnt_recovery(host, argp->state); 443*1da177e4SLinus Torvalds nlm_release_host(host); 444*1da177e4SLinus Torvalds } 445*1da177e4SLinus Torvalds } else { 446*1da177e4SLinus Torvalds /* If we run on an NFS server, delete all locks held by the client */ 447*1da177e4SLinus Torvalds 448*1da177e4SLinus Torvalds if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) { 449*1da177e4SLinus Torvalds nlmsvc_free_host_resources(host); 450*1da177e4SLinus Torvalds nlm_release_host(host); 451*1da177e4SLinus Torvalds } 452*1da177e4SLinus Torvalds } 453*1da177e4SLinus Torvalds return rpc_success; 454*1da177e4SLinus Torvalds } 455*1da177e4SLinus Torvalds 456*1da177e4SLinus Torvalds /* 457*1da177e4SLinus Torvalds * client sent a GRANTED_RES, let's remove the associated block 458*1da177e4SLinus Torvalds */ 459*1da177e4SLinus Torvalds static int 460*1da177e4SLinus Torvalds nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, 461*1da177e4SLinus Torvalds void *resp) 462*1da177e4SLinus Torvalds { 463*1da177e4SLinus Torvalds if (!nlmsvc_ops) 464*1da177e4SLinus Torvalds return rpc_success; 465*1da177e4SLinus Torvalds 466*1da177e4SLinus Torvalds dprintk("lockd: GRANTED_RES called\n"); 467*1da177e4SLinus Torvalds 468*1da177e4SLinus Torvalds nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status); 469*1da177e4SLinus Torvalds return rpc_success; 470*1da177e4SLinus Torvalds } 471*1da177e4SLinus Torvalds 472*1da177e4SLinus Torvalds 473*1da177e4SLinus Torvalds 474*1da177e4SLinus Torvalds /* 475*1da177e4SLinus Torvalds * This is the generic lockd callback for async RPC calls 476*1da177e4SLinus Torvalds */ 477*1da177e4SLinus Torvalds static u32 478*1da177e4SLinus Torvalds nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) 479*1da177e4SLinus Torvalds { 480*1da177e4SLinus Torvalds struct nlm_host *host; 481*1da177e4SLinus Torvalds struct nlm_rqst *call; 482*1da177e4SLinus Torvalds 483*1da177e4SLinus Torvalds if (!(call = nlmclnt_alloc_call())) 484*1da177e4SLinus Torvalds return rpc_system_err; 485*1da177e4SLinus Torvalds 486*1da177e4SLinus Torvalds host = nlmclnt_lookup_host(&rqstp->rq_addr, 487*1da177e4SLinus Torvalds rqstp->rq_prot, rqstp->rq_vers); 488*1da177e4SLinus Torvalds if (!host) { 489*1da177e4SLinus Torvalds kfree(call); 490*1da177e4SLinus Torvalds return rpc_system_err; 491*1da177e4SLinus Torvalds } 492*1da177e4SLinus Torvalds 493*1da177e4SLinus Torvalds call->a_flags = RPC_TASK_ASYNC; 494*1da177e4SLinus Torvalds call->a_host = host; 495*1da177e4SLinus Torvalds memcpy(&call->a_args, resp, sizeof(*resp)); 496*1da177e4SLinus Torvalds 497*1da177e4SLinus Torvalds if (nlmsvc_async_call(call, proc, nlm4svc_callback_exit) < 0) 498*1da177e4SLinus Torvalds goto error; 499*1da177e4SLinus Torvalds 500*1da177e4SLinus Torvalds return rpc_success; 501*1da177e4SLinus Torvalds error: 502*1da177e4SLinus Torvalds kfree(call); 503*1da177e4SLinus Torvalds nlm_release_host(host); 504*1da177e4SLinus Torvalds return rpc_system_err; 505*1da177e4SLinus Torvalds } 506*1da177e4SLinus Torvalds 507*1da177e4SLinus Torvalds static void 508*1da177e4SLinus Torvalds nlm4svc_callback_exit(struct rpc_task *task) 509*1da177e4SLinus Torvalds { 510*1da177e4SLinus Torvalds struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; 511*1da177e4SLinus Torvalds 512*1da177e4SLinus Torvalds if (task->tk_status < 0) { 513*1da177e4SLinus Torvalds dprintk("lockd: %4d callback failed (errno = %d)\n", 514*1da177e4SLinus Torvalds task->tk_pid, -task->tk_status); 515*1da177e4SLinus Torvalds } 516*1da177e4SLinus Torvalds nlm_release_host(call->a_host); 517*1da177e4SLinus Torvalds kfree(call); 518*1da177e4SLinus Torvalds } 519*1da177e4SLinus Torvalds 520*1da177e4SLinus Torvalds /* 521*1da177e4SLinus Torvalds * NLM Server procedures. 522*1da177e4SLinus Torvalds */ 523*1da177e4SLinus Torvalds 524*1da177e4SLinus Torvalds #define nlm4svc_encode_norep nlm4svc_encode_void 525*1da177e4SLinus Torvalds #define nlm4svc_decode_norep nlm4svc_decode_void 526*1da177e4SLinus Torvalds #define nlm4svc_decode_testres nlm4svc_decode_void 527*1da177e4SLinus Torvalds #define nlm4svc_decode_lockres nlm4svc_decode_void 528*1da177e4SLinus Torvalds #define nlm4svc_decode_unlockres nlm4svc_decode_void 529*1da177e4SLinus Torvalds #define nlm4svc_decode_cancelres nlm4svc_decode_void 530*1da177e4SLinus Torvalds #define nlm4svc_decode_grantedres nlm4svc_decode_void 531*1da177e4SLinus Torvalds 532*1da177e4SLinus Torvalds #define nlm4svc_proc_none nlm4svc_proc_null 533*1da177e4SLinus Torvalds #define nlm4svc_proc_test_res nlm4svc_proc_null 534*1da177e4SLinus Torvalds #define nlm4svc_proc_lock_res nlm4svc_proc_null 535*1da177e4SLinus Torvalds #define nlm4svc_proc_cancel_res nlm4svc_proc_null 536*1da177e4SLinus Torvalds #define nlm4svc_proc_unlock_res nlm4svc_proc_null 537*1da177e4SLinus Torvalds 538*1da177e4SLinus Torvalds struct nlm_void { int dummy; }; 539*1da177e4SLinus Torvalds 540*1da177e4SLinus Torvalds #define PROC(name, xargt, xrest, argt, rest, respsize) \ 541*1da177e4SLinus Torvalds { .pc_func = (svc_procfunc) nlm4svc_proc_##name, \ 542*1da177e4SLinus Torvalds .pc_decode = (kxdrproc_t) nlm4svc_decode_##xargt, \ 543*1da177e4SLinus Torvalds .pc_encode = (kxdrproc_t) nlm4svc_encode_##xrest, \ 544*1da177e4SLinus Torvalds .pc_release = NULL, \ 545*1da177e4SLinus Torvalds .pc_argsize = sizeof(struct nlm_##argt), \ 546*1da177e4SLinus Torvalds .pc_ressize = sizeof(struct nlm_##rest), \ 547*1da177e4SLinus Torvalds .pc_xdrressize = respsize, \ 548*1da177e4SLinus Torvalds } 549*1da177e4SLinus Torvalds #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ 550*1da177e4SLinus Torvalds #define No (1+1024/4) /* netobj */ 551*1da177e4SLinus Torvalds #define St 1 /* status */ 552*1da177e4SLinus Torvalds #define Rg 4 /* range (offset + length) */ 553*1da177e4SLinus Torvalds struct svc_procedure nlmsvc_procedures4[] = { 554*1da177e4SLinus Torvalds PROC(null, void, void, void, void, 1), 555*1da177e4SLinus Torvalds PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg), 556*1da177e4SLinus Torvalds PROC(lock, lockargs, res, args, res, Ck+St), 557*1da177e4SLinus Torvalds PROC(cancel, cancargs, res, args, res, Ck+St), 558*1da177e4SLinus Torvalds PROC(unlock, unlockargs, res, args, res, Ck+St), 559*1da177e4SLinus Torvalds PROC(granted, testargs, res, args, res, Ck+St), 560*1da177e4SLinus Torvalds PROC(test_msg, testargs, norep, args, void, 1), 561*1da177e4SLinus Torvalds PROC(lock_msg, lockargs, norep, args, void, 1), 562*1da177e4SLinus Torvalds PROC(cancel_msg, cancargs, norep, args, void, 1), 563*1da177e4SLinus Torvalds PROC(unlock_msg, unlockargs, norep, args, void, 1), 564*1da177e4SLinus Torvalds PROC(granted_msg, testargs, norep, args, void, 1), 565*1da177e4SLinus Torvalds PROC(test_res, testres, norep, res, void, 1), 566*1da177e4SLinus Torvalds PROC(lock_res, lockres, norep, res, void, 1), 567*1da177e4SLinus Torvalds PROC(cancel_res, cancelres, norep, res, void, 1), 568*1da177e4SLinus Torvalds PROC(unlock_res, unlockres, norep, res, void, 1), 569*1da177e4SLinus Torvalds PROC(granted_res, res, norep, res, void, 1), 570*1da177e4SLinus Torvalds /* statd callback */ 571*1da177e4SLinus Torvalds PROC(sm_notify, reboot, void, reboot, void, 1), 572*1da177e4SLinus Torvalds PROC(none, void, void, void, void, 0), 573*1da177e4SLinus Torvalds PROC(none, void, void, void, void, 0), 574*1da177e4SLinus Torvalds PROC(none, void, void, void, void, 0), 575*1da177e4SLinus Torvalds PROC(share, shareargs, shareres, args, res, Ck+St+1), 576*1da177e4SLinus Torvalds PROC(unshare, shareargs, shareres, args, res, Ck+St+1), 577*1da177e4SLinus Torvalds PROC(nm_lock, lockargs, res, args, res, Ck+St), 578*1da177e4SLinus Torvalds PROC(free_all, notify, void, args, void, 1), 579*1da177e4SLinus Torvalds 580*1da177e4SLinus Torvalds }; 581