1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /* ONC_PLUS EXTRACT START */
22
23 /*
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
32
33 #include <sys/flock_impl.h>
34 #include <sys/vfs.h>
35 #include <sys/t_lock.h> /* for <sys/callb.h> */
36 #include <sys/callb.h>
37 #include <sys/clconf.h>
38 #include <sys/cladm.h>
39 #include <sys/nbmlock.h>
40 #include <sys/cred.h>
41 #include <sys/policy.h>
592 /*
593 * Initialize an flk_callback_t and then link it into the head of an
594 * existing list (which may be NULL).
595 */
596
597 void
598 flk_add_callback(flk_callback_t *newcb,
599 callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *),
600 void *cbdata, flk_callback_t *cblist)
601 {
602 flk_init_callback(newcb, cb_fcn, cbdata);
603
604 if (cblist == NULL)
605 return;
606
607 newcb->cb_prev = cblist->cb_prev;
608 newcb->cb_next = cblist;
609 cblist->cb_prev->cb_next = newcb;
610 cblist->cb_prev = newcb;
611 }
612 /* ONC_PLUS EXTRACT END */
613
614 /*
615 * Initialize the flk_edge_cache data structure and create the
616 * nlm_reg_status array.
617 */
618
619 void
620 flk_init(void)
621 {
622 uint_t i;
623
624 flk_edge_cache = kmem_cache_create("flk_edges",
625 sizeof (struct edge), 0, NULL, NULL, NULL, NULL, NULL, 0);
626 if (flk_edge_cache == NULL) {
627 cmn_err(CE_PANIC, "Couldn't create flk_edge_cache\n");
628 }
629 /*
630 * Create the NLM registry object.
631 */
632
967
968 if (NOT_BLOCKED(request)) {
969 /*
970 * request not dependent on any other locks
971 * so execute this request
972 */
973 return (flk_execute_request(request));
974 } else {
975 /*
976 * check for deadlock
977 */
978 if (flk_check_deadlock(request))
979 return (EDEADLK);
980 /*
981 * this thread has to sleep
982 */
983 return (flk_wait_execute_request(request));
984 }
985 }
986
987 /* ONC_PLUS EXTRACT START */
988 /*
989 * The actual execution of the request in the simple case is only to
990 * insert the 'request' in the list of active locks if it is not an
991 * UNLOCK.
992 * We have to consider the existing active locks' relation to
993 * this 'request' if they are owned by same process. flk_relation() does
994 * this job and sees to that the dependency graph information is maintained
995 * properly.
996 */
997
998 int
999 flk_execute_request(lock_descriptor_t *request)
1000 {
1001 graph_t *gp = request->l_graph;
1002 vnode_t *vp = request->l_vnode;
1003 lock_descriptor_t *lock, *lock1;
1004 int done_searching = 0;
1005
1006 CHECK_SLEEPING_LOCKS(gp);
1007 CHECK_ACTIVE_LOCKS(gp);
1026 return (0);
1027 }
1028
1029 do {
1030 lock1 = lock->l_next;
1031 if (SAME_OWNER(request, lock)) {
1032 done_searching = flk_relation(lock, request);
1033 }
1034 lock = lock1;
1035 } while (lock->l_vnode == vp && !done_searching);
1036
1037 /*
1038 * insert in active queue
1039 */
1040
1041 if (request->l_type != F_UNLCK)
1042 flk_insert_active_lock(request);
1043
1044 return (0);
1045 }
1046 /* ONC_PLUS EXTRACT END */
1047
1048 /*
1049 * 'request' is blocked by some one therefore we put it into sleep queue.
1050 */
1051 static int
1052 flk_wait_execute_request(lock_descriptor_t *request)
1053 {
1054 graph_t *gp = request->l_graph;
1055 callb_cpr_t *cprp; /* CPR info from callback */
1056 struct flock_globals *fg;
1057 int index;
1058
1059 ASSERT(MUTEX_HELD(&gp->gp_mutex));
1060 ASSERT(IS_WILLING_TO_SLEEP(request));
1061
1062 flk_insert_sleeping_lock(request);
1063
1064 if (IS_LOCKMGR(request)) {
1065 index = HASH_INDEX(request->l_vnode);
1066 fg = flk_get_globals();
2226 /* get NLM id from sysid */
2227 lock_nlmid = GETNLMID(lock->l_flock.l_sysid);
2228
2229 /*
2230 * If NLM server request _and_ nlmid of lock matches
2231 * nlmid of argument, then we've found a remote lock.
2232 */
2233 if (IS_LOCKMGR(lock) && nlmid == lock_nlmid) {
2234 result = 1;
2235 goto done;
2236 }
2237 lock = lock->l_next;
2238 }
2239 }
2240
2241 done:
2242 mutex_exit(&gp->gp_mutex);
2243 return (result);
2244 }
2245
2246 /* ONC_PLUS EXTRACT START */
2247 /*
2248 * Determine whether there are any locks for the given vnode with a remote
2249 * sysid. Returns zero if not, non-zero if there are.
2250 *
2251 * Note that the return value from this function is potentially invalid
2252 * once it has been returned. The caller is responsible for providing its
2253 * own synchronization mechanism to ensure that the return value is useful
2254 * (e.g., see nfs_lockcompletion()).
2255 */
2256 int
2257 flk_has_remote_locks(vnode_t *vp)
2258 {
2259 lock_descriptor_t *lock;
2260 int result = 0;
2261 graph_t *gp;
2262
2263 gp = flk_get_lock_graph(vp, FLK_USE_GRAPH);
2264 if (gp == NULL) {
2265 return (0);
2266 }
2597 pid == IGN_PID) &&
2598 lock->l_flock.l_sysid == sysid) {
2599 flk_delete_active_lock(lock, 0);
2600 STACK_PUSH(link_stack, lock, l_stack);
2601 }
2602 lock = nlock;
2603 } while (lock->l_vnode == vp);
2604 }
2605
2606 while ((lock = STACK_TOP(link_stack)) != NULL) {
2607 STACK_POP(link_stack, l_stack);
2608 flk_wakeup(lock, 1);
2609 flk_free_lock(lock);
2610 }
2611
2612 CHECK_SLEEPING_LOCKS(gp);
2613 CHECK_ACTIVE_LOCKS(gp);
2614 CHECK_OWNER_LOCKS(gp, pid, sysid, vp);
2615 mutex_exit(&gp->gp_mutex);
2616 }
2617 /* ONC_PLUS EXTRACT END */
2618
2619
2620 /*
2621 * Called from 'fs' read and write routines for files that have mandatory
2622 * locking enabled.
2623 */
2624
2625 int
2626 chklock(
2627 struct vnode *vp,
2628 int iomode,
2629 u_offset_t offset,
2630 ssize_t len,
2631 int fmode,
2632 caller_context_t *ct)
2633 {
2634 register int i;
2635 struct flock64 bf;
2636 int error = 0;
2637
2638 bf.l_type = (iomode & FWRITE) ? F_WRLCK : F_RDLCK;
2639 bf.l_whence = 0;
2640 bf.l_start = offset;
2641 bf.l_len = len;
2642 if (ct == NULL) {
2643 bf.l_pid = curproc->p_pid;
2644 bf.l_sysid = 0;
2645 } else {
2646 bf.l_pid = ct->cc_pid;
2647 bf.l_sysid = ct->cc_sysid;
2648 }
2649 i = (fmode & (FNDELAY|FNONBLOCK)) ? INOFLCK : INOFLCK|SLPFLCK;
2650 if ((i = reclock(vp, &bf, i, 0, offset, NULL)) != 0 ||
2651 bf.l_type != F_UNLCK)
2652 error = i ? i : EAGAIN;
2653 return (error);
2654 }
2655
2656 /* ONC_PLUS EXTRACT START */
2657 /*
2658 * convoff - converts the given data (start, whence) to the
2659 * given whence.
2660 */
2661 int
2662 convoff(vp, lckdat, whence, offset)
2663 struct vnode *vp;
2664 struct flock64 *lckdat;
2665 int whence;
2666 offset_t offset;
2667 {
2668 int error;
2669 struct vattr vattr;
2670
2671 if ((lckdat->l_whence == 2) || (whence == 2)) {
2672 vattr.va_mask = AT_SIZE;
2673 if (error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL))
2674 return (error);
2675 }
2676
2689
2690 if (lckdat->l_start < 0)
2691 return (EINVAL);
2692
2693 switch (whence) {
2694 case 1:
2695 lckdat->l_start -= offset;
2696 break;
2697 case 2:
2698 lckdat->l_start -= vattr.va_size;
2699 /* FALLTHRU */
2700 case 0:
2701 break;
2702 default:
2703 return (EINVAL);
2704 }
2705
2706 lckdat->l_whence = (short)whence;
2707 return (0);
2708 }
2709 /* ONC_PLUS EXTRACT END */
2710
2711
2712 /* proc_graph function definitions */
2713
2714 /*
2715 * Function checks for deadlock due to the new 'lock'. If deadlock found
2716 * edges of this lock are freed and returned.
2717 */
2718
2719 static int
2720 flk_check_deadlock(lock_descriptor_t *lock)
2721 {
2722 proc_vertex_t *start_vertex, *pvertex;
2723 proc_vertex_t *dvertex;
2724 proc_edge_t *pep, *ppep;
2725 edge_t *ep, *nep;
2726 proc_vertex_t *process_stack;
2727
2728 STACK_INIT(process_stack);
2729
3053
3054 while (pep != NULL) {
3055 if (pep->to_proc == toproc) {
3056 ASSERT(pep->refcount > 0);
3057 pep->refcount++;
3058 break;
3059 }
3060 pep = pep->next;
3061 }
3062 if (pep == NULL) {
3063 pep = flk_get_proc_edge();
3064 pep->to_proc = toproc;
3065 pep->refcount = 1;
3066 toproc->incount++;
3067 pep->next = fromproc->edge;
3068 fromproc->edge = pep;
3069 }
3070 mutex_exit(&flock_lock);
3071 }
3072
3073 /* ONC_PLUS EXTRACT START */
3074 /*
3075 * Set the control status for lock manager requests.
3076 *
3077 */
3078
3079 /*
3080 * PSARC case 1997/292
3081 *
3082 * Requires: "nlmid" must be >= 1 and <= clconf_maximum_nodeid().
3083 * Effects: Set the state of the NLM server identified by "nlmid"
3084 * in the NLM registry to state "nlm_state."
3085 * Raises exception no_such_nlm if "nlmid" doesn't identify a known
3086 * NLM server to this LLM.
3087 * Note that when this routine is called with NLM_SHUTTING_DOWN there
3088 * may be locks requests that have gotten started but not finished. In
3089 * particular, there may be blocking requests that are in the callback code
3090 * before sleeping (so they're not holding the lock for the graph). If
3091 * such a thread reacquires the graph's lock (to go to sleep) after
3092 * NLM state in the NLM registry is set to a non-up value,
3093 * it will notice the status and bail out. If the request gets
3675 if (gp == NULL) {
3676 continue;
3677 }
3678
3679 mutex_enter(&gp->gp_mutex);
3680 fg->lockmgr_status[i] = FLK_LOCKMGR_DOWN;
3681 for (lock = ACTIVE_HEAD(gp)->l_next;
3682 lock != ACTIVE_HEAD(gp);
3683 lock = nlock) {
3684 nlock = lock->l_next;
3685 if (IS_LOCKMGR(lock) && lock->l_zoneid == zoneid) {
3686 ASSERT(IS_ACTIVE(lock));
3687 flk_delete_active_lock(lock, 0);
3688 flk_wakeup(lock, 1);
3689 flk_free_lock(lock);
3690 }
3691 }
3692 mutex_exit(&gp->gp_mutex);
3693 }
3694 }
3695 /* ONC_PLUS EXTRACT END */
3696
3697
3698 /*
3699 * Wait until a lock is granted, cancelled, or interrupted.
3700 */
3701
3702 static void
3703 wait_for_lock(lock_descriptor_t *request)
3704 {
3705 graph_t *gp = request->l_graph;
3706
3707 ASSERT(MUTEX_HELD(&gp->gp_mutex));
3708
3709 while (!(IS_GRANTED(request)) && !(IS_CANCELLED(request)) &&
3710 !(IS_INTERRUPTED(request))) {
3711 if (!cv_wait_sig(&request->l_cv, &gp->gp_mutex)) {
3712 flk_set_state(request, FLK_INTERRUPTED_STATE);
3713 request->l_state |= INTERRUPTED_LOCK;
3714 }
3715 }
3716 }
3717
3718 /* ONC_PLUS EXTRACT START */
3719 /*
3720 * Create an flock structure from the existing lock information
3721 *
3722 * This routine is used to create flock structures for the lock manager
3723 * to use in a reclaim request. Since the lock was originated on this
3724 * host, it must be conforming to UNIX semantics, so no checking is
3725 * done to make sure it falls within the lower half of the 32-bit range.
3726 */
3727
3728 static void
3729 create_flock(lock_descriptor_t *lp, flock64_t *flp)
3730 {
3731 ASSERT(lp->l_end == MAX_U_OFFSET_T || lp->l_end <= MAXEND);
3732 ASSERT(lp->l_end >= lp->l_start);
3733
3734 flp->l_type = lp->l_type;
3735 flp->l_whence = 0;
3736 flp->l_start = lp->l_start;
3737 flp->l_len = (lp->l_end == MAX_U_OFFSET_T) ? 0 :
3738 (lp->l_end - lp->l_start + 1);
3853 if (IS_LOCKMGR(request)) {
3854 flrp->l_start = blocker->l_start;
3855 if (blocker->l_end == MAX_U_OFFSET_T)
3856 flrp->l_len = 0;
3857 else
3858 flrp->l_len = blocker->l_end - blocker->l_start + 1;
3859 } else {
3860 if (blocker->l_start > MAXEND) {
3861 flrp->l_start = MAXEND;
3862 flrp->l_len = 0;
3863 } else {
3864 flrp->l_start = blocker->l_start;
3865 if (blocker->l_end == MAX_U_OFFSET_T)
3866 flrp->l_len = 0;
3867 else
3868 flrp->l_len = blocker->l_end -
3869 blocker->l_start + 1;
3870 }
3871 }
3872 }
3873 /* ONC_PLUS EXTRACT END */
3874
3875 /*
3876 * PSARC case 1997/292
3877 */
3878 /*
3879 * This is the public routine exported by flock.h.
3880 */
3881 void
3882 cl_flk_change_nlm_state_to_unknown(int nlmid)
3883 {
3884 /*
3885 * Check to see if node is booted as a cluster. If not, return.
3886 */
3887 if ((cluster_bootflags & CLUSTER_BOOTED) == 0) {
3888 return;
3889 }
3890
3891 /*
3892 * See comment in cl_flk_set_nlm_status().
3893 */
|
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32 #include <sys/flock_impl.h>
33 #include <sys/vfs.h>
34 #include <sys/t_lock.h> /* for <sys/callb.h> */
35 #include <sys/callb.h>
36 #include <sys/clconf.h>
37 #include <sys/cladm.h>
38 #include <sys/nbmlock.h>
39 #include <sys/cred.h>
40 #include <sys/policy.h>
591 /*
592 * Initialize an flk_callback_t and then link it into the head of an
593 * existing list (which may be NULL).
594 */
595
596 void
597 flk_add_callback(flk_callback_t *newcb,
598 callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *),
599 void *cbdata, flk_callback_t *cblist)
600 {
601 flk_init_callback(newcb, cb_fcn, cbdata);
602
603 if (cblist == NULL)
604 return;
605
606 newcb->cb_prev = cblist->cb_prev;
607 newcb->cb_next = cblist;
608 cblist->cb_prev->cb_next = newcb;
609 cblist->cb_prev = newcb;
610 }
611
612 /*
613 * Initialize the flk_edge_cache data structure and create the
614 * nlm_reg_status array.
615 */
616
617 void
618 flk_init(void)
619 {
620 uint_t i;
621
622 flk_edge_cache = kmem_cache_create("flk_edges",
623 sizeof (struct edge), 0, NULL, NULL, NULL, NULL, NULL, 0);
624 if (flk_edge_cache == NULL) {
625 cmn_err(CE_PANIC, "Couldn't create flk_edge_cache\n");
626 }
627 /*
628 * Create the NLM registry object.
629 */
630
965
966 if (NOT_BLOCKED(request)) {
967 /*
968 * request not dependent on any other locks
969 * so execute this request
970 */
971 return (flk_execute_request(request));
972 } else {
973 /*
974 * check for deadlock
975 */
976 if (flk_check_deadlock(request))
977 return (EDEADLK);
978 /*
979 * this thread has to sleep
980 */
981 return (flk_wait_execute_request(request));
982 }
983 }
984
985 /*
986 * The actual execution of the request in the simple case is only to
987 * insert the 'request' in the list of active locks if it is not an
988 * UNLOCK.
989 * We have to consider the existing active locks' relation to
990 * this 'request' if they are owned by same process. flk_relation() does
991 * this job and sees to that the dependency graph information is maintained
992 * properly.
993 */
994
995 int
996 flk_execute_request(lock_descriptor_t *request)
997 {
998 graph_t *gp = request->l_graph;
999 vnode_t *vp = request->l_vnode;
1000 lock_descriptor_t *lock, *lock1;
1001 int done_searching = 0;
1002
1003 CHECK_SLEEPING_LOCKS(gp);
1004 CHECK_ACTIVE_LOCKS(gp);
1023 return (0);
1024 }
1025
1026 do {
1027 lock1 = lock->l_next;
1028 if (SAME_OWNER(request, lock)) {
1029 done_searching = flk_relation(lock, request);
1030 }
1031 lock = lock1;
1032 } while (lock->l_vnode == vp && !done_searching);
1033
1034 /*
1035 * insert in active queue
1036 */
1037
1038 if (request->l_type != F_UNLCK)
1039 flk_insert_active_lock(request);
1040
1041 return (0);
1042 }
1043
1044 /*
1045 * 'request' is blocked by some one therefore we put it into sleep queue.
1046 */
1047 static int
1048 flk_wait_execute_request(lock_descriptor_t *request)
1049 {
1050 graph_t *gp = request->l_graph;
1051 callb_cpr_t *cprp; /* CPR info from callback */
1052 struct flock_globals *fg;
1053 int index;
1054
1055 ASSERT(MUTEX_HELD(&gp->gp_mutex));
1056 ASSERT(IS_WILLING_TO_SLEEP(request));
1057
1058 flk_insert_sleeping_lock(request);
1059
1060 if (IS_LOCKMGR(request)) {
1061 index = HASH_INDEX(request->l_vnode);
1062 fg = flk_get_globals();
2222 /* get NLM id from sysid */
2223 lock_nlmid = GETNLMID(lock->l_flock.l_sysid);
2224
2225 /*
2226 * If NLM server request _and_ nlmid of lock matches
2227 * nlmid of argument, then we've found a remote lock.
2228 */
2229 if (IS_LOCKMGR(lock) && nlmid == lock_nlmid) {
2230 result = 1;
2231 goto done;
2232 }
2233 lock = lock->l_next;
2234 }
2235 }
2236
2237 done:
2238 mutex_exit(&gp->gp_mutex);
2239 return (result);
2240 }
2241
2242 /*
2243 * Determine whether there are any locks for the given vnode with a remote
2244 * sysid. Returns zero if not, non-zero if there are.
2245 *
2246 * Note that the return value from this function is potentially invalid
2247 * once it has been returned. The caller is responsible for providing its
2248 * own synchronization mechanism to ensure that the return value is useful
2249 * (e.g., see nfs_lockcompletion()).
2250 */
2251 int
2252 flk_has_remote_locks(vnode_t *vp)
2253 {
2254 lock_descriptor_t *lock;
2255 int result = 0;
2256 graph_t *gp;
2257
2258 gp = flk_get_lock_graph(vp, FLK_USE_GRAPH);
2259 if (gp == NULL) {
2260 return (0);
2261 }
2592 pid == IGN_PID) &&
2593 lock->l_flock.l_sysid == sysid) {
2594 flk_delete_active_lock(lock, 0);
2595 STACK_PUSH(link_stack, lock, l_stack);
2596 }
2597 lock = nlock;
2598 } while (lock->l_vnode == vp);
2599 }
2600
2601 while ((lock = STACK_TOP(link_stack)) != NULL) {
2602 STACK_POP(link_stack, l_stack);
2603 flk_wakeup(lock, 1);
2604 flk_free_lock(lock);
2605 }
2606
2607 CHECK_SLEEPING_LOCKS(gp);
2608 CHECK_ACTIVE_LOCKS(gp);
2609 CHECK_OWNER_LOCKS(gp, pid, sysid, vp);
2610 mutex_exit(&gp->gp_mutex);
2611 }
2612
2613
2614 /*
2615 * Called from 'fs' read and write routines for files that have mandatory
2616 * locking enabled.
2617 */
2618
2619 int
2620 chklock(
2621 struct vnode *vp,
2622 int iomode,
2623 u_offset_t offset,
2624 ssize_t len,
2625 int fmode,
2626 caller_context_t *ct)
2627 {
2628 register int i;
2629 struct flock64 bf;
2630 int error = 0;
2631
2632 bf.l_type = (iomode & FWRITE) ? F_WRLCK : F_RDLCK;
2633 bf.l_whence = 0;
2634 bf.l_start = offset;
2635 bf.l_len = len;
2636 if (ct == NULL) {
2637 bf.l_pid = curproc->p_pid;
2638 bf.l_sysid = 0;
2639 } else {
2640 bf.l_pid = ct->cc_pid;
2641 bf.l_sysid = ct->cc_sysid;
2642 }
2643 i = (fmode & (FNDELAY|FNONBLOCK)) ? INOFLCK : INOFLCK|SLPFLCK;
2644 if ((i = reclock(vp, &bf, i, 0, offset, NULL)) != 0 ||
2645 bf.l_type != F_UNLCK)
2646 error = i ? i : EAGAIN;
2647 return (error);
2648 }
2649
2650 /*
2651 * convoff - converts the given data (start, whence) to the
2652 * given whence.
2653 */
2654 int
2655 convoff(vp, lckdat, whence, offset)
2656 struct vnode *vp;
2657 struct flock64 *lckdat;
2658 int whence;
2659 offset_t offset;
2660 {
2661 int error;
2662 struct vattr vattr;
2663
2664 if ((lckdat->l_whence == 2) || (whence == 2)) {
2665 vattr.va_mask = AT_SIZE;
2666 if (error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL))
2667 return (error);
2668 }
2669
2682
2683 if (lckdat->l_start < 0)
2684 return (EINVAL);
2685
2686 switch (whence) {
2687 case 1:
2688 lckdat->l_start -= offset;
2689 break;
2690 case 2:
2691 lckdat->l_start -= vattr.va_size;
2692 /* FALLTHRU */
2693 case 0:
2694 break;
2695 default:
2696 return (EINVAL);
2697 }
2698
2699 lckdat->l_whence = (short)whence;
2700 return (0);
2701 }
2702
2703
2704 /* proc_graph function definitions */
2705
2706 /*
2707 * Function checks for deadlock due to the new 'lock'. If deadlock found
2708 * edges of this lock are freed and returned.
2709 */
2710
2711 static int
2712 flk_check_deadlock(lock_descriptor_t *lock)
2713 {
2714 proc_vertex_t *start_vertex, *pvertex;
2715 proc_vertex_t *dvertex;
2716 proc_edge_t *pep, *ppep;
2717 edge_t *ep, *nep;
2718 proc_vertex_t *process_stack;
2719
2720 STACK_INIT(process_stack);
2721
3045
3046 while (pep != NULL) {
3047 if (pep->to_proc == toproc) {
3048 ASSERT(pep->refcount > 0);
3049 pep->refcount++;
3050 break;
3051 }
3052 pep = pep->next;
3053 }
3054 if (pep == NULL) {
3055 pep = flk_get_proc_edge();
3056 pep->to_proc = toproc;
3057 pep->refcount = 1;
3058 toproc->incount++;
3059 pep->next = fromproc->edge;
3060 fromproc->edge = pep;
3061 }
3062 mutex_exit(&flock_lock);
3063 }
3064
3065 /*
3066 * Set the control status for lock manager requests.
3067 *
3068 */
3069
3070 /*
3071 * PSARC case 1997/292
3072 *
3073 * Requires: "nlmid" must be >= 1 and <= clconf_maximum_nodeid().
3074 * Effects: Set the state of the NLM server identified by "nlmid"
3075 * in the NLM registry to state "nlm_state."
3076 * Raises exception no_such_nlm if "nlmid" doesn't identify a known
3077 * NLM server to this LLM.
3078 * Note that when this routine is called with NLM_SHUTTING_DOWN there
3079 * may be locks requests that have gotten started but not finished. In
3080 * particular, there may be blocking requests that are in the callback code
3081 * before sleeping (so they're not holding the lock for the graph). If
3082 * such a thread reacquires the graph's lock (to go to sleep) after
3083 * NLM state in the NLM registry is set to a non-up value,
3084 * it will notice the status and bail out. If the request gets
3666 if (gp == NULL) {
3667 continue;
3668 }
3669
3670 mutex_enter(&gp->gp_mutex);
3671 fg->lockmgr_status[i] = FLK_LOCKMGR_DOWN;
3672 for (lock = ACTIVE_HEAD(gp)->l_next;
3673 lock != ACTIVE_HEAD(gp);
3674 lock = nlock) {
3675 nlock = lock->l_next;
3676 if (IS_LOCKMGR(lock) && lock->l_zoneid == zoneid) {
3677 ASSERT(IS_ACTIVE(lock));
3678 flk_delete_active_lock(lock, 0);
3679 flk_wakeup(lock, 1);
3680 flk_free_lock(lock);
3681 }
3682 }
3683 mutex_exit(&gp->gp_mutex);
3684 }
3685 }
3686
3687
3688 /*
3689 * Wait until a lock is granted, cancelled, or interrupted.
3690 */
3691
3692 static void
3693 wait_for_lock(lock_descriptor_t *request)
3694 {
3695 graph_t *gp = request->l_graph;
3696
3697 ASSERT(MUTEX_HELD(&gp->gp_mutex));
3698
3699 while (!(IS_GRANTED(request)) && !(IS_CANCELLED(request)) &&
3700 !(IS_INTERRUPTED(request))) {
3701 if (!cv_wait_sig(&request->l_cv, &gp->gp_mutex)) {
3702 flk_set_state(request, FLK_INTERRUPTED_STATE);
3703 request->l_state |= INTERRUPTED_LOCK;
3704 }
3705 }
3706 }
3707
3708 /*
3709 * Create an flock structure from the existing lock information
3710 *
3711 * This routine is used to create flock structures for the lock manager
3712 * to use in a reclaim request. Since the lock was originated on this
3713 * host, it must be conforming to UNIX semantics, so no checking is
3714 * done to make sure it falls within the lower half of the 32-bit range.
3715 */
3716
3717 static void
3718 create_flock(lock_descriptor_t *lp, flock64_t *flp)
3719 {
3720 ASSERT(lp->l_end == MAX_U_OFFSET_T || lp->l_end <= MAXEND);
3721 ASSERT(lp->l_end >= lp->l_start);
3722
3723 flp->l_type = lp->l_type;
3724 flp->l_whence = 0;
3725 flp->l_start = lp->l_start;
3726 flp->l_len = (lp->l_end == MAX_U_OFFSET_T) ? 0 :
3727 (lp->l_end - lp->l_start + 1);
3842 if (IS_LOCKMGR(request)) {
3843 flrp->l_start = blocker->l_start;
3844 if (blocker->l_end == MAX_U_OFFSET_T)
3845 flrp->l_len = 0;
3846 else
3847 flrp->l_len = blocker->l_end - blocker->l_start + 1;
3848 } else {
3849 if (blocker->l_start > MAXEND) {
3850 flrp->l_start = MAXEND;
3851 flrp->l_len = 0;
3852 } else {
3853 flrp->l_start = blocker->l_start;
3854 if (blocker->l_end == MAX_U_OFFSET_T)
3855 flrp->l_len = 0;
3856 else
3857 flrp->l_len = blocker->l_end -
3858 blocker->l_start + 1;
3859 }
3860 }
3861 }
3862
3863 /*
3864 * PSARC case 1997/292
3865 */
3866 /*
3867 * This is the public routine exported by flock.h.
3868 */
3869 void
3870 cl_flk_change_nlm_state_to_unknown(int nlmid)
3871 {
3872 /*
3873 * Check to see if node is booted as a cluster. If not, return.
3874 */
3875 if ((cluster_bootflags & CLUSTER_BOOTED) == 0) {
3876 return;
3877 }
3878
3879 /*
3880 * See comment in cl_flk_set_nlm_status().
3881 */
|