Home | History | Annotate | Download | only in fs
      1     0   stevel /*
      2     0   stevel  * CDDL HEADER START
      3     0   stevel  *
      4     0   stevel  * The contents of this file are subject to the terms of the
      5  5331      amw  * Common Development and Distribution License (the "License").
      6  5331      amw  * You may not use this file except in compliance with the License.
      7     0   stevel  *
      8     0   stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0   stevel  * or http://www.opensolaris.org/os/licensing.
     10     0   stevel  * See the License for the specific language governing permissions
     11     0   stevel  * and limitations under the License.
     12     0   stevel  *
     13     0   stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0   stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0   stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0   stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0   stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0   stevel  *
     19     0   stevel  * CDDL HEADER END
     20     0   stevel  */
     21     0   stevel /*
     22  7961  Natalie  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  5331      amw  * Use is subject to license terms.
     24     0   stevel  */
     25     0   stevel 
     26     0   stevel /*
     27     0   stevel  * Utility routines and top-level conflict detection code for NBMAND
     28     0   stevel  * locks.
     29     0   stevel  */
     30     0   stevel 
     31     0   stevel #include <sys/nbmlock.h>
     32     0   stevel #include <sys/rwlock.h>
     33     0   stevel #include <sys/vnode.h>
     34     0   stevel #include <sys/cmn_err.h>
     35     0   stevel #include <sys/types.h>
     36     0   stevel #include <sys/fcntl.h>
     37     0   stevel #include <sys/vfs.h>
     38     0   stevel 
     39     0   stevel /*
     40     0   stevel  * Enter the critical region for synchronizing I/O requests with lock/share
     41     0   stevel  * requests.  "mode" specifies whether the caller intends to update
     42     0   stevel  * lock/share state (as opposed to just query it).
     43     0   stevel  */
     44     0   stevel 
     45     0   stevel void
     46     0   stevel nbl_start_crit(vnode_t *vp, krw_t mode)
     47     0   stevel {
     48     0   stevel 	rw_enter(&vp->v_nbllock, mode);
     49     0   stevel }
     50     0   stevel 
     51     0   stevel /*
     52     0   stevel  * Leave the critical region.
     53     0   stevel  */
     54     0   stevel 
     55     0   stevel void
     56     0   stevel nbl_end_crit(vnode_t *vp)
     57     0   stevel {
     58     0   stevel 	rw_exit(&vp->v_nbllock);
     59     0   stevel }
     60     0   stevel 
     61     0   stevel /*
     62     0   stevel  * Return non-zero if some thread is in the critical region.
     63     0   stevel  * Note that this is appropriate for use in ASSERT()s only.
     64     0   stevel  */
     65     0   stevel 
     66     0   stevel int
     67     0   stevel nbl_in_crit(vnode_t *vp)
     68     0   stevel {
     69     0   stevel 	return (RW_LOCK_HELD(&vp->v_nbllock));
     70     0   stevel }
     71     0   stevel 
     72     0   stevel /*
     73     0   stevel  * Returns non-zero if we need to look further for an NBMAND lock or
     74     0   stevel  * share conflict.
     75     0   stevel  */
     76     0   stevel int
     77     0   stevel nbl_need_check(vnode_t *vp)
     78     0   stevel {
     79     0   stevel 	/*
     80     0   stevel 	 * Currently we only check if NBMAND locks/shares are allowed on
     81     0   stevel 	 * the filesystem.  An option for the future would be to have a
     82     0   stevel 	 * flag on the vnode, though the locking for that can get tricky.
     83     0   stevel 	 */
     84     0   stevel 	return ((vp->v_vfsp) && (vp->v_vfsp->vfs_flag & VFS_NBMAND));
     85     0   stevel }
     86     0   stevel 
     87     0   stevel /*
     88     0   stevel  * Top-level conflict detection routine.  The arguments describe the
     89     0   stevel  * operation that is being attempted.  If the operation conflicts with an
     90     0   stevel  * existing lock or share reservation, a non-zero value is returned.  If
     91     0   stevel  * the operation is allowed, zero is returned.  Note that there is an
     92     0   stevel  * implicit argument, which is the process ID of the requester.
     93     0   stevel  *
     94     0   stevel  * svmand indicates that the file has System V mandatory locking enabled,
     95     0   stevel  * so we should look at all record locks, not just NBMAND record locks.
     96     0   stevel  * (This is to avoid a deadlock between a process making an I/O request and
     97     0   stevel  * a process trying to release a lock.  Instead of letting the first
     98     0   stevel  * process block in the filesystem code, we flag a conflict here.)
     99     0   stevel  */
    100     0   stevel 
    101     0   stevel int
    102     0   stevel nbl_conflict(vnode_t *vp,
    103     0   stevel 		nbl_op_t op,		/* attempted operation */
    104     0   stevel 		u_offset_t offset,	/* ignore if not I/O */
    105     0   stevel 		ssize_t length,		/* ignore if not I/O */
    106  5331      amw 		int svmand,		/* System V mandatory locking */
    107  5331      amw 		caller_context_t *ct)	/* caller context */
    108     0   stevel {
    109     0   stevel 	ASSERT(nbl_in_crit(vp));
    110     0   stevel 	ASSERT(op == NBL_READ || op == NBL_WRITE || op == NBL_RENAME ||
    111     0   stevel 	    op == NBL_REMOVE || op == NBL_READWRITE);
    112     0   stevel 
    113  5331      amw 	if (nbl_share_conflict(vp, op, ct)) {
    114     0   stevel 		return (1);
    115     0   stevel 	}
    116     0   stevel 
    117     0   stevel 	/*
    118     0   stevel 	 * If this is not an I/O request, there's no need to check against
    119     0   stevel 	 * the locks on the file.
    120     0   stevel 	 */
    121     0   stevel 	if (op == NBL_REMOVE || op == NBL_RENAME)
    122     0   stevel 		return (0);
    123     0   stevel 
    124  5331      amw 	return (nbl_lock_conflict(vp, op, offset, length, svmand, ct));
    125     0   stevel }
    126     0   stevel 
    127     0   stevel /*
    128     0   stevel  * Determine if the given file has mode bits for System V mandatory locks.
    129     0   stevel  * If there was an error, the errno value is returned.  Otherwise, zero is
    130     0   stevel  * returned and *svp is set appropriately (non-zero for mandatory locks,
    131     0   stevel  * zero for no mandatory locks).
    132     0   stevel  */
    133     0   stevel 
    134     0   stevel int
    135     0   stevel nbl_svmand(vnode_t *vp, cred_t *cr, int *svp)
    136     0   stevel {
    137     0   stevel 	struct vattr va;
    138     0   stevel 	int error;
    139     0   stevel 
    140     0   stevel 	va.va_mask = AT_MODE;
    141  5331      amw 	error = VOP_GETATTR(vp, &va, 0, cr, NULL);
    142     0   stevel 	if (error != 0)
    143     0   stevel 		return (error);
    144     0   stevel 
    145     0   stevel 	*svp = MANDLOCK(vp, va.va_mode);
    146     0   stevel 	return (0);
    147     0   stevel }
    148