Lines Matching +full:lock +full:- +full:status
1 // SPDX-License-Identifier: GPL-2.0-only
49 memcpy(c->data, &cookie, 4); in nlmclnt_next_cookie()
50 c->len=4; in nlmclnt_next_cookie()
56 refcount_inc(&lockowner->count); in nlmclnt_get_lockowner()
62 if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock)) in nlmclnt_put_lockowner()
64 list_del(&lockowner->list); in nlmclnt_put_lockowner()
65 spin_unlock(&lockowner->host->h_lock); in nlmclnt_put_lockowner()
66 nlmclnt_release_host(lockowner->host); in nlmclnt_put_lockowner()
73 list_for_each_entry(lockowner, &host->h_lockowners, list) { in nlm_pidbusy()
74 if (lockowner->pid == pid) in nlm_pidbusy()
75 return -EBUSY; in nlm_pidbusy()
84 res = host->h_pidcount++; in __nlm_alloc_pid()
92 list_for_each_entry(lockowner, &host->h_lockowners, list) { in __nlmclnt_find_lockowner()
93 if (lockowner->owner != owner) in __nlmclnt_find_lockowner()
104 spin_lock(&host->h_lock); in nlmclnt_find_lockowner()
107 spin_unlock(&host->h_lock); in nlmclnt_find_lockowner()
109 spin_lock(&host->h_lock); in nlmclnt_find_lockowner()
113 refcount_set(&new->count, 1); in nlmclnt_find_lockowner()
114 new->owner = owner; in nlmclnt_find_lockowner()
115 new->pid = __nlm_alloc_pid(host); in nlmclnt_find_lockowner()
116 new->host = nlm_get_host(host); in nlmclnt_find_lockowner()
117 list_add(&new->list, &host->h_lockowners); in nlmclnt_find_lockowner()
121 spin_unlock(&host->h_lock); in nlmclnt_find_lockowner()
127 * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls
131 struct nlm_args *argp = &req->a_args; in nlmclnt_setlockargs()
132 struct nlm_lock *lock = &argp->lock; in nlmclnt_setlockargs() local
133 char *nodename = req->a_host->h_rpcclnt->cl_nodename; in nlmclnt_setlockargs()
135 nlmclnt_next_cookie(&argp->cookie); in nlmclnt_setlockargs()
136 memcpy(&lock->fh, NFS_FH(file_inode(fl->c.flc_file)), in nlmclnt_setlockargs()
138 lock->caller = nodename; in nlmclnt_setlockargs()
139 lock->oh.data = req->a_owner; in nlmclnt_setlockargs()
140 lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", in nlmclnt_setlockargs()
141 (unsigned int)fl->fl_u.nfs_fl.owner->pid, in nlmclnt_setlockargs()
143 lock->svid = fl->fl_u.nfs_fl.owner->pid; in nlmclnt_setlockargs()
144 lock->fl.fl_start = fl->fl_start; in nlmclnt_setlockargs()
145 lock->fl.fl_end = fl->fl_end; in nlmclnt_setlockargs()
146 lock->fl.c.flc_type = fl->c.flc_type; in nlmclnt_setlockargs()
151 WARN_ON_ONCE(req->a_args.lock.fl.fl_ops != NULL); in nlmclnt_release_lockargs()
155 * nlmclnt_proc - Perform a single client-side lock request
157 * @cmd: fcntl-style file lock operation to perform
158 * @fl: address of arguments for the lock operation
165 int status; in nlmclnt_proc() local
166 const struct nlmclnt_operations *nlmclnt_ops = host->h_nlmclnt_ops; in nlmclnt_proc()
170 return -ENOMEM; in nlmclnt_proc()
172 if (nlmclnt_ops && nlmclnt_ops->nlmclnt_alloc_call) in nlmclnt_proc()
173 nlmclnt_ops->nlmclnt_alloc_call(data); in nlmclnt_proc()
176 if (!fl->fl_u.nfs_fl.owner) { in nlmclnt_proc()
179 return -ENOMEM; in nlmclnt_proc()
183 call->a_callback_data = data; in nlmclnt_proc()
186 if (fl->c.flc_type != F_UNLCK) { in nlmclnt_proc()
187 call->a_args.block = IS_SETLKW(cmd) ? 1 : 0; in nlmclnt_proc()
188 status = nlmclnt_lock(call, fl); in nlmclnt_proc()
190 status = nlmclnt_unlock(call, fl); in nlmclnt_proc()
192 status = nlmclnt_test(call, fl); in nlmclnt_proc()
194 status = -EINVAL; in nlmclnt_proc()
195 fl->fl_ops->fl_release_private(fl); in nlmclnt_proc()
196 fl->fl_ops = NULL; in nlmclnt_proc()
198 dprintk("lockd: clnt proc returns %d\n", status); in nlmclnt_proc()
199 return status; in nlmclnt_proc()
213 refcount_set(&call->a_count, 1); in nlm_alloc_call()
214 locks_init_lock(&call->a_args.lock.fl); in nlm_alloc_call()
215 locks_init_lock(&call->a_res.lock.fl); in nlm_alloc_call()
216 call->a_host = nlm_get_host(host); in nlm_alloc_call()
229 const struct nlmclnt_operations *nlmclnt_ops = call->a_host->h_nlmclnt_ops; in nlmclnt_release_call()
231 if (!refcount_dec_and_test(&call->a_count)) in nlmclnt_release_call()
233 if (nlmclnt_ops && nlmclnt_ops->nlmclnt_release_call) in nlmclnt_release_call()
234 nlmclnt_ops->nlmclnt_release_call(call->a_callback_data); in nlmclnt_release_call()
235 nlmclnt_release_host(call->a_host); in nlmclnt_release_call()
248 int status = -EINTR; in nlm_wait_on_grace() local
255 status = 0; in nlm_wait_on_grace()
258 return status; in nlm_wait_on_grace()
267 struct nlm_host *host = req->a_host; in nlmclnt_call()
269 struct nlm_args *argp = &req->a_args; in nlmclnt_call()
270 struct nlm_res *resp = &req->a_res; in nlmclnt_call()
276 int status; in nlmclnt_call() local
279 (int)proc, host->h_name); in nlmclnt_call()
282 if (host->h_reclaiming && !argp->reclaim) in nlmclnt_call()
287 return -ENOLCK; in nlmclnt_call()
288 msg.rpc_proc = &clnt->cl_procinfo[proc]; in nlmclnt_call()
291 if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) { in nlmclnt_call()
292 dprintk("lockd: rpc_call returned error %d\n", -status); in nlmclnt_call()
293 switch (status) { in nlmclnt_call()
294 case -EPROTONOSUPPORT: in nlmclnt_call()
295 status = -EINVAL; in nlmclnt_call()
297 case -ECONNREFUSED: in nlmclnt_call()
298 case -ETIMEDOUT: in nlmclnt_call()
299 case -ENOTCONN: in nlmclnt_call()
301 status = -EAGAIN; in nlmclnt_call()
303 case -ERESTARTSYS: in nlmclnt_call()
304 return signalled () ? -EINTR : status; in nlmclnt_call()
310 if (resp->status == nlm_lck_denied_grace_period) { in nlmclnt_call()
312 if (argp->reclaim) { in nlmclnt_call()
315 return -ENOLCK; in nlmclnt_call()
318 if (!argp->reclaim) { in nlmclnt_call()
320 wake_up_all(&host->h_gracewait); in nlmclnt_call()
322 dprintk("lockd: server returns status %d\n", in nlmclnt_call()
323 ntohl(resp->status)); in nlmclnt_call()
334 status = nlm_wait_on_grace(&host->h_gracewait); in nlmclnt_call()
335 } while (status == 0); in nlmclnt_call()
337 return status; in nlmclnt_call()
345 struct nlm_host *host = req->a_host; in __nlm_async_call()
355 (int)proc, host->h_name); in __nlm_async_call()
361 msg->rpc_proc = &clnt->cl_procinfo[proc]; in __nlm_async_call()
367 tk_ops->rpc_release(req); in __nlm_async_call()
368 return ERR_PTR(-ENOLCK); in __nlm_async_call()
388 .rpc_argp = &req->a_args, in nlm_async_call()
389 .rpc_resp = &req->a_res, in nlm_async_call()
397 .rpc_argp = &req->a_res, in nlm_async_reply()
407 * completion in order to be able to correctly track the lock
413 .rpc_argp = &req->a_args, in nlmclnt_async_call()
414 .rpc_resp = &req->a_res, in nlmclnt_async_call()
429 * TEST for the presence of a conflicting lock
434 int status; in nlmclnt_test() local
436 status = nlmclnt_call(nfs_file_cred(fl->c.flc_file), req, in nlmclnt_test()
438 if (status < 0) in nlmclnt_test()
441 switch (req->a_res.status) { in nlmclnt_test()
443 fl->c.flc_type = F_UNLCK; in nlmclnt_test()
447 * Report the conflicting lock back to the application. in nlmclnt_test()
449 fl->fl_start = req->a_res.lock.fl.fl_start; in nlmclnt_test()
450 fl->fl_end = req->a_res.lock.fl.fl_end; in nlmclnt_test()
451 fl->c.flc_type = req->a_res.lock.fl.c.flc_type; in nlmclnt_test()
452 fl->c.flc_pid = -req->a_res.lock.fl.c.flc_pid; in nlmclnt_test()
455 status = nlm_stat_to_errno(req->a_res.status); in nlmclnt_test()
458 trace_nlmclnt_test(&req->a_args.lock, in nlmclnt_test()
459 (const struct sockaddr *)&req->a_host->h_addr, in nlmclnt_test()
460 req->a_host->h_addrlen, req->a_res.status); in nlmclnt_test()
462 return status; in nlmclnt_test()
467 spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock); in nlmclnt_locks_copy_lock()
468 new->fl_u.nfs_fl.state = fl->fl_u.nfs_fl.state; in nlmclnt_locks_copy_lock()
469 new->fl_u.nfs_fl.owner = nlmclnt_get_lockowner(fl->fl_u.nfs_fl.owner); in nlmclnt_locks_copy_lock()
470 list_add_tail(&new->fl_u.nfs_fl.list, &fl->fl_u.nfs_fl.owner->host->h_granted); in nlmclnt_locks_copy_lock()
471 spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock); in nlmclnt_locks_copy_lock()
476 spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock); in nlmclnt_locks_release_private()
477 list_del(&fl->fl_u.nfs_fl.list); in nlmclnt_locks_release_private()
478 spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock); in nlmclnt_locks_release_private()
479 nlmclnt_put_lockowner(fl->fl_u.nfs_fl.owner); in nlmclnt_locks_release_private()
489 fl->fl_u.nfs_fl.state = 0; in nlmclnt_locks_init_private()
490 fl->fl_u.nfs_fl.owner = nlmclnt_find_lockowner(host, in nlmclnt_locks_init_private()
491 fl->c.flc_owner); in nlmclnt_locks_init_private()
492 INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list); in nlmclnt_locks_init_private()
493 fl->fl_ops = &nlmclnt_lock_ops; in nlmclnt_locks_init_private()
498 return locks_lock_file_wait(fl->c.flc_file, fl); in do_vfs_lock()
502 * LOCK: Try to create a lock
506 * When given a blocking lock request in a sync RPC call, the HPUX lockd
508 * the lock could be granted. This way, our local process could hang
511 * Solution A: Implement busy-waiting
515 * re-implementing lockd for a third time in two months. The async
524 const struct cred *cred = nfs_file_cred(fl->c.flc_file); in nlmclnt_lock()
525 struct nlm_host *host = req->a_host; in nlmclnt_lock()
526 struct nlm_res *resp = &req->a_res; in nlmclnt_lock()
528 unsigned char flags = fl->c.flc_flags; in nlmclnt_lock()
531 int status = -ENOLCK; in nlmclnt_lock() local
535 req->a_args.state = nsm_local_state; in nlmclnt_lock()
537 fl->c.flc_flags |= FL_ACCESS; in nlmclnt_lock()
538 status = do_vfs_lock(fl); in nlmclnt_lock()
539 fl->c.flc_flags = flags; in nlmclnt_lock()
540 if (status < 0) in nlmclnt_lock()
546 * Initialise resp->status to a valid non-zero value, in nlmclnt_lock()
549 resp->status = nlm_lck_blocked; in nlmclnt_lock()
552 * A GRANTED callback can come at any time -- even before the reply in nlmclnt_lock()
553 * to the LOCK request arrives, so we queue the wait before in nlmclnt_lock()
554 * requesting the lock. in nlmclnt_lock()
559 fl->fl_u.nfs_fl.state = host->h_state; in nlmclnt_lock()
560 status = nlmclnt_call(cred, req, NLMPROC_LOCK); in nlmclnt_lock()
561 if (status < 0) in nlmclnt_lock()
564 if (resp->status == nlm_lck_denied_grace_period) in nlmclnt_lock()
566 if (resp->status != nlm_lck_blocked) in nlmclnt_lock()
568 /* Wait on an NLM blocking lock */ in nlmclnt_lock()
569 status = nlmclnt_wait(&block, req, NLMCLNT_POLL_TIMEOUT); in nlmclnt_lock()
570 if (status < 0) in nlmclnt_lock()
576 if (resp->status == nlm_lck_blocked) in nlmclnt_lock()
577 resp->status = b_status; in nlmclnt_lock()
579 /* if we were interrupted while blocking, then cancel the lock request in nlmclnt_lock()
582 if (resp->status == nlm_lck_blocked) { in nlmclnt_lock()
583 if (!req->a_args.block) in nlmclnt_lock()
585 if (nlmclnt_cancel(host, req->a_args.block, fl) == 0) in nlmclnt_lock()
589 if (resp->status == nlm_granted) { in nlmclnt_lock()
590 down_read(&host->h_rwsem); in nlmclnt_lock()
592 if (fl->fl_u.nfs_fl.state != host->h_state) { in nlmclnt_lock()
593 up_read(&host->h_rwsem); in nlmclnt_lock()
596 /* Ensure the resulting lock will get added to granted list */ in nlmclnt_lock()
597 fl->c.flc_flags |= FL_SLEEP; in nlmclnt_lock()
599 printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __func__); in nlmclnt_lock()
600 up_read(&host->h_rwsem); in nlmclnt_lock()
601 fl->c.flc_flags = flags; in nlmclnt_lock()
602 status = 0; in nlmclnt_lock()
604 if (status < 0) in nlmclnt_lock()
611 if (resp->status == nlm_lck_denied && (flags & FL_SLEEP)) in nlmclnt_lock()
612 status = -ENOLCK; in nlmclnt_lock()
614 status = nlm_stat_to_errno(resp->status); in nlmclnt_lock()
616 trace_nlmclnt_lock(&req->a_args.lock, in nlmclnt_lock()
617 (const struct sockaddr *)&req->a_host->h_addr, in nlmclnt_lock()
618 req->a_host->h_addrlen, req->a_res.status); in nlmclnt_lock()
620 return status; in nlmclnt_lock()
622 /* Fatal error: ensure that we remove the lock altogether */ in nlmclnt_lock()
623 trace_nlmclnt_lock(&req->a_args.lock, in nlmclnt_lock()
624 (const struct sockaddr *)&req->a_host->h_addr, in nlmclnt_lock()
625 req->a_host->h_addrlen, req->a_res.status); in nlmclnt_lock()
626 dprintk("lockd: lock attempt ended in fatal error.\n" in nlmclnt_lock()
628 type = fl->c.flc_type; in nlmclnt_lock()
629 fl->c.flc_type = F_UNLCK; in nlmclnt_lock()
630 down_read(&host->h_rwsem); in nlmclnt_lock()
632 up_read(&host->h_rwsem); in nlmclnt_lock()
633 fl->c.flc_type = type; in nlmclnt_lock()
634 fl->c.flc_flags = flags; in nlmclnt_lock()
636 return status; in nlmclnt_lock()
640 * RECLAIM: Try to reclaim a lock
646 int status; in nlmclnt_reclaim() local
649 locks_init_lock(&req->a_args.lock.fl); in nlmclnt_reclaim()
650 locks_init_lock(&req->a_res.lock.fl); in nlmclnt_reclaim()
651 req->a_host = host; in nlmclnt_reclaim()
655 req->a_args.reclaim = 1; in nlmclnt_reclaim()
657 status = nlmclnt_call(nfs_file_cred(fl->c.flc_file), req, in nlmclnt_reclaim()
659 if (status >= 0 && req->a_res.status == nlm_granted) in nlmclnt_reclaim()
662 printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d " in nlmclnt_reclaim()
663 "(errno %d, status %d)\n", in nlmclnt_reclaim()
664 fl->c.flc_pid, in nlmclnt_reclaim()
665 status, ntohl(req->a_res.status)); in nlmclnt_reclaim()
679 return -ENOLCK; in nlmclnt_reclaim()
683 * UNLOCK: remove an existing lock
688 struct nlm_host *host = req->a_host; in nlmclnt_unlock()
689 struct nlm_res *resp = &req->a_res; in nlmclnt_unlock()
690 int status; in nlmclnt_unlock() local
691 unsigned char flags = fl->c.flc_flags; in nlmclnt_unlock()
698 fl->c.flc_flags |= FL_EXISTS; in nlmclnt_unlock()
699 down_read(&host->h_rwsem); in nlmclnt_unlock()
700 status = do_vfs_lock(fl); in nlmclnt_unlock()
701 up_read(&host->h_rwsem); in nlmclnt_unlock()
702 fl->c.flc_flags = flags; in nlmclnt_unlock()
703 if (status == -ENOENT) { in nlmclnt_unlock()
704 status = 0; in nlmclnt_unlock()
708 refcount_inc(&req->a_count); in nlmclnt_unlock()
709 status = nlmclnt_async_call(nfs_file_cred(fl->c.flc_file), req, in nlmclnt_unlock()
711 if (status < 0) in nlmclnt_unlock()
714 if (resp->status == nlm_granted) in nlmclnt_unlock()
717 if (resp->status != nlm_lck_denied_nolocks) in nlmclnt_unlock()
718 printk("lockd: unexpected unlock status: %d\n", in nlmclnt_unlock()
719 ntohl(resp->status)); in nlmclnt_unlock()
721 status = -ENOLCK; in nlmclnt_unlock()
723 trace_nlmclnt_unlock(&req->a_args.lock, in nlmclnt_unlock()
724 (const struct sockaddr *)&req->a_host->h_addr, in nlmclnt_unlock()
725 req->a_host->h_addrlen, req->a_res.status); in nlmclnt_unlock()
727 return status; in nlmclnt_unlock()
733 const struct nlmclnt_operations *nlmclnt_ops = req->a_host->h_nlmclnt_ops; in nlmclnt_unlock_prepare()
736 if (nlmclnt_ops && nlmclnt_ops->nlmclnt_unlock_prepare) in nlmclnt_unlock_prepare()
737 defer_call = nlmclnt_ops->nlmclnt_unlock_prepare(task, req->a_callback_data); in nlmclnt_unlock_prepare()
746 u32 status = ntohl(req->a_res.status); in nlmclnt_unlock_callback() local
751 if (task->tk_status < 0) { in nlmclnt_unlock_callback()
752 dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); in nlmclnt_unlock_callback()
753 switch (task->tk_status) { in nlmclnt_unlock_callback()
754 case -EACCES: in nlmclnt_unlock_callback()
755 case -EIO: in nlmclnt_unlock_callback()
761 if (status == NLM_LCK_DENIED_GRACE_PERIOD) { in nlmclnt_unlock_callback()
765 if (status != NLM_LCK_GRANTED) in nlmclnt_unlock_callback()
766 printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status); in nlmclnt_unlock_callback()
770 nlm_rebind_host(req->a_host); in nlmclnt_unlock_callback()
782 * Cancel a blocked lock request.
784 * process that has been Ctrl-C'ed.
789 int status; in nlmclnt_cancel() local
791 dprintk("lockd: blocking lock attempt was interrupted by a signal.\n" in nlmclnt_cancel()
792 " Attempting to cancel lock.\n"); in nlmclnt_cancel()
796 return -ENOMEM; in nlmclnt_cancel()
797 req->a_flags = RPC_TASK_ASYNC; in nlmclnt_cancel()
800 req->a_args.block = block; in nlmclnt_cancel()
802 refcount_inc(&req->a_count); in nlmclnt_cancel()
803 status = nlmclnt_async_call(nfs_file_cred(fl->c.flc_file), req, in nlmclnt_cancel()
805 if (status == 0 && req->a_res.status == nlm_lck_denied) in nlmclnt_cancel()
806 status = -ENOLCK; in nlmclnt_cancel()
808 return status; in nlmclnt_cancel()
814 u32 status = ntohl(req->a_res.status); in nlmclnt_cancel_callback() local
819 if (task->tk_status < 0) { in nlmclnt_cancel_callback()
821 task->tk_status); in nlmclnt_cancel_callback()
825 switch (status) { in nlmclnt_cancel_callback()
836 status); in nlmclnt_cancel_callback()
844 if (req->a_retries++ >= NLMCLNT_MAX_RETRIES) in nlmclnt_cancel_callback()
846 nlm_rebind_host(req->a_host); in nlmclnt_cancel_callback()
857 * Convert an NLM status code to a generic kernel errno
860 nlm_stat_to_errno(__be32 status) in nlm_stat_to_errno() argument
862 switch(ntohl(status)) { in nlm_stat_to_errno()
866 return -EAGAIN; in nlm_stat_to_errno()
869 return -ENOLCK; in nlm_stat_to_errno()
871 printk(KERN_NOTICE "lockd: unexpected status NLM_BLOCKED\n"); in nlm_stat_to_errno()
872 return -ENOLCK; in nlm_stat_to_errno()
875 return -EDEADLK; in nlm_stat_to_errno()
877 return -EROFS; in nlm_stat_to_errno()
879 return -ESTALE; in nlm_stat_to_errno()
881 return -EOVERFLOW; in nlm_stat_to_errno()
883 return -ENOLCK; in nlm_stat_to_errno()
886 printk(KERN_NOTICE "lockd: unexpected server status %d\n", in nlm_stat_to_errno()
887 ntohl(status)); in nlm_stat_to_errno()
888 return -ENOLCK; in nlm_stat_to_errno()