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