xref: /illumos-gate/usr/src/uts/common/sys/flock.h (revision b4203d75)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*b4203d75SMarcel Telka /*	  All Rights Reserved	*/
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
287c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
297c478bd9Sstevel@tonic-gate  */
30bbaa8b60SDan Kruchinin /*
31b819cea2SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
327a5aac98SJerry Jelinek  * Copyright 2015 Joyent, Inc.
33bbaa8b60SDan Kruchinin  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #ifndef _SYS_FLOCK_H
367c478bd9Sstevel@tonic-gate #define	_SYS_FLOCK_H
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
407c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
417c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>		/* for <sys/callb.h> */
427c478bd9Sstevel@tonic-gate #include <sys/callb.h>
437c478bd9Sstevel@tonic-gate #include <sys/param.h>
447c478bd9Sstevel@tonic-gate #include <sys/zone.h>
457a5aac98SJerry Jelinek #if defined(_KERNEL)
467a5aac98SJerry Jelinek #include <sys/file.h>
477a5aac98SJerry Jelinek #endif
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
507c478bd9Sstevel@tonic-gate extern "C" {
517c478bd9Sstevel@tonic-gate #endif
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /*
547c478bd9Sstevel@tonic-gate  * Private declarations and instrumentation for local locking.
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate  * The flag passed to fs_frlock() may be ORed together with either
597c478bd9Sstevel@tonic-gate  * `F_REMOTELOCK' or `F_PXFSLOCK'.  Since this flag is initialized using the
607c478bd9Sstevel@tonic-gate  * `f_flag' field in the `file' structure, and that field is an unsigned short,
617c478bd9Sstevel@tonic-gate  * we do not use the first 2 bytes.
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate #define	F_REMOTELOCK	(0x01 << 16) /* Set if NLM lock */
647c478bd9Sstevel@tonic-gate #define	F_PXFSLOCK	(0x02 << 16) /* Clustering: set if PXFS lock */
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate /*
677c478bd9Sstevel@tonic-gate  * The command passed to reclock() is made by ORing together one or more of
687c478bd9Sstevel@tonic-gate  * the following values.
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #define	INOFLCK		0x01	/* Vnode is locked when reclock() is called. */
727c478bd9Sstevel@tonic-gate #define	SETFLCK		0x02	/* Set a file lock. */
737c478bd9Sstevel@tonic-gate #define	SLPFLCK		0x04	/* Wait if blocked. */
747c478bd9Sstevel@tonic-gate #define	RCMDLCK		0x08	/* F_REMOTELOCK specified */
757c478bd9Sstevel@tonic-gate #define	PCMDLCK		0x10	/* Clustering: F_PXFSLOCK specified */
767c478bd9Sstevel@tonic-gate #define	NBMLCK		0x20	/* non-blocking mandatory locking */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * Special pid value that can be passed to cleanlocks().  It means that
807c478bd9Sstevel@tonic-gate  * cleanlocks() should flush all locks for the given sysid, not just the
817c478bd9Sstevel@tonic-gate  * locks owned by a specific process.
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #define	IGN_PID		(-1)
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /* file locking structure (connected to vnode) */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #define	l_end		l_len
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /*
917c478bd9Sstevel@tonic-gate  * The lock manager is allowed to use unsigned offsets and lengths, though
927c478bd9Sstevel@tonic-gate  * regular Unix processes are still required to use signed offsets and
937c478bd9Sstevel@tonic-gate  * lengths.
947c478bd9Sstevel@tonic-gate  */
957c478bd9Sstevel@tonic-gate typedef ulong_t u_off_t;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate #define	MAX_U_OFF_T	((u_off_t)~0)
987c478bd9Sstevel@tonic-gate #define	MAX_U_OFFSET_T	((u_offset_t)~0)
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * define MAXEND as the largest positive value the signed offset_t will hold.
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate #define	MAXEND		MAXOFFSET_T
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * Definitions for accessing the l_pad area of struct flock.  The
1077c478bd9Sstevel@tonic-gate  * descriminant of the pad_info_t union is the fcntl command used in
1087c478bd9Sstevel@tonic-gate  * conjunction with the flock struct.
1097c478bd9Sstevel@tonic-gate  */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate typedef union {
1127c478bd9Sstevel@tonic-gate 	int	pi_pad[4];		/* (original pad area) */
1137c478bd9Sstevel@tonic-gate 	int	pi_has_rmt;		/* F_HASREMOTELOCKS */
1147c478bd9Sstevel@tonic-gate } pad_info_t;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate #define	l_has_rmt(flockp)	(((pad_info_t *)((flockp)->l_pad))->pi_has_rmt)
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * Optional callbacks for blocking lock requests.  Each function is called
1207c478bd9Sstevel@tonic-gate  * twice.
1217c478bd9Sstevel@tonic-gate  * The first call is after the request is put in the "sleeping" list, but
1227c478bd9Sstevel@tonic-gate  *   before waiting.  At most one callback may return a callb_cpr_t object;
1237c478bd9Sstevel@tonic-gate  *   the others must return NULL.  If a callb_cpr_t is returned, the thread
1247c478bd9Sstevel@tonic-gate  *   will be marked as safe to suspend while waiting for the lock.
1257c478bd9Sstevel@tonic-gate  * The second call is after the request wakes up.  Note that the request
1267c478bd9Sstevel@tonic-gate  *   might not have been granted at the second call (e.g., the request was
1277c478bd9Sstevel@tonic-gate  *   signalled).
1287c478bd9Sstevel@tonic-gate  * New callbacks should be added to the head of the list.  For the first
1297c478bd9Sstevel@tonic-gate  * call the list is walked in order.  For the second call the list is
1307c478bd9Sstevel@tonic-gate  * walked backwards (in case the callbacks need to reacquire locks).
1317c478bd9Sstevel@tonic-gate  */
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate typedef enum {FLK_BEFORE_SLEEP, FLK_AFTER_SLEEP} flk_cb_when_t;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate struct flk_callback {
1367c478bd9Sstevel@tonic-gate 	struct flk_callback *cb_next;	/* circular linked list */
1377c478bd9Sstevel@tonic-gate 	struct flk_callback *cb_prev;
1387c478bd9Sstevel@tonic-gate 	callb_cpr_t	*(*cb_callback)(flk_cb_when_t, void *);	/* fcn ptr */
1397c478bd9Sstevel@tonic-gate 	void		*cb_data;	/* ptr to callback data */
1407c478bd9Sstevel@tonic-gate };
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate typedef struct flk_callback flk_callback_t;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  * This structure members are not used any more inside the kernel.
1467c478bd9Sstevel@tonic-gate  * The structure is used for casting some pointer assignments only.
1477c478bd9Sstevel@tonic-gate  */
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate typedef struct filock {
1507c478bd9Sstevel@tonic-gate 	kcondvar_t cv;
1517c478bd9Sstevel@tonic-gate 	struct	flock set;	/* contains type, start, and end */
1527c478bd9Sstevel@tonic-gate 	struct	{
1537c478bd9Sstevel@tonic-gate 		int granted_flag;	/* granted flag */
1547c478bd9Sstevel@tonic-gate 		struct filock *blk;	/* for sleeping locks only */
1557c478bd9Sstevel@tonic-gate 		struct attacher *blocking_list;
1567c478bd9Sstevel@tonic-gate 		struct attacher *my_attacher;
1577c478bd9Sstevel@tonic-gate 	}	stat;
1587c478bd9Sstevel@tonic-gate 	struct	filock *prev;
1597c478bd9Sstevel@tonic-gate 	struct	filock *next;
1607c478bd9Sstevel@tonic-gate } filock_t;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate #define	FLP_DELAYED_FREE	-1	/* special value for granted_flag */
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate /* structure that contains list of locks to be granted */
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate #define	MAX_GRANT_LOCKS		52
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate typedef struct grant_lock {
1697c478bd9Sstevel@tonic-gate 	struct filock *grant_lock_list[MAX_GRANT_LOCKS];
1707c478bd9Sstevel@tonic-gate 	struct grant_lock *next;
1717c478bd9Sstevel@tonic-gate } grant_lock_t;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate  * Provide a way to cleanly enable and disable Network Lock Manager locking
1757c478bd9Sstevel@tonic-gate  * requests (i.e., requests from remote clients):
1767c478bd9Sstevel@tonic-gate  *    FLK_NLM_SHUTTING_DOWN: Forces all blocked NLM requests to bail out
1777c478bd9Sstevel@tonic-gate  *	and return ENOLCK.
1787c478bd9Sstevel@tonic-gate  *    FLK_NLM_DOWN: Clears all granted NLM server locks.  Both status
1797c478bd9Sstevel@tonic-gate  *	codes cause new NLM lock requests to fail immediately with ENOLCK.
1807c478bd9Sstevel@tonic-gate  *    FLK_NLM_UP: Changes the state of all locks to UP, after a server has
1817c478bd9Sstevel@tonic-gate  *	shutdown and is restarting on the same node.
1827c478bd9Sstevel@tonic-gate  */
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate  * Enumerated type of the four possible states an NLM server can be in.
1867c478bd9Sstevel@tonic-gate  */
1877c478bd9Sstevel@tonic-gate typedef enum {
1887c478bd9Sstevel@tonic-gate 	FLK_NLM_UP,
1897c478bd9Sstevel@tonic-gate 	FLK_NLM_SHUTTING_DOWN,
1907c478bd9Sstevel@tonic-gate 	FLK_NLM_DOWN,
1917c478bd9Sstevel@tonic-gate 	FLK_NLM_UNKNOWN
1927c478bd9Sstevel@tonic-gate } flk_nlm_status_t;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * Provide a way to cleanly enable and disable lock manager locking
1967c478bd9Sstevel@tonic-gate  * requests (i.e., requests from remote clients).  FLK_WAKEUP_SLEEPERS
1977c478bd9Sstevel@tonic-gate  * forces all blocked lock manager requests to bail out and return ENOLCK.
1987c478bd9Sstevel@tonic-gate  * FLK_LOCKMGR_DOWN clears all granted lock manager locks.  Both status
1997c478bd9Sstevel@tonic-gate  * codes cause new lock manager requests to fail immediately with ENOLCK.
2007c478bd9Sstevel@tonic-gate  */
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate typedef enum {
2037c478bd9Sstevel@tonic-gate     FLK_LOCKMGR_UP,
2047c478bd9Sstevel@tonic-gate     FLK_WAKEUP_SLEEPERS,
2057c478bd9Sstevel@tonic-gate     FLK_LOCKMGR_DOWN
2067c478bd9Sstevel@tonic-gate } flk_lockmgr_status_t;
2077c478bd9Sstevel@tonic-gate 
208b819cea2SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate /*
2117c478bd9Sstevel@tonic-gate  * The following structure is used to hold a list of locks returned
2127c478bd9Sstevel@tonic-gate  * by the F_ACTIVELIST or F_SLEEPINGLIST commands to fs_frlock.
2137c478bd9Sstevel@tonic-gate  *
2147c478bd9Sstevel@tonic-gate  * N.B. The lists returned by these commands are dynamically
2157c478bd9Sstevel@tonic-gate  * allocated and must be freed by the caller.  The vnodes returned
2167c478bd9Sstevel@tonic-gate  * in the lists are held and must be released when the caller is done.
2177c478bd9Sstevel@tonic-gate  */
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate typedef struct locklist {
2207c478bd9Sstevel@tonic-gate 	struct vnode *ll_vp;
2217c478bd9Sstevel@tonic-gate 	struct flock64 ll_flock;
2227c478bd9Sstevel@tonic-gate 	struct locklist *ll_next;
2237c478bd9Sstevel@tonic-gate } locklist_t;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate #define	FLK_QUERY_ACTIVE	0x1
2267c478bd9Sstevel@tonic-gate #define	FLK_QUERY_SLEEPING	0x2
2277c478bd9Sstevel@tonic-gate 
2287a5aac98SJerry Jelinek #if defined(_KERNEL)
2297a5aac98SJerry Jelinek int	ofdlock(file_t *, int, struct flock64 *, int, u_offset_t);
2307a5aac98SJerry Jelinek void	ofdcleanlock(file_t *);
2317a5aac98SJerry Jelinek #endif
2327c478bd9Sstevel@tonic-gate int	reclock(struct vnode *, struct flock64 *, int, int, u_offset_t,
2337c478bd9Sstevel@tonic-gate 		flk_callback_t *);
2347c478bd9Sstevel@tonic-gate int	chklock(struct vnode *, int, u_offset_t, ssize_t, int,
2357c478bd9Sstevel@tonic-gate 		caller_context_t *);
2367c478bd9Sstevel@tonic-gate int	convoff(struct vnode *, struct flock64 *, int, offset_t);
2377c478bd9Sstevel@tonic-gate void	cleanlocks(struct vnode *, pid_t, int);
2387c478bd9Sstevel@tonic-gate locklist_t *flk_get_sleeping_locks(int sysid, pid_t pid);
2397c478bd9Sstevel@tonic-gate locklist_t *flk_get_active_locks(int sysid, pid_t pid);
2407c478bd9Sstevel@tonic-gate locklist_t *flk_active_locks_for_vp(const struct vnode *vp);
2417c478bd9Sstevel@tonic-gate locklist_t *flk_active_nbmand_locks_for_vp(const struct vnode *vp);
2427c478bd9Sstevel@tonic-gate locklist_t *flk_active_nbmand_locks(pid_t pid);
2437c478bd9Sstevel@tonic-gate void	flk_free_locklist(locklist_t *);
2447c478bd9Sstevel@tonic-gate int	flk_convert_lock_data(struct vnode *, struct flock64 *,
2457c478bd9Sstevel@tonic-gate 		u_offset_t *, u_offset_t *, offset_t);
2467c478bd9Sstevel@tonic-gate int	flk_check_lock_data(u_offset_t, u_offset_t, offset_t);
2477c478bd9Sstevel@tonic-gate int	flk_has_remote_locks(struct vnode *vp);
2487c478bd9Sstevel@tonic-gate void	flk_set_lockmgr_status(flk_lockmgr_status_t status);
2497c478bd9Sstevel@tonic-gate int	flk_sysid_has_locks(int sysid, int chklck);
250bbaa8b60SDan Kruchinin int	flk_has_remote_locks_for_sysid(vnode_t *vp, int);
2517c478bd9Sstevel@tonic-gate void	flk_init_callback(flk_callback_t *,
2527c478bd9Sstevel@tonic-gate 		callb_cpr_t *(*)(flk_cb_when_t, void *), void *);
2537c478bd9Sstevel@tonic-gate void	flk_add_callback(flk_callback_t *,
2547c478bd9Sstevel@tonic-gate 		callb_cpr_t *(*)(flk_cb_when_t, void *), void *,
2557c478bd9Sstevel@tonic-gate 		flk_callback_t *);
25666848735SMarcel Telka void	flk_del_callback(flk_callback_t *);
2577c478bd9Sstevel@tonic-gate callb_cpr_t *flk_invoke_callbacks(flk_callback_t *, flk_cb_when_t);
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate /* Zones hooks */
2607c478bd9Sstevel@tonic-gate extern	zone_key_t flock_zone_key;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate void	*flk_zone_init(zoneid_t);
2637c478bd9Sstevel@tonic-gate void	flk_zone_fini(zoneid_t, void *);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate /* Clustering hooks */
2667c478bd9Sstevel@tonic-gate void	cl_flk_set_nlm_status(int nlmid, flk_nlm_status_t nlm_state);
2677c478bd9Sstevel@tonic-gate void	cl_flk_remove_locks_by_sysid(int sysid);
2687c478bd9Sstevel@tonic-gate int	cl_flk_has_remote_locks_for_nlmid(struct vnode *vp, int nlmid);
2697c478bd9Sstevel@tonic-gate void	cl_flk_change_nlm_state_to_unknown(int nlmid);
2707c478bd9Sstevel@tonic-gate void	cl_flk_delete_pxfs_locks(struct vfs *vfsp, int pxfsid);
2717c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate #endif
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate #endif	/* _SYS_FLOCK_H */
278