xref: /illumos-gate/usr/src/uts/common/sys/flock.h (revision 4fe8b4169f2d86d1a437c24b01105d63d7c7bb37)
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 void	flk_del_callback(flk_callback_t *);
257 callb_cpr_t *flk_invoke_callbacks(flk_callback_t *, flk_cb_when_t);
258 
259 /* Zones hooks */
260 extern	zone_key_t flock_zone_key;
261 
262 void	*flk_zone_init(zoneid_t);
263 void	flk_zone_fini(zoneid_t, void *);
264 
265 /* Clustering hooks */
266 void	cl_flk_set_nlm_status(int nlmid, flk_nlm_status_t nlm_state);
267 void	cl_flk_remove_locks_by_sysid(int sysid);
268 int	cl_flk_has_remote_locks_for_nlmid(struct vnode *vp, int nlmid);
269 void	cl_flk_change_nlm_state_to_unknown(int nlmid);
270 void	cl_flk_delete_pxfs_locks(struct vfs *vfsp, int pxfsid);
271 #endif /* _KERNEL */
272 
273 #ifdef	__cplusplus
274 }
275 #endif
276 
277 #endif	/* _SYS_FLOCK_H */
278