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