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