1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 #ifndef _SMBSRV_SMB_OPLOCK_H
  17 #define _SMBSRV_SMB_OPLOCK_H
  18 
  19 #include <smbsrv/ntifs.h>
  20 
  21 #ifdef __cplusplus
  22 extern "C" {
  23 #endif
  24 
  25 /*
  26  * 2.1.1.10 Per Oplock
  27  *
  28  *
  29  * ExclusiveOpen: The Open used to request the opportunistic lock.
  30  *
  31  * IIOplocks: A list of zero or more Opens used to request a LEVEL_TWO
  32  *  opportunistic lock, as specified in section 2.1.5.17.1.
  33  *
  34  * ROplocks: A list of zero or more Opens used to request a LEVEL_GRANULAR
  35  *  (RequestedOplockLevel: READ_CACHING) opportunistic lock, as specified in
  36  *   section 2.1.5.17.1.
  37  *
  38  * RHOplocks: A list of zero or more Opens used to request a LEVEL_GRANULAR
  39  *  (RequestedOplockLevel: (READ_CACHING|HANDLE_CACHING)) opportunistic lock,
  40  *  as specified in section 2.1.5.17.1.
  41  *
  42  * RHBreakQueue: A list of zero or more RHOpContext objects. This queue is
  43  *  used to track (READ_CACHING|HANDLE_CACHING) oplocks as they are breaking.
  44  *
  45  * WaitList: A list of zero or more Opens belonging to operations that are
  46  *  waiting for an oplock to break, as specified in section 2.1.4.12.
  47  *
  48  * State: The current state of the oplock, expressed as a combination of
  49  *  one or more flags. Valid flags are:
  50  *      [ As follows;  Re-ordered a bit from the spec. ]
  51  */
  52 
  53 /*
  54  * READ_CACHING - Indicates that this Oplock represents an oplock
  55  * that provides caching of reads; this provides the SMB 2.1 read
  56  * caching lease, as described in [MS-SMB2] section 2.2.13.2.8.
  57  */
  58 #define READ_CACHING    OPLOCK_LEVEL_CACHE_READ         /* 1 */
  59 
  60 /*
  61  * HANDLE_CACHING - Indicates that this Oplock represents an oplock
  62  * that provides caching of handles; this provides the SMB 2.1 handle
  63  * caching lease, as described in [MS-SMB2] section 2.2.13.2.8.
  64  */
  65 #define HANDLE_CACHING  OPLOCK_LEVEL_CACHE_HANDLE       /* 2 */
  66 
  67 /*
  68  * WRITE_CACHING - Indicates that this Oplock represents an oplock
  69  * that provides caching of writes; this provides the SMB 2.1 write
  70  * caching lease, as described in [MS-SMB2] section 2.2.13.2.8.
  71  */
  72 #define WRITE_CACHING   OPLOCK_LEVEL_CACHE_WRITE        /* 4 */
  73 
  74 /*
  75  * EXCLUSIVE - Indicates that this Oplock represents an oplock that
  76  * can be held by exactly one client at a time. This flag always appears
  77  * in combination with other flags that indicate the actual oplock level.
  78  * For example, (READ_CACHING|WRITE_CACHING|EXCLUSIVE) represents a
  79  * read caching and write caching oplock, which can be held by only
  80  * one client at a time.
  81  */
  82 #define EXCLUSIVE                       0x00000010
  83 
  84 /*
  85  * MIXED_R_AND_RH - Always appears together with READ_CACHING and
  86  * HANDLE_CACHING.  Indicates that this Oplock represents an oplock
  87  * on which at least one client has been granted a read caching oplock,
  88  * and at least one other client has been granted a read caching and
  89  * handle caching oplock.
  90  */
  91 #define MIXED_R_AND_RH                  0x00000020
  92 
  93 /*
  94  * LEVEL_TWO_OPLOCK - Indicates that this Oplock represents a
  95  * Level 2 (also called Shared) oplock.
  96  * Corresponds to SMB2_OPLOCK_LEVEL_II
  97  */
  98 #define LEVEL_TWO_OPLOCK        OPLOCK_LEVEL_TWO        /* 0x100 */
  99 
 100 /*
 101  * LEVEL_ONE_OPLOCK - Indicates that this Oplock represents a
 102  * Level 1 (also called Exclusive) oplock.
 103  * Corresponds to SMB2_OPLOCK_LEVEL_EXCLUSIVE
 104  */
 105 #define LEVEL_ONE_OPLOCK        OPLOCK_LEVEL_ONE        /* 0x200 */
 106 
 107 /*
 108  * BATCH_OPLOCK - Indicates that this Oplock represents a Batch oplock.
 109  * Corresponds to SMB2_OPLOCK_LEVEL_BATCH
 110  */
 111 #define BATCH_OPLOCK            OPLOCK_LEVEL_BATCH      /* 0x400 */
 112 
 113 /* Note: ntifs.h                OPLOCK_LEVEL_GRANULAR      0x800 */
 114 
 115 /*
 116  * Note that the oplock leasing implementation uses this shift
 117  * to convert (i.e.) CACHE_READ to BREAK_TO_READ_CACHING etc.
 118  * This relationship is checked in smb_srv_oplock.c
 119  */
 120 #define BREAK_SHIFT 16
 121 
 122 /*
 123  * BREAK_TO_READ_CACHING - Indicates that this Oplock represents an
 124  * oplock that is currently breaking to an oplock that provides
 125  * caching of reads; the oplock has broken but the break has not yet
 126  * been acknowledged.
 127  */
 128 #define BREAK_TO_READ_CACHING           0x00010000
 129 
 130 /*
 131  * BREAK_TO_HANDLE_CACHING - Indicates that this Oplock represents an
 132  * oplock that is currently breaking to an oplock that provides
 133  * caching of handles; the oplock has broken but the break has not yet
 134  * been acknowledged.  Note: == (CACHE_HANDLE << BREAK_SHIFT)
 135  */
 136 #define BREAK_TO_HANDLE_CACHING         0x00020000
 137 
 138 /*
 139  * BREAK_TO_WRITE_CACHING - Indicates that this Oplock represents an
 140  * oplock that is currently breaking to an oplock that provides
 141  * caching of writes; the oplock has broken but the break has
 142  * not yet been acknowledged.
 143  */
 144 #define BREAK_TO_WRITE_CACHING          0x00040000
 145 
 146 /*
 147  * BREAK_TO_NO_CACHING - Indicates that this Oplock represents an
 148  * oplock that is currently breaking to None (that is, no oplock);
 149  * the oplock has broken but the break has not yet been acknowledged.
 150  */
 151 #define BREAK_TO_NO_CACHING             0x00080000
 152 
 153 /*
 154  * BREAK_TO_TWO - Indicates that this Oplock represents an oplock
 155  * that is currently breaking from either Level 1 or Batch to Level 2;
 156  * the oplock has broken but the break has not yet been acknowledged.
 157  */
 158 #define BREAK_TO_TWO                    0x00100000
 159 
 160 /*
 161  * BREAK_TO_NONE - Indicates that this Oplock represents an oplock
 162  * that is currently breaking from either Level 1 or Batch to None
 163  * (that is, no oplock); the oplock has broken but the break has
 164  * not yet been acknowledged.
 165  */
 166 #define BREAK_TO_NONE                   0x00200000
 167 
 168 /*
 169  * BREAK_TO_TWO_TO_NONE - Indicates that this Oplock represents an
 170  * oplock that is currently breaking from either Level 1 or Batch to
 171  * None (that is, no oplock), and was previously breaking from Level 1
 172  *  or Batch to Level 2; the oplock has broken but the break has
 173  * not yet been acknowledged.
 174  */
 175 #define BREAK_TO_TWO_TO_NONE            0x00400000
 176 
 177 /*
 178  * NO_OPLOCK - Indicates that this Oplock does not represent a
 179  * currently granted or breaking oplock. This is semantically
 180  * equivalent to the Oplock object being entirely absent from a
 181  * Stream. This flag always appears alone.
 182  * Note we also have OPLOCK_LEVEL_NONE == 0 from ntifs.h
 183  */
 184 #define NO_OPLOCK                       0x10000000
 185 
 186 /*
 187  * An internal flag, non-overlapping wth other oplock flags,
 188  * used only in smb_cmn_oplock.c (and here only to make clear
 189  * that it does not overlap with an other flags above).
 190  */
 191 #define PARENT_OBJECT                   0x40000000
 192 
 193 /*
 194  * Also not in the spec, but convenient
 195  */
 196 #define BREAK_LEVEL_MASK (\
 197         BREAK_TO_READ_CACHING |\
 198         BREAK_TO_WRITE_CACHING |\
 199         BREAK_TO_HANDLE_CACHING |\
 200         BREAK_TO_NO_CACHING)
 201 
 202 #define BREAK_ANY (\
 203         BREAK_LEVEL_MASK |\
 204         BREAK_TO_TWO |\
 205         BREAK_TO_NONE |\
 206         BREAK_TO_TWO_TO_NONE)
 207 
 208 
 209 /*
 210  * Convenience macro to walk ofiles on a give node.
 211  * Used as follows:
 212  *      FOREACH_NODE_OFILE(node, o) { muck_with(o); }
 213  */
 214 #define FOREACH_NODE_OFILE(node, o)     for \
 215         (o = smb_llist_head(&node->n_ofile_list); \
 216         o != NULL; \
 217         o = smb_llist_next(&node->n_ofile_list, o))
 218 
 219 /*
 220  * Some short-hand names used in the oplock code.
 221  */
 222 
 223 #define STATUS_NEW_HANDLE       NT_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE
 224 #define STATUS_CANT_GRANT       NT_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK
 225 
 226 typedef enum oplock_type {
 227         LEVEL_NONE = OPLOCK_LEVEL_NONE,
 228         LEVEL_TWO = OPLOCK_LEVEL_TWO,
 229         LEVEL_ONE = OPLOCK_LEVEL_ONE,
 230         LEVEL_BATCH = OPLOCK_LEVEL_BATCH,
 231         LEVEL_GRANULAR = OPLOCK_LEVEL_GRANULAR
 232 } oplock_type_t;
 233 
 234 typedef enum oplock_cache_level {
 235         CACHE_R =       READ_CACHING,
 236 
 237         CACHE_RH =      READ_CACHING |
 238                         HANDLE_CACHING,
 239 
 240         CACHE_RW =      READ_CACHING |
 241                         WRITE_CACHING,
 242 
 243         CACHE_RWH =     READ_CACHING |
 244                         WRITE_CACHING |
 245                         HANDLE_CACHING,
 246 } oplock_cache_t;
 247 
 248 #ifdef __cplusplus
 249 }
 250 #endif
 251 
 252 #endif /* _SMBSRV_SMB_OPLOCK_H */