Print this page
3882 remove xmod & friends
   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          */