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