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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 /* 31 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 32 * Copyright 2015 Joyent, Inc. 33 */ 34 35 #ifndef _SYS_FLOCK_H 36 #define _SYS_FLOCK_H 37 38 #include <sys/types.h> 39 #include <sys/fcntl.h> 40 #include <sys/vnode.h> 41 #include <sys/t_lock.h> /* for <sys/callb.h> */ 42 #include <sys/callb.h> 43 #include <sys/param.h> 44 #include <sys/zone.h> 45 #if defined(_KERNEL) 46 #include <sys/file.h> 47 #endif 48 49 #ifdef __cplusplus 50 extern "C" { 51 #endif 52 53 /* 54 * Private declarations and instrumentation for local locking. 55 */ 56 57 /* 58 * The flag passed to fs_frlock() may be ORed together with either 59 * `F_REMOTELOCK' or `F_PXFSLOCK'. Since this flag is initialized using the 60 * `f_flag' field in the `file' structure, and that field is an unsigned short, 61 * we do not use the first 2 bytes. 62 */ 63 #define F_REMOTELOCK (0x01 << 16) /* Set if NLM lock */ 64 #define F_PXFSLOCK (0x02 << 16) /* Clustering: set if PXFS lock */ 65 66 /* 67 * The command passed to reclock() is made by ORing together one or more of 68 * the following values. 69 */ 70 71 #define INOFLCK 0x01 /* Vnode is locked when reclock() is called. */ 72 #define SETFLCK 0x02 /* Set a file lock. */ 73 #define SLPFLCK 0x04 /* Wait if blocked. */ 74 #define RCMDLCK 0x08 /* F_REMOTELOCK specified */ 75 #define PCMDLCK 0x10 /* Clustering: F_PXFSLOCK specified */ 76 #define NBMLCK 0x20 /* non-blocking mandatory locking */ 77 78 /* 79 * Special pid value that can be passed to cleanlocks(). It means that 80 * cleanlocks() should flush all locks for the given sysid, not just the 81 * locks owned by a specific process. 82 */ 83 84 #define IGN_PID (-1) 85 86 /* file locking structure (connected to vnode) */ 87 88 #define l_end l_len 89 90 /* 91 * The lock manager is allowed to use unsigned offsets and lengths, though 92 * regular Unix processes are still required to use signed offsets and 93 * lengths. 94 */ 95 typedef ulong_t u_off_t; 96 97 #define MAX_U_OFF_T ((u_off_t)~0) 98 #define MAX_U_OFFSET_T ((u_offset_t)~0) 99 100 /* 101 * define MAXEND as the largest positive value the signed offset_t will hold. 102 */ 103 #define MAXEND MAXOFFSET_T 104 105 /* 106 * Definitions for accessing the l_pad area of struct flock. The 107 * descriminant of the pad_info_t union is the fcntl command used in 108 * conjunction with the flock struct. 109 */ 110 111 typedef union { 112 int pi_pad[4]; /* (original pad area) */ 113 int pi_has_rmt; /* F_HASREMOTELOCKS */ 114 } pad_info_t; 115 116 #define l_has_rmt(flockp) (((pad_info_t *)((flockp)->l_pad))->pi_has_rmt) 117 118 /* 119 * Optional callbacks for blocking lock requests. Each function is called 120 * twice. 121 * The first call is after the request is put in the "sleeping" list, but 122 * before waiting. At most one callback may return a callb_cpr_t object; 123 * the others must return NULL. If a callb_cpr_t is returned, the thread 124 * will be marked as safe to suspend while waiting for the lock. 125 * The second call is after the request wakes up. Note that the request 126 * might not have been granted at the second call (e.g., the request was 127 * signalled). 128 * New callbacks should be added to the head of the list. For the first 129 * call the list is walked in order. For the second call the list is 130 * walked backwards (in case the callbacks need to reacquire locks). 131 */ 132 133 typedef enum {FLK_BEFORE_SLEEP, FLK_AFTER_SLEEP} flk_cb_when_t; 134 135 struct flk_callback { 136 struct flk_callback *cb_next; /* circular linked list */ 137 struct flk_callback *cb_prev; 138 callb_cpr_t *(*cb_callback)(flk_cb_when_t, void *); /* fcn ptr */ 139 void *cb_data; /* ptr to callback data */ 140 }; 141 142 typedef struct flk_callback flk_callback_t; 143 144 /* 145 * This structure members are not used any more inside the kernel. 146 * The structure is used for casting some pointer assignments only. 147 */ 148 149 typedef struct filock { 150 kcondvar_t cv; 151 struct flock set; /* contains type, start, and end */ 152 struct { 153 int granted_flag; /* granted flag */ 154 struct filock *blk; /* for sleeping locks only */ 155 struct attacher *blocking_list; 156 struct attacher *my_attacher; 157 } stat; 158 struct filock *prev; 159 struct filock *next; 160 } filock_t; 161 162 #define FLP_DELAYED_FREE -1 /* special value for granted_flag */ 163 164 /* structure that contains list of locks to be granted */ 165 166 #define MAX_GRANT_LOCKS 52 167 168 typedef struct grant_lock { 169 struct filock *grant_lock_list[MAX_GRANT_LOCKS]; 170 struct grant_lock *next; 171 } grant_lock_t; 172 173 /* 174 * Provide a way to cleanly enable and disable Network Lock Manager locking 175 * requests (i.e., requests from remote clients): 176 * FLK_NLM_SHUTTING_DOWN: Forces all blocked NLM requests to bail out 177 * and return ENOLCK. 178 * FLK_NLM_DOWN: Clears all granted NLM server locks. Both status 179 * codes cause new NLM lock requests to fail immediately with ENOLCK. 180 * FLK_NLM_UP: Changes the state of all locks to UP, after a server has 181 * shutdown and is restarting on the same node. 182 */ 183 184 /* 185 * Enumerated type of the four possible states an NLM server can be in. 186 */ 187 typedef enum { 188 FLK_NLM_UP, 189 FLK_NLM_SHUTTING_DOWN, 190 FLK_NLM_DOWN, 191 FLK_NLM_UNKNOWN 192 } flk_nlm_status_t; 193 194 /* 195 * Provide a way to cleanly enable and disable lock manager locking 196 * requests (i.e., requests from remote clients). FLK_WAKEUP_SLEEPERS 197 * forces all blocked lock manager requests to bail out and return ENOLCK. 198 * FLK_LOCKMGR_DOWN clears all granted lock manager locks. Both status 199 * codes cause new lock manager requests to fail immediately with ENOLCK. 200 */ 201 202 typedef enum { 203 FLK_LOCKMGR_UP, 204 FLK_WAKEUP_SLEEPERS, 205 FLK_LOCKMGR_DOWN 206 } flk_lockmgr_status_t; 207 208 #if defined(_KERNEL) || defined(_FAKE_KERNEL) 209 210 /* 211 * The following structure is used to hold a list of locks returned 212 * by the F_ACTIVELIST or F_SLEEPINGLIST commands to fs_frlock. 213 * 214 * N.B. The lists returned by these commands are dynamically 215 * allocated and must be freed by the caller. The vnodes returned 216 * in the lists are held and must be released when the caller is done. 217 */ 218 219 typedef struct locklist { 220 struct vnode *ll_vp; 221 struct flock64 ll_flock; 222 struct locklist *ll_next; 223 } locklist_t; 224 225 #define FLK_QUERY_ACTIVE 0x1 226 #define FLK_QUERY_SLEEPING 0x2 227 228 #if defined(_KERNEL) 229 int ofdlock(file_t *, int, struct flock64 *, int, u_offset_t); 230 void ofdcleanlock(file_t *); 231 #endif 232 int reclock(struct vnode *, struct flock64 *, int, int, u_offset_t, 233 flk_callback_t *); 234 int chklock(struct vnode *, int, u_offset_t, ssize_t, int, 235 caller_context_t *); 236 int convoff(struct vnode *, struct flock64 *, int, offset_t); 237 void cleanlocks(struct vnode *, pid_t, int); 238 locklist_t *flk_get_sleeping_locks(int sysid, pid_t pid); 239 locklist_t *flk_get_active_locks(int sysid, pid_t pid); 240 locklist_t *flk_active_locks_for_vp(const struct vnode *vp); 241 locklist_t *flk_active_nbmand_locks_for_vp(const struct vnode *vp); 242 locklist_t *flk_active_nbmand_locks(pid_t pid); 243 void flk_free_locklist(locklist_t *); 244 int flk_convert_lock_data(struct vnode *, struct flock64 *, 245 u_offset_t *, u_offset_t *, offset_t); 246 int flk_check_lock_data(u_offset_t, u_offset_t, offset_t); 247 int flk_has_remote_locks(struct vnode *vp); 248 void flk_set_lockmgr_status(flk_lockmgr_status_t status); 249 int flk_sysid_has_locks(int sysid, int chklck); 250 int flk_has_remote_locks_for_sysid(vnode_t *vp, int); 251 void flk_init_callback(flk_callback_t *, 252 callb_cpr_t *(*)(flk_cb_when_t, void *), void *); 253 void flk_add_callback(flk_callback_t *, 254 callb_cpr_t *(*)(flk_cb_when_t, void *), void *, 255 flk_callback_t *); 256 callb_cpr_t *flk_invoke_callbacks(flk_callback_t *, flk_cb_when_t); 257 258 /* Zones hooks */ 259 extern zone_key_t flock_zone_key; 260 261 void *flk_zone_init(zoneid_t); 262 void flk_zone_fini(zoneid_t, void *); 263 264 /* Clustering hooks */ 265 void cl_flk_set_nlm_status(int nlmid, flk_nlm_status_t nlm_state); 266 void cl_flk_remove_locks_by_sysid(int sysid); 267 int cl_flk_has_remote_locks_for_nlmid(struct vnode *vp, int nlmid); 268 void cl_flk_change_nlm_state_to_unknown(int nlmid); 269 void cl_flk_delete_pxfs_locks(struct vfs *vfsp, int pxfsid); 270 #endif /* _KERNEL */ 271 272 #ifdef __cplusplus 273 } 274 #endif 275 276 #endif /* _SYS_FLOCK_H */ 277