clntproc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:17k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/lockd/clntproc.c
  3.  *
  4.  * RPC procedures for the client side NLM implementation
  5.  *
  6.  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  7.  */
  8. #include <linux/config.h>
  9. #include <linux/types.h>
  10. #include <linux/errno.h>
  11. #include <linux/fs.h>
  12. #include <linux/nfs_fs.h>
  13. #include <linux/utsname.h>
  14. #include <linux/smp_lock.h>
  15. #include <linux/sunrpc/clnt.h>
  16. #include <linux/sunrpc/svc.h>
  17. #include <linux/lockd/lockd.h>
  18. #include <linux/lockd/sm_inter.h>
  19. #define NLMDBG_FACILITY NLMDBG_CLIENT
  20. #define NLMCLNT_GRACE_WAIT (5*HZ)
  21. static int nlmclnt_test(struct nlm_rqst *, struct file_lock *);
  22. static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
  23. static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
  24. static void nlmclnt_unlock_callback(struct rpc_task *);
  25. static void nlmclnt_cancel_callback(struct rpc_task *);
  26. static int nlm_stat_to_errno(u32 stat);
  27. /*
  28.  * Cookie counter for NLM requests
  29.  */
  30. static u32 nlm_cookie = 0x1234;
  31. static inline void nlmclnt_next_cookie(struct nlm_cookie *c)
  32. {
  33. memcpy(c->data, &nlm_cookie, 4);
  34. memset(c->data+4, 0, 4);
  35. c->len=4;
  36. nlm_cookie++;
  37. }
  38. /*
  39.  * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls
  40.  */
  41. static inline void
  42. nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
  43. {
  44. struct nlm_args *argp = &req->a_args;
  45. struct nlm_lock *lock = &argp->lock;
  46. nlmclnt_next_cookie(&argp->cookie);
  47. argp->state   = nsm_local_state;
  48. memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
  49. lock->caller  = system_utsname.nodename;
  50. lock->oh.data = req->a_owner;
  51. lock->oh.len  = sprintf(req->a_owner, "%d@%s",
  52. current->pid, system_utsname.nodename);
  53. locks_copy_lock(&lock->fl, fl);
  54. }
  55. /*
  56.  * Initialize arguments for GRANTED call. The nlm_rqst structure
  57.  * has been cleared already.
  58.  */
  59. int
  60. nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
  61. {
  62. locks_copy_lock(&call->a_args.lock.fl, &lock->fl);
  63. memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh));
  64. call->a_args.lock.caller = system_utsname.nodename;
  65. call->a_args.lock.oh.len = lock->oh.len;
  66. /* set default data area */
  67. call->a_args.lock.oh.data = call->a_owner;
  68. if (lock->oh.len > NLMCLNT_OHSIZE) {
  69. void *data = kmalloc(lock->oh.len, GFP_KERNEL);
  70. if (!data)
  71. return 0;
  72. call->a_args.lock.oh.data = (u8 *) data;
  73. }
  74. memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len);
  75. return 1;
  76. }
  77. void
  78. nlmclnt_freegrantargs(struct nlm_rqst *call)
  79. {
  80. /*
  81.  * Check whether we allocated memory for the owner.
  82.  */
  83. if (call->a_args.lock.oh.data != (u8 *) call->a_owner) {
  84. kfree(call->a_args.lock.oh.data);
  85. }
  86. }
  87. /*
  88.  * This is the main entry point for the NLM client.
  89.  */
  90. int
  91. nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
  92. {
  93. struct nfs_server *nfssrv = NFS_SERVER(inode);
  94. struct nlm_host *host;
  95. struct nlm_rqst reqst, *call = &reqst;
  96. sigset_t oldset;
  97. unsigned long flags;
  98. int status, proto, vers;
  99. vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1;
  100. if (NFS_PROTO(inode)->version > 3) {
  101. printk(KERN_NOTICE "NFSv4 file locking not implemented!n");
  102. return -ENOLCK;
  103. }
  104. /* Retrieve transport protocol from NFS client */
  105. proto = NFS_CLIENT(inode)->cl_xprt->prot;
  106. if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers)))
  107. return -ENOLCK;
  108. /* Create RPC client handle if not there, and copy soft
  109.  * and intr flags from NFS client. */
  110. if (host->h_rpcclnt == NULL) {
  111. struct rpc_clnt *clnt;
  112. /* Bind an rpc client to this host handle (does not
  113.  * perform a portmapper lookup) */
  114. if (!(clnt = nlm_bind_host(host))) {
  115. status = -ENOLCK;
  116. goto done;
  117. }
  118. clnt->cl_softrtry = nfssrv->client->cl_softrtry;
  119. clnt->cl_intr     = nfssrv->client->cl_intr;
  120. clnt->cl_chatty   = nfssrv->client->cl_chatty;
  121. }
  122. /* Keep the old signal mask */
  123. spin_lock_irqsave(&current->sigmask_lock, flags);
  124. oldset = current->blocked;
  125. /* If we're cleaning up locks because the process is exiting,
  126.  * perform the RPC call asynchronously. */
  127. if ((IS_SETLK(cmd) || IS_SETLKW(cmd))
  128.     && fl->fl_type == F_UNLCK
  129.     && (current->flags & PF_EXITING)) {
  130. sigfillset(&current->blocked); /* Mask all signals */
  131. recalc_sigpending(current);
  132. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  133. call = nlmclnt_alloc_call();
  134. if (!call) {
  135. status = -ENOMEM;
  136. goto out_restore;
  137. }
  138. call->a_flags = RPC_TASK_ASYNC;
  139. } else {
  140. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  141. memset(call, 0, sizeof(*call));
  142. locks_init_lock(&call->a_args.lock.fl);
  143. locks_init_lock(&call->a_res.lock.fl);
  144. }
  145. call->a_host = host;
  146. /* Set up the argument struct */
  147. nlmclnt_setlockargs(call, fl);
  148. if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
  149. if (fl->fl_type != F_UNLCK) {
  150. call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
  151. status = nlmclnt_lock(call, fl);
  152. } else
  153. status = nlmclnt_unlock(call, fl);
  154. } else if (IS_GETLK(cmd))
  155. status = nlmclnt_test(call, fl);
  156. else
  157. status = -EINVAL;
  158. if (status < 0 && (call->a_flags & RPC_TASK_ASYNC))
  159. kfree(call);
  160.  out_restore:
  161. spin_lock_irqsave(&current->sigmask_lock, flags);
  162. current->blocked = oldset;
  163. recalc_sigpending(current);
  164. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  165. done:
  166. dprintk("lockd: clnt proc returns %dn", status);
  167. nlm_release_host(host);
  168. return status;
  169. }
  170. /*
  171.  * Wait while server is in grace period
  172.  */
  173. static inline int
  174. nlmclnt_grace_wait(struct nlm_host *host)
  175. {
  176. if (!host->h_reclaiming)
  177. interruptible_sleep_on_timeout(&host->h_gracewait, 10*HZ);
  178. else
  179. interruptible_sleep_on(&host->h_gracewait);
  180. return signalled()? -ERESTARTSYS : 0;
  181. }
  182. /*
  183.  * Allocate an NLM RPC call struct
  184.  */
  185. struct nlm_rqst *
  186. nlmclnt_alloc_call(void)
  187. {
  188. struct nlm_rqst *call;
  189. while (!signalled()) {
  190. call = (struct nlm_rqst *) kmalloc(sizeof(struct nlm_rqst), GFP_KERNEL);
  191. if (call) {
  192. memset(call, 0, sizeof(*call));
  193. locks_init_lock(&call->a_args.lock.fl);
  194. locks_init_lock(&call->a_res.lock.fl);
  195. return call;
  196. }
  197. printk("nlmclnt_alloc_call: failed, waiting for memoryn");
  198. current->state = TASK_INTERRUPTIBLE;
  199. schedule_timeout(5*HZ);
  200. }
  201. return NULL;
  202. }
  203. /*
  204.  * Generic NLM call
  205.  */
  206. int
  207. nlmclnt_call(struct nlm_rqst *req, u32 proc)
  208. {
  209. struct nlm_host *host = req->a_host;
  210. struct rpc_clnt *clnt;
  211. struct nlm_args *argp = &req->a_args;
  212. struct nlm_res *resp = &req->a_res;
  213. struct file *filp = argp->lock.fl.fl_file;
  214. struct rpc_message msg;
  215. int status;
  216. dprintk("lockd: call procedure %s on %sn",
  217. nlm_procname(proc), host->h_name);
  218. msg.rpc_proc = proc;
  219. msg.rpc_argp = argp;
  220. msg.rpc_resp = resp;
  221. if (filp)
  222. msg.rpc_cred = nfs_file_cred(filp);
  223. else
  224. msg.rpc_cred = NULL;
  225. do {
  226. if (host->h_reclaiming && !argp->reclaim) {
  227. interruptible_sleep_on(&host->h_gracewait);
  228. continue;
  229. }
  230. /* If we have no RPC client yet, create one. */
  231. if ((clnt = nlm_bind_host(host)) == NULL)
  232. return -ENOLCK;
  233. /* Perform the RPC call. If an error occurs, try again */
  234. if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) {
  235. dprintk("lockd: rpc_call returned error %dn", -status);
  236. switch (status) {
  237. case -EPROTONOSUPPORT:
  238. status = -EINVAL;
  239. break;
  240. case -ECONNREFUSED:
  241. case -ETIMEDOUT:
  242. case -ENOTCONN:
  243. nlm_rebind_host(host);
  244. status = -EAGAIN;
  245. break;
  246. case -ERESTARTSYS:
  247. return signalled () ? -EINTR : status;
  248. default:
  249. break;
  250. }
  251. break;
  252. } else
  253. if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) {
  254. dprintk("lockd: server in grace periodn");
  255. if (argp->reclaim) {
  256. printk(KERN_WARNING
  257.      "lockd: spurious grace period reject?!n");
  258. return -ENOLCK;
  259. }
  260. } else {
  261. dprintk("lockd: server returns status %dn", resp->status);
  262. return 0; /* Okay, call complete */
  263. }
  264. /* Back off a little and try again */
  265. interruptible_sleep_on_timeout(&host->h_gracewait, 15*HZ);
  266. /* When the lock requested by F_SETLKW isn't available,
  267.    we will wait until the request can be satisfied. If
  268.    a signal is received during wait, we should return
  269.    -EINTR. */
  270. if (signalled ()) {
  271. status = -EINTR;
  272. break;
  273. }
  274. } while (1);
  275. return status;
  276. }
  277. /*
  278.  * Generic NLM call, async version.
  279.  */
  280. int
  281. nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
  282. {
  283. struct nlm_host *host = req->a_host;
  284. struct rpc_clnt *clnt;
  285. struct nlm_args *argp = &req->a_args;
  286. struct nlm_res *resp = &req->a_res;
  287. struct rpc_message msg;
  288. int status;
  289. dprintk("lockd: call procedure %s on %s (async)n",
  290. nlm_procname(proc), host->h_name);
  291. /* If we have no RPC client yet, create one. */
  292. if ((clnt = nlm_bind_host(host)) == NULL)
  293. return -ENOLCK;
  294.         /* bootstrap and kick off the async RPC call */
  295. msg.rpc_proc = proc;
  296. msg.rpc_argp = argp;
  297. msg.rpc_resp =resp;
  298. msg.rpc_cred = NULL;
  299.         status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
  300. return status;
  301. }
  302. int
  303. nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
  304. {
  305. struct nlm_host *host = req->a_host;
  306. struct rpc_clnt *clnt;
  307. struct nlm_args *argp = &req->a_args;
  308. struct nlm_res *resp = &req->a_res;
  309. struct file *file = argp->lock.fl.fl_file;
  310. struct rpc_message msg;
  311. int status;
  312. dprintk("lockd: call procedure %s on %s (async)n",
  313. nlm_procname(proc), host->h_name);
  314. /* If we have no RPC client yet, create one. */
  315. if ((clnt = nlm_bind_host(host)) == NULL)
  316. return -ENOLCK;
  317.         /* bootstrap and kick off the async RPC call */
  318. msg.rpc_proc = proc;
  319. msg.rpc_argp = argp;
  320. msg.rpc_resp =resp;
  321. if (file)
  322. msg.rpc_cred = nfs_file_cred(file);
  323. else
  324. msg.rpc_cred = NULL;
  325. /* Increment host refcount */
  326. nlm_get_host(host);
  327.         status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
  328. if (status < 0)
  329. nlm_release_host(host);
  330. return status;
  331. }
  332. /*
  333.  * TEST for the presence of a conflicting lock
  334.  */
  335. static int
  336. nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
  337. {
  338. int status;
  339. if ((status = nlmclnt_call(req, NLMPROC_TEST)) < 0)
  340. return status;
  341. status = req->a_res.status;
  342. if (status == NLM_LCK_GRANTED) {
  343. fl->fl_type = F_UNLCK;
  344. } if (status == NLM_LCK_DENIED) {
  345. /*
  346.  * Report the conflicting lock back to the application.
  347.  * FIXME: Is it OK to report the pid back as well?
  348.  */
  349. locks_copy_lock(fl, &req->a_res.lock.fl);
  350. /* fl->fl_pid = 0; */
  351. } else {
  352. return nlm_stat_to_errno(req->a_res.status);
  353. }
  354. return 0;
  355. }
  356. static
  357. void nlmclnt_insert_lock_callback(struct file_lock *fl)
  358. {
  359. nlm_get_host(fl->fl_u.nfs_fl.host);
  360. }
  361. static
  362. void nlmclnt_remove_lock_callback(struct file_lock *fl)
  363. {
  364. if (fl->fl_u.nfs_fl.host) {
  365. nlm_release_host(fl->fl_u.nfs_fl.host);
  366. fl->fl_u.nfs_fl.host = NULL;
  367. }
  368. }
  369. /*
  370.  * LOCK: Try to create a lock
  371.  *
  372.  * Programmer Harassment Alert
  373.  *
  374.  * When given a blocking lock request in a sync RPC call, the HPUX lockd
  375.  * will faithfully return LCK_BLOCKED but never cares to notify us when
  376.  * the lock could be granted. This way, our local process could hang
  377.  * around forever waiting for the callback.
  378.  *
  379.  *  Solution A: Implement busy-waiting
  380.  *  Solution B: Use the async version of the call (NLM_LOCK_{MSG,RES})
  381.  *
  382.  * For now I am implementing solution A, because I hate the idea of
  383.  * re-implementing lockd for a third time in two months. The async
  384.  * calls shouldn't be too hard to do, however.
  385.  *
  386.  * This is one of the lovely things about standards in the NFS area:
  387.  * they're so soft and squishy you can't really blame HP for doing this.
  388.  */
  389. static int
  390. nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
  391. {
  392. struct nlm_host *host = req->a_host;
  393. struct nlm_res *resp = &req->a_res;
  394. int status;
  395. if (!host->h_monitored && nsm_monitor(host) < 0) {
  396. printk(KERN_NOTICE "lockd: failed to monitor %sn",
  397. host->h_name);
  398. return -ENOLCK;
  399. }
  400. do {
  401. if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) {
  402. if (resp->status != NLM_LCK_BLOCKED)
  403. break;
  404. status = nlmclnt_block(host, fl, &resp->status);
  405. }
  406. if (status < 0)
  407. return status;
  408. } while (resp->status == NLM_LCK_BLOCKED);
  409. if (resp->status == NLM_LCK_GRANTED) {
  410. fl->fl_u.nfs_fl.state = host->h_state;
  411. fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
  412. fl->fl_u.nfs_fl.host = host;
  413. fl->fl_insert = nlmclnt_insert_lock_callback;
  414. fl->fl_remove = nlmclnt_remove_lock_callback;
  415. }
  416. return nlm_stat_to_errno(resp->status);
  417. }
  418. /*
  419.  * RECLAIM: Try to reclaim a lock
  420.  */
  421. int
  422. nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl)
  423. {
  424. struct nlm_rqst reqst, *req;
  425. int status;
  426. req = &reqst;
  427. memset(req, 0, sizeof(*req));
  428. locks_init_lock(&req->a_args.lock.fl);
  429. locks_init_lock(&req->a_res.lock.fl);
  430. req->a_host  = host;
  431. req->a_flags = 0;
  432. /* Set up the argument struct */
  433. nlmclnt_setlockargs(req, fl);
  434. req->a_args.reclaim = 1;
  435. if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
  436.  && req->a_res.status == NLM_LCK_GRANTED)
  437. return 0;
  438. printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
  439. "(errno %d, status %d)n", fl->fl_pid,
  440. status, req->a_res.status);
  441. /*
  442.  * FIXME: This is a serious failure. We can
  443.  *
  444.  *  a. Ignore the problem
  445.  *  b. Send the owning process some signal (Linux doesn't have
  446.  * SIGLOST, though...)
  447.  *  c. Retry the operation
  448.  *
  449.  * Until someone comes up with a simple implementation
  450.  * for b or c, I'll choose option a.
  451.  */
  452. return -ENOLCK;
  453. }
  454. /*
  455.  * UNLOCK: remove an existing lock
  456.  */
  457. static int
  458. nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
  459. {
  460. struct nlm_res *resp = &req->a_res;
  461. int status;
  462. /* Clean the GRANTED flag now so the lock doesn't get
  463.  * reclaimed while we're stuck in the unlock call. */
  464. fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
  465. if (req->a_flags & RPC_TASK_ASYNC) {
  466. return nlmclnt_async_call(req, NLMPROC_UNLOCK,
  467. nlmclnt_unlock_callback);
  468. }
  469. if ((status = nlmclnt_call(req, NLMPROC_UNLOCK)) < 0)
  470. return status;
  471. if (resp->status == NLM_LCK_GRANTED)
  472. return 0;
  473. if (resp->status != NLM_LCK_DENIED_NOLOCKS)
  474. printk("lockd: unexpected unlock status: %dn", resp->status);
  475. /* What to do now? I'm out of my depth... */
  476. return -ENOLCK;
  477. }
  478. static void
  479. nlmclnt_unlock_callback(struct rpc_task *task)
  480. {
  481. struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata;
  482. int status = req->a_res.status;
  483. if (RPC_ASSASSINATED(task))
  484. goto die;
  485. if (task->tk_status < 0) {
  486. dprintk("lockd: unlock failed (err = %d)n", -task->tk_status);
  487. goto retry_rebind;
  488. }
  489. if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
  490. rpc_delay(task, NLMCLNT_GRACE_WAIT);
  491. goto retry_unlock;
  492. }
  493. if (status != NLM_LCK_GRANTED)
  494. printk(KERN_WARNING "lockd: unexpected unlock status: %dn", status);
  495. die:
  496. nlm_release_host(req->a_host);
  497. kfree(req);
  498. return;
  499.  retry_rebind:
  500. nlm_rebind_host(req->a_host);
  501.  retry_unlock:
  502. rpc_restart_call(task);
  503. }
  504. /*
  505.  * Cancel a blocked lock request.
  506.  * We always use an async RPC call for this in order not to hang a
  507.  * process that has been Ctrl-C'ed.
  508.  */
  509. int
  510. nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
  511. {
  512. struct nlm_rqst *req;
  513. unsigned long flags;
  514. sigset_t oldset;
  515. int status;
  516. /* Block all signals while setting up call */
  517. spin_lock_irqsave(&current->sigmask_lock, flags);
  518. oldset = current->blocked;
  519. sigfillset(&current->blocked);
  520. recalc_sigpending(current);
  521. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  522. req = nlmclnt_alloc_call();
  523. if (!req)
  524. return -ENOMEM;
  525. req->a_host  = host;
  526. req->a_flags = RPC_TASK_ASYNC;
  527. nlmclnt_setlockargs(req, fl);
  528. status = nlmclnt_async_call(req, NLMPROC_CANCEL,
  529. nlmclnt_cancel_callback);
  530. if (status < 0)
  531. kfree(req);
  532. spin_lock_irqsave(&current->sigmask_lock, flags);
  533. current->blocked = oldset;
  534. recalc_sigpending(current);
  535. spin_unlock_irqrestore(&current->sigmask_lock, flags);
  536. return status;
  537. }
  538. static void
  539. nlmclnt_cancel_callback(struct rpc_task *task)
  540. {
  541. struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata;
  542. if (RPC_ASSASSINATED(task))
  543. goto die;
  544. if (task->tk_status < 0) {
  545. dprintk("lockd: CANCEL call error %d, retrying.n",
  546. task->tk_status);
  547. goto retry_cancel;
  548. }
  549. dprintk("lockd: cancel status %d (task %d)n",
  550. req->a_res.status, task->tk_pid);
  551. switch (req->a_res.status) {
  552. case NLM_LCK_GRANTED:
  553. case NLM_LCK_DENIED_GRACE_PERIOD:
  554. /* Everything's good */
  555. break;
  556. case NLM_LCK_DENIED_NOLOCKS:
  557. dprintk("lockd: CANCEL failed (server has no locks)n");
  558. goto retry_cancel;
  559. default:
  560. printk(KERN_NOTICE "lockd: weird return %d for CANCEL calln",
  561. req->a_res.status);
  562. }
  563. die:
  564. nlm_release_host(req->a_host);
  565. kfree(req);
  566. return;
  567. retry_cancel:
  568. nlm_rebind_host(req->a_host);
  569. rpc_restart_call(task);
  570. rpc_delay(task, 30 * HZ);
  571. }
  572. /*
  573.  * Convert an NLM status code to a generic kernel errno
  574.  */
  575. static int
  576. nlm_stat_to_errno(u32 status)
  577. {
  578. switch(status) {
  579. case NLM_LCK_GRANTED:
  580. return 0;
  581. case NLM_LCK_DENIED:
  582. return -EAGAIN;
  583. case NLM_LCK_DENIED_NOLOCKS:
  584. case NLM_LCK_DENIED_GRACE_PERIOD:
  585. return -ENOLCK;
  586. case NLM_LCK_BLOCKED:
  587. printk(KERN_NOTICE "lockd: unexpected status NLM_BLOCKEDn");
  588. return -ENOLCK;
  589. #ifdef CONFIG_LOCKD_V4
  590. case NLM_DEADLCK:
  591. return -EDEADLK;
  592. case NLM_ROFS:
  593. return -EROFS;
  594. case NLM_STALE_FH:
  595. return -ESTALE;
  596. case NLM_FBIG:
  597. return -EOVERFLOW;
  598. case NLM_FAILED:
  599. return -ENOLCK;
  600. #endif
  601. }
  602. printk(KERN_NOTICE "lockd: unexpected server status %dn", status);
  603. return -ENOLCK;
  604. }