Print this page
    
NEX-19647 panic in smb_notify_encode_action
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-18761 panic in smb_ofile_free with vdbench
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-17431 (HyperV) Windows VM goes panic after failover
NEX-18639 Panic in smb_ofile_release with expired ofile
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-15958 panic importing CA share after failover
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Include in backports of:
  NEX-9808 SMB3 persistent handles
NEX-15958 panic importing CA share after failover
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Include in backports of:
  NEX-9808 SMB3 persistent handles
NEX-15931 Panic removing files in SMB3 CA share
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Include in backports of:
  NEX-9808 SMB3 persistent handles
NEX-15931 Panic removing files in SMB3 CA share
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Include in backports of:
  NEX-9808 SMB3 persistent handles
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-13653 Obsolete SMB server work-around for ZFS read-only
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9360 SMB1 fails renaming an open file
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-8495 Panic after SMB flush on a named pipe
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6096 Enable compile warnings re. parentheses in smbsrv
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
NEX-6042 SMB resilient handle lock replay
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5977 smbtorture smb2.notify.mask fails after NEX-3553
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3553 SMB2/3 durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5586 SMB2 ofiles need real Persistent IDs
NEX-5313 SMB2 oplock break notification should use TID=0
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-5537 Want reference counts for users, trees...
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-5312 delete_on_close should be acted on earlier
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-3906 Prefer that SMB change notify not tie up a worker thread
NEX-5278 SMB notify should buffer per file handle
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3432 CLONE - NEX-3232 Symantec Backup Exec fails opening files over SMB
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Daniel Borek <daniel.borek@nexenta.com>
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-39 Use AF_UNIX pipes for RPC
SMB-65 SMB server in non-global zones (use zone_kcred())
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #7815 SMB server delivers old modification time... (fix allocsz)
re #7815 SMB server delivers old modification time...
re #11215 rb3676 sesctl to SGI JBOD hangs in biowait() with a command stuck in mptsas driver
re #10734 NT Trans. Notify returning too quickly
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb_ofile.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_ofile.c
   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 (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24   23   * Copyright 2016 Syneto S.R.L. All rights reserved.
  25   24   * Copyright (c) 2016 by Delphix. All rights reserved.
       25 + * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  26   26   */
  27   27  
  28   28  /*
  29   29   * General Structures Layout
  30   30   * -------------------------
  31   31   *
  32   32   * This is a simplified diagram showing the relationship between most of the
  33   33   * main structures.
  34   34   *
  35   35   * +-------------------+
  36   36   * |     SMB_INFO      |
  37   37   * +-------------------+
  38   38   *          |
  39   39   *          |
  40   40   *          v
  41   41   * +-------------------+       +-------------------+      +-------------------+
  42   42   * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
  43   43   * +-------------------+       +-------------------+      +-------------------+
  44   44   *   |          |
  45   45   *   |          |
  46   46   *   |          v
  47   47   *   |  +-------------------+     +-------------------+   +-------------------+
  48   48   *   |  |       USER        |<--->|       USER        |...|       USER        |
  49   49   *   |  +-------------------+     +-------------------+   +-------------------+
  50   50   *   |
  51   51   *   |
  52   52   *   v
  53   53   * +-------------------+       +-------------------+      +-------------------+
  54   54   * |       TREE        |<----->|       TREE        |......|       TREE        |
  55   55   * +-------------------+       +-------------------+      +-------------------+
  56   56   *      |         |
  57   57   *      |         |
  58   58   *      |         v
  59   59   *      |     +-------+       +-------+      +-------+
  60   60   *      |     | OFILE |<----->| OFILE |......| OFILE |
  61   61   *      |     +-------+       +-------+      +-------+
  62   62   *      |
  63   63   *      |
  
    | 
      ↓ open down ↓ | 
    28 lines elided | 
    
      ↑ open up ↑ | 
  
  64   64   *      v
  65   65   *  +-------+       +------+      +------+
  66   66   *  | ODIR  |<----->| ODIR |......| ODIR |
  67   67   *  +-------+       +------+      +------+
  68   68   *
  69   69   *
  70   70   * Ofile State Machine
  71   71   * ------------------
  72   72   *
  73   73   *    +-------------------------+        T0
  74      - *    |  SMB_OFILE_STATE_OPEN   |<----------- Creation/Allocation
       74 + *    |  SMB_OFILE_STATE_OPEN   |<--+-------- Creation/Allocation
       75 + *    +-------------------------+   |
       76 + *          |           |           | T5
       77 + *          |           |       +---------------------------+
       78 + *          |           |       | SMB_OFILE_STATE_RECONNECT |
       79 + *          |           |       +---------------------------+
       80 + *          |           |           ^
       81 + *          |           v           |
       82 + *          |   +---------------+   |
       83 + *          |   | STATE_SAVE_DH |   |
       84 + *          |   | STATE_SAVING  |   |
       85 + *          |   +---------------+   |
       86 + *          |           |           | T4
       87 + *          | T1        | T3    +--------------------------+
       88 + *          |           +------>| SMB_OFILE_STATE_ORPHANED |
       89 + *          v                   +--------------------------+
       90 + *    +-------------------------+   |           |
       91 + *    | SMB_OFILE_STATE_CLOSING |<--+ T6        | T7
       92 + *    +-------------------------+               |
       93 + *          |           ^                       v
       94 + *          | T2        | T8    +-------------------------+
       95 + *          |           +-------| SMB_OFILE_STATE_EXPIRED |
       96 + *          v                   +-------------------------+
  75   97   *    +-------------------------+
  76      - *                  |
  77      - *                  | T1
  78      - *                  |
  79      - *                  v
  80      - *    +-------------------------+
  81      - *    | SMB_OFILE_STATE_CLOSING |
  82      - *    +-------------------------+
  83      - *                  |
  84      - *                  | T2
  85      - *                  |
  86      - *                  v
  87      - *    +-------------------------+    T3
  88   98   *    | SMB_OFILE_STATE_CLOSED  |----------> Deletion/Free
  89      - *    +-------------------------+
       99 + *    +-------------------------+    T9
  90  100   *
  91  101   * SMB_OFILE_STATE_OPEN
  92  102   *
  93  103   *    While in this state:
  94  104   *      - The ofile is queued in the list of ofiles of its tree.
  95  105   *      - References will be given out if the ofile is looked up.
  96  106   *
      107 + * SMB_OFILE_STATE_SAVE_DH
      108 + *
      109 + *    Similar to state _CLOSING, but instead of deleting the ofile,
      110 + *    it leaves the ofile in state _ORPHANED (for later reclaim).
      111 + *    Will move to _SAVING after last ref, then _ORPHANED.
      112 + *
      113 + *    While in this state:
      114 + *      - The ofile has been marked for preservation during a
      115 + *        walk of the tree ofile list to close multiple files.
      116 + *      - References will not be given out if the ofile is looked up,
      117 + *        except for oplock break processing.
      118 + *      - Still affects Sharing Violation rules
      119 + *
      120 + * SMB_OFILE_STATE_SAVING
      121 + *
      122 + *    Transient state used to keep oplock break processing out
      123 + *    while the ofile moves to state _ORPHANED.
      124 + *
      125 + *    While in this state:
      126 + *      - References will not be given out if the ofile is looked up,
      127 + *        except for oplock break processing.
      128 + *      - Still affects Sharing Violation rules
      129 + *
  97  130   * SMB_OFILE_STATE_CLOSING
  98  131   *
      132 + *    Close has been requested.  Stay in this state until the last
      133 + *    ref. is gone, then move to state _CLOSED
      134 + *
  99  135   *    While in this state:
 100  136   *      - The ofile is queued in the list of ofiles of its tree.
 101  137   *      - References will not be given out if the ofile is looked up.
 102  138   *      - The file is closed and the locks held are being released.
 103  139   *      - The resources associated with the ofile remain.
 104  140   *
 105  141   * SMB_OFILE_STATE_CLOSED
 106  142   *
 107  143   *    While in this state:
 108  144   *      - The ofile is queued in the list of ofiles of its tree.
 109  145   *      - References will not be given out if the ofile is looked up.
 110  146   *      - The resources associated with the ofile remain.
 111  147   *
      148 + * SMB_OFILE_STATE_ORPHANED
      149 + *
      150 + *    While in this state:
      151 + *      - The ofile is queued in the list of ofiles of its tree.
      152 + *      - Can be reclaimed by the original owner
      153 + *      - References will not be given out if the ofile is looked up.
      154 + *      - All the tree, user, and session "up" pointers are NULL!
      155 + *      - Will eventually be "expired" if not reclaimed
      156 + *      - Can be closed if its oplock is broken
      157 + *      - Still affects Sharing Violation rules
      158 + *
      159 + * SMB_OFILE_STATE_EXPIRED
      160 + *
      161 + *    While in this state:
      162 + *      - The ofile is queued in the list of ofiles of its tree.
      163 + *      - References will not be given out if the ofile is looked up.
      164 + *      - The ofile has not been reclaimed and will soon be closed,
      165 + *        due to, for example, the durable handle timer expiring, or its
      166 + *        oplock being broken.
      167 + *      - Cannot be reclaimed at this point
      168 + *
      169 + * SMB_OFILE_STATE_RECONNECT
      170 + *
      171 + *    Transient state used to keep oplock break processing out
      172 + *    while the ofile moves from state _ORPHANED to _OPEN.
      173 + *
      174 + *    While in this state:
      175 + *      - The ofile is being reclaimed; do not touch it.
      176 + *      - References will not be given out if the ofile is looked up.
      177 + *      - Still affects Sharing Violation rules
      178 + *      - see smb2_dh_reconnect() for which members need to be avoided
      179 + *
 112  180   * Transition T0
 113  181   *
 114  182   *    This transition occurs in smb_ofile_open(). A new ofile is created and
 115  183   *    added to the list of ofiles of a tree.
 116  184   *
 117  185   * Transition T1
 118  186   *
 119      - *    This transition occurs in smb_ofile_close().
      187 + *    This transition occurs in smb_ofile_close(). Note that this only happens
      188 + *    when we determine that an ofile should be closed in spite of its durable
      189 + *    handle properties.
 120  190   *
 121  191   * Transition T2
 122  192   *
 123  193   *    This transition occurs in smb_ofile_release(). The resources associated
 124  194   *    with the ofile are freed as well as the ofile structure. For the
 125  195   *    transition to occur, the ofile must be in the SMB_OFILE_STATE_CLOSED
 126  196   *    state and the reference count be zero.
 127  197   *
      198 + * Transition T3
      199 + *
      200 + *    This transition occurs in smb_ofile_orphan_dh(). It happens during an
      201 + *    smb2 logoff, or during a session disconnect when certain conditions are
      202 + *    met. The ofile and structures above it will be kept around until the ofile
      203 + *    either gets reclaimed, expires after f_timeout_offset nanoseconds, or its
      204 + *    oplock is broken.
      205 + *
      206 + * Transition T4
      207 + *
      208 + *    This transition occurs in smb2_dh_reconnect(). An smb2 create request
      209 + *    with a DURABLE_HANDLE_RECONNECT(_V2) create context has been
      210 + *    recieved from the original owner. If leases are supported or it's
      211 + *    RECONNECT_V2, reconnect is subject to additional conditions. The ofile
      212 + *    will be unwired from the old, disconnected session, tree, and user,
      213 + *    and wired up to its new context.
      214 + *
      215 + * Transition T5
      216 + *
      217 + *    This transition occurs in smb2_dh_reconnect(). The ofile has been
      218 + *    successfully reclaimed.
      219 + *
      220 + * Transition T6
      221 + *
      222 + *    This transition occurs in smb_ofile_close(). The ofile has been orphaned
      223 + *    while some thread was blocked, and that thread closes the ofile. Can only
      224 + *    happen when the ofile is orphaned due to an SMB2 LOGOFF request.
      225 + *
      226 + * Transition T7
      227 + *
      228 + *    This transition occurs in smb_session_durable_timers() and
      229 + *    smb_oplock_send_brk(). The ofile will soon be closed.
      230 + *    In the former case, f_timeout_offset nanoseconds have passed since
      231 + *    the ofile was orphaned. In the latter, an oplock break occured
      232 + *    on the ofile while it was orphaned.
      233 + *
      234 + * Transition T8
      235 + *
      236 + *    This transition occurs in smb_ofile_close().
      237 + *
      238 + * Transition T9
      239 + *
      240 + *    This transition occurs in smb_ofile_delete().
      241 + *
 128  242   * Comments
 129  243   * --------
 130  244   *
 131  245   *    The state machine of the ofile structures is controlled by 3 elements:
 132  246   *      - The list of ofiles of the tree it belongs to.
 133  247   *      - The mutex embedded in the structure itself.
 134  248   *      - The reference count.
 135  249   *
 136  250   *    There's a mutex embedded in the ofile structure used to protect its fields
 137  251   *    and there's a lock embedded in the list of ofiles of a tree. To
 138  252   *    increment or to decrement the reference count the mutex must be entered.
 139  253   *    To insert the ofile into the list of ofiles of the tree and to remove
 140  254   *    the ofile from it, the lock must be entered in RW_WRITER mode.
 141  255   *
 142  256   *    Rules of access to a ofile structure:
 143  257   *
 144  258   *    1) In order to avoid deadlocks, when both (mutex and lock of the ofile
 145      - *       list) have to be entered, the lock must be entered first.
      259 + *       list) have to be entered, the lock must be entered first. Additionally,
      260 + *       f_mutex must not be held when removing the ofile from sv_persistid_ht.
 146  261   *
 147  262   *    2) All actions applied to an ofile require a reference count.
 148  263   *
 149  264   *    3) There are 2 ways of getting a reference count. One is when the ofile
 150  265   *       is opened. The other one when the ofile is looked up. This translates
 151  266   *       into 2 functions: smb_ofile_open() and smb_ofile_lookup_by_fid().
 152  267   *
 153  268   *    It should be noted that the reference count of an ofile registers the
 154  269   *    number of references to the ofile in other structures (such as an smb
 155  270   *    request). The reference count is not incremented in these 2 instances:
 156  271   *
 157  272   *    1) The ofile is open. An ofile is anchored by its state. If there's
 158  273   *       no activity involving an ofile currently open, the reference count
 159  274   *       of that ofile is zero.
 160  275   *
 161  276   *    2) The ofile is queued in the list of ofiles of its tree. The fact of
 162  277   *       being queued in that list is NOT registered by incrementing the
 163  278   *       reference count.
 164  279   */
 165      -#include <smbsrv/smb_kproto.h>
      280 +#include <smbsrv/smb2_kproto.h>
 166  281  #include <smbsrv/smb_fsops.h>
      282 +#include <sys/time.h>
      283 +#include <sys/random.h>
 167  284  
 168  285  static boolean_t smb_ofile_is_open_locked(smb_ofile_t *);
 169      -static smb_ofile_t *smb_ofile_close_and_next(smb_ofile_t *);
      286 +static void smb_ofile_delete(void *arg);
      287 +static void smb_ofile_save_dh(void *arg);
      288 +
 170  289  static int smb_ofile_netinfo_encode(smb_ofile_t *, uint8_t *, size_t,
 171  290      uint32_t *);
 172  291  static int smb_ofile_netinfo_init(smb_ofile_t *, smb_netfileinfo_t *);
 173  292  static void smb_ofile_netinfo_fini(smb_netfileinfo_t *);
 174  293  
 175  294  /*
 176      - * smb_ofile_open
      295 + * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
      296 + * which is used to uniquely identify open instances for the
      297 + * VFS share reservation and POSIX locks.
 177  298   */
      299 +static volatile uint32_t smb_fids = 0;
      300 +#define SMB_UNIQ_FID()  atomic_inc_32_nv(&smb_fids)
      301 +
      302 +/*
      303 + * smb_ofile_alloc
      304 + * Allocate an ofile and fill in it's "up" pointers, but
      305 + * do NOT link it into the tree's list of ofiles or the
      306 + * node's list of ofiles.  An ofile in this state is a
      307 + * "proposed" open passed to the oplock break code.
      308 + *
      309 + * If we don't get as far as smb_ofile_open with this OF,
      310 + * call smb_ofile_free() to free this object.
      311 + *
      312 + * Note: The following sr members may be null during
      313 + * persistent handle import: session, uid_usr, tid_tree
      314 + */
 178  315  smb_ofile_t *
 179      -smb_ofile_open(
      316 +smb_ofile_alloc(
 180  317      smb_request_t       *sr,
 181      -    smb_node_t          *node,
 182      -    struct open_param   *op,
      318 +    smb_arg_open_t      *op,
      319 +    smb_node_t          *node, /* optional (may be NULL) */
 183  320      uint16_t            ftype,
 184      -    uint32_t            uniqid,
 185      -    smb_error_t         *err)
      321 +    uint16_t            tree_fid)
 186  322  {
 187      -        smb_tree_t      *tree = sr->tid_tree;
      323 +        smb_user_t      *user = sr->uid_user;   /* optional */
      324 +        smb_tree_t      *tree = sr->tid_tree;   /* optional */
 188  325          smb_ofile_t     *of;
 189      -        uint16_t        fid;
 190      -        smb_attr_t      attr;
 191      -        int             rc;
 192      -        enum errstates { EMPTY, FIDALLOC, CRHELD, MUTEXINIT };
 193      -        enum errstates  state = EMPTY;
 194  326  
 195      -        if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) {
 196      -                err->status = NT_STATUS_TOO_MANY_OPENED_FILES;
 197      -                err->errcls = ERRDOS;
 198      -                err->errcode = ERROR_TOO_MANY_OPEN_FILES;
 199      -                return (NULL);
 200      -        }
 201      -        state = FIDALLOC;
 202      -
 203  327          of = kmem_cache_alloc(smb_cache_ofile, KM_SLEEP);
 204  328          bzero(of, sizeof (smb_ofile_t));
 205  329          of->f_magic = SMB_OFILE_MAGIC;
      330 +
      331 +        mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
      332 +        list_create(&of->f_notify.nc_waiters, sizeof (smb_request_t),
      333 +            offsetof(smb_request_t, sr_waiters));
      334 +        mutex_init(&of->dh_nvlock, NULL, MUTEX_DEFAULT, NULL);
      335 +
      336 +        of->f_state = SMB_OFILE_STATE_ALLOC;
 206  337          of->f_refcnt = 1;
 207      -        of->f_fid = fid;
 208      -        of->f_uniqid = uniqid;
      338 +        of->f_ftype = ftype;
      339 +        of->f_fid = tree_fid;
      340 +        /* of->f_persistid see smb2_create */
      341 +        of->f_uniqid = SMB_UNIQ_FID();
 209  342          of->f_opened_by_pid = sr->smb_pid;
 210  343          of->f_granted_access = op->desired_access;
 211  344          of->f_share_access = op->share_access;
 212  345          of->f_create_options = op->create_options;
 213      -        of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ?
 214      -            smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred;
 215      -        crhold(of->f_cr);
 216      -        state = CRHELD;
 217      -        of->f_ftype = ftype;
 218      -        of->f_server = tree->t_server;
 219      -        of->f_session = tree->t_session;
      346 +        if (user != NULL) {
      347 +                if ((op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) != 0)
      348 +                        of->f_cr = smb_user_getprivcred(user);
      349 +                else
      350 +                        of->f_cr = user->u_cred;
      351 +                crhold(of->f_cr);
      352 +        }
      353 +        of->f_server = sr->sr_server;
      354 +        of->f_session = sr->session;    /* may be NULL */
      355 +
      356 +        (void) memset(of->f_lock_seq, -1, SMB_OFILE_LSEQ_MAX);
      357 +
      358 +        of->f_mode = smb_fsop_amask_to_omode(of->f_granted_access);
      359 +        if ((of->f_granted_access & FILE_DATA_ALL) == FILE_EXECUTE)
      360 +                of->f_flags |= SMB_OFLAGS_EXECONLY;
      361 +
 220  362          /*
 221      -         * grab a ref for of->f_user
 222      -         * released in smb_ofile_delete()
      363 +         * In case a lease is requested, copy the lease keys now so
      364 +         * any oplock breaks during open don't break those on our
      365 +         * other handles that might have the same lease.
 223  366           */
 224      -        smb_user_hold_internal(sr->uid_user);
 225      -        of->f_user = sr->uid_user;
 226      -        of->f_tree = tree;
 227      -        of->f_node = node;
      367 +        bcopy(op->lease_key, of->TargetOplockKey, SMB_LEASE_KEY_SZ);
      368 +        bcopy(op->parent_lease_key, of->ParentOplockKey, SMB_LEASE_KEY_SZ);
 228  369  
 229      -        mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
 230      -        state = MUTEXINIT;
      370 +        /*
      371 +         * grab a ref for of->f_user and of->f_tree
      372 +         * We know the user and tree must be "live" because
      373 +         * this SR holds references to them.  The node ref. is
      374 +         * held by our caller, until smb_ofile_open puts this
      375 +         * ofile on the node ofile list with smb_node_add_ofile.
      376 +         */
      377 +        if (user != NULL) {
      378 +                smb_user_hold_internal(user);
      379 +                of->f_user = user;
      380 +        }
      381 +        if (tree != NULL) {
      382 +                smb_tree_hold_internal(tree);
      383 +                of->f_tree = tree;
      384 +        }
      385 +        of->f_node = node;      /* may be NULL */
      386 +
      387 +        return (of);
      388 +}
      389 +
      390 +/*
      391 + * smb_ofile_open
      392 + *
      393 + * Complete an open on an ofile that was previously allocated by
      394 + * smb_ofile_alloc, by putting it on the tree ofile list and
      395 + * (if it's a file) the node ofile list.
      396 + */
      397 +void
      398 +smb_ofile_open(
      399 +    smb_request_t       *sr,
      400 +    smb_arg_open_t      *op,
      401 +    smb_ofile_t         *of)
      402 +{
      403 +        smb_tree_t      *tree = sr->tid_tree;
      404 +        smb_node_t      *node = of->f_node;
      405 +
      406 +        ASSERT(of->f_state == SMB_OFILE_STATE_ALLOC);
 231  407          of->f_state = SMB_OFILE_STATE_OPEN;
 232  408  
 233      -        if (ftype == SMB_FTYPE_MESG_PIPE) {
      409 +        switch (of->f_ftype) {
      410 +        case SMB_FTYPE_BYTE_PIPE:
      411 +        case SMB_FTYPE_MESG_PIPE:
 234  412                  /* See smb_opipe_open. */
 235  413                  of->f_pipe = op->pipe;
 236  414                  smb_server_inc_pipes(of->f_server);
 237      -        } else {
 238      -                ASSERT(ftype == SMB_FTYPE_DISK); /* Regular file, not a pipe */
 239      -                ASSERT(node);
      415 +                break;
      416 +        case SMB_FTYPE_DISK:
      417 +        case SMB_FTYPE_PRINTER:
      418 +                /* Regular file, not a pipe */
      419 +                ASSERT(node != NULL);
 240  420  
 241      -                /*
 242      -                 * Note that the common open path often adds bits like
 243      -                 * READ_CONTROL, so the logic "is this open exec-only"
 244      -                 * needs to look at only the FILE_DATA_ALL bits.
 245      -                 */
 246      -                if ((of->f_granted_access & FILE_DATA_ALL) == FILE_EXECUTE)
 247      -                        of->f_flags |= SMB_OFLAGS_EXECONLY;
 248      -
 249      -                bzero(&attr, sizeof (smb_attr_t));
 250      -                attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR;
 251      -                rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr);
 252      -                if (rc != 0) {
 253      -                        err->status = NT_STATUS_INTERNAL_ERROR;
 254      -                        err->errcls = ERRDOS;
 255      -                        err->errcode = ERROR_INTERNAL_ERROR;
 256      -                        goto errout;
 257      -                }
 258      -                if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) {
 259      -                        /*
 260      -                         * Add this bit for the file's owner even if it's not
 261      -                         * specified in the request (Windows behavior).
 262      -                         */
 263      -                        of->f_granted_access |= FILE_READ_ATTRIBUTES;
 264      -                }
 265      -
 266      -                if (smb_node_is_file(node)) {
 267      -                        of->f_mode =
 268      -                            smb_fsop_amask_to_omode(of->f_granted_access);
 269      -                        if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) {
 270      -                                err->status = NT_STATUS_ACCESS_DENIED;
 271      -                                err->errcls = ERRDOS;
 272      -                                err->errcode = ERROR_ACCESS_DENIED;
 273      -                                goto errout;
 274      -                        }
 275      -                }
 276      -
 277      -                if (tree->t_flags & SMB_TREE_READONLY)
 278      -                        of->f_flags |= SMB_OFLAGS_READONLY;
 279      -
 280      -                /*
 281      -                 * Note that if we created_readonly, that
 282      -                 * will _not_ yet show in attr.sa_dosattr
 283      -                 * so creating a readonly file gives the
 284      -                 * caller a writable handle as it should.
 285      -                 */
 286      -                if (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)
 287      -                        of->f_flags |= SMB_OFLAGS_READONLY;
 288      -
 289  421                  smb_node_inc_open_ofiles(node);
 290  422                  smb_node_add_ofile(node, of);
 291  423                  smb_node_ref(node);
 292  424                  smb_server_inc_files(of->f_server);
      425 +                break;
      426 +        default:
      427 +                ASSERT(0);
 293  428          }
 294  429          smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
 295  430          smb_llist_insert_tail(&tree->t_ofile_list, of);
 296  431          smb_llist_exit(&tree->t_ofile_list);
 297  432          atomic_inc_32(&tree->t_open_files);
 298  433          atomic_inc_32(&of->f_session->s_file_cnt);
 299      -        return (of);
 300  434  
 301      -errout:
 302      -        switch (state) {
 303      -        case MUTEXINIT:
 304      -                mutex_destroy(&of->f_mutex);
 305      -                smb_user_release(of->f_user);
 306      -                /*FALLTHROUGH*/
 307      -        case CRHELD:
 308      -                crfree(of->f_cr);
 309      -                of->f_magic = 0;
 310      -                kmem_cache_free(smb_cache_ofile, of);
 311      -                /*FALLTHROUGH*/
 312      -        case FIDALLOC:
 313      -                smb_idpool_free(&tree->t_fid_pool, fid);
 314      -                /*FALLTHROUGH*/
 315      -        case EMPTY:
 316      -                break;
 317      -        }
 318      -        return (NULL);
 319  435  }
 320  436  
 321  437  /*
 322  438   * smb_ofile_close
      439 + *
      440 + * Incoming states: (where from)
      441 + *   SMB_OFILE_STATE_OPEN  protocol close, smb_ofile_drop
      442 + *   SMB_OFILE_STATE_EXPIRED  called via smb2_dh_expire
      443 + *   SMB_OFILE_STATE_ORPHANED  smb_server_cleanup_sessions()
 323  444   */
 324  445  void
 325  446  smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec)
 326  447  {
 327  448          smb_attr_t *pa;
 328  449          timestruc_t now;
 329      -        uint32_t flags = 0;
 330  450  
 331  451          SMB_OFILE_VALID(of);
 332  452  
 333  453          mutex_enter(&of->f_mutex);
 334  454          ASSERT(of->f_refcnt);
 335      -        if (of->f_state != SMB_OFILE_STATE_OPEN) {
      455 +
      456 +        switch (of->f_state) {
      457 +        case SMB_OFILE_STATE_OPEN:
      458 +        case SMB_OFILE_STATE_ORPHANED:
      459 +        case SMB_OFILE_STATE_EXPIRED:
      460 +                of->f_state = SMB_OFILE_STATE_CLOSING;
 336  461                  mutex_exit(&of->f_mutex);
      462 +                break;
      463 +        default:
      464 +                mutex_exit(&of->f_mutex);
 337  465                  return;
 338  466          }
 339      -        of->f_state = SMB_OFILE_STATE_CLOSING;
 340      -        mutex_exit(&of->f_mutex);
 341  467  
      468 +        /*
      469 +         * Only one thread here (the one that that set f_state closing)
      470 +         */
 342  471          switch (of->f_ftype) {
 343  472          case SMB_FTYPE_BYTE_PIPE:
 344  473          case SMB_FTYPE_MESG_PIPE:
 345  474                  smb_opipe_close(of);
 346  475                  smb_server_dec_pipes(of->f_server);
 347  476                  break;
 348  477  
 349  478          case SMB_FTYPE_DISK:
 350      -        case SMB_FTYPE_PRINTER:
      479 +                if (of->dh_persist)
      480 +                        smb2_dh_close_persistent(of);
      481 +                if (of->f_persistid != 0)
      482 +                        smb_ofile_del_persistid(of);
      483 +                if (of->f_lease != NULL)
      484 +                        smb2_lease_ofile_close(of);
      485 +                smb_oplock_break_CLOSE(of->f_node, of);
      486 +                /* FALLTHROUGH */
      487 +
      488 +        case SMB_FTYPE_PRINTER: /* or FTYPE_DISK */
 351  489                  /*
 352  490                   * In here we make changes to of->f_pending_attr
 353  491                   * while not holding of->f_mutex.  This is OK
 354  492                   * because we've changed f_state to CLOSING,
 355  493                   * so no more threads will take this path.
 356  494                   */
 357  495                  pa = &of->f_pending_attr;
 358  496                  if (mtime_sec != 0) {
 359  497                          pa->sa_vattr.va_mtime.tv_sec = mtime_sec;
 360  498                          pa->sa_mask |= SMB_AT_MTIME;
 361  499                  }
 362  500  
 363  501                  /*
 364  502                   * If we have ever modified data via this handle
 365  503                   * (write or truncate) and if the mtime was not
 366  504                   * set via this handle, update the mtime again
 367  505                   * during the close.  Windows expects this.
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
 368  506                   * [ MS-FSA 2.1.5.4 "Update Timestamps" ]
 369  507                   */
 370  508                  if (of->f_written &&
 371  509                      (pa->sa_mask & SMB_AT_MTIME) == 0) {
 372  510                          pa->sa_mask |= SMB_AT_MTIME;
 373  511                          gethrestime(&now);
 374  512                          pa->sa_vattr.va_mtime = now;
 375  513                  }
 376  514  
 377  515                  if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) {
 378      -                        if (smb_tree_has_feature(of->f_tree,
 379      -                            SMB_TREE_CATIA)) {
 380      -                                flags |= SMB_CATIA;
 381      -                        }
      516 +                        /* We delete using the on-disk name. */
      517 +                        uint32_t flags = SMB_CASE_SENSITIVE;
 382  518                          (void) smb_node_set_delete_on_close(of->f_node,
 383  519                              of->f_cr, flags);
 384  520                  }
 385  521                  smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid);
 386  522                  smb_node_destroy_lock_by_ofile(of->f_node, of);
 387  523  
 388  524                  if (smb_node_is_file(of->f_node)) {
 389  525                          (void) smb_fsop_close(of->f_node, of->f_mode,
 390  526                              of->f_cr);
 391      -                        smb_oplock_release(of->f_node, of);
 392  527                  } else {
 393  528                          /*
 394  529                           * If there was an odir, close it.
 395  530                           */
 396  531                          if (of->f_odir != NULL)
 397  532                                  smb_odir_close(of->f_odir);
      533 +                        /*
      534 +                         * Cancel any notify change requests that
      535 +                         * might be watching this open file (dir),
      536 +                         * and unsubscribe it from node events.
      537 +                         *
      538 +                         * Can't hold f_mutex when calling smb_notify_ofile.
      539 +                         * Don't really need it when unsubscribing, but
      540 +                         * harmless, and consistent with subscribing.
      541 +                         */
      542 +                        if (of->f_notify.nc_subscribed)
      543 +                                smb_notify_ofile(of,
      544 +                                    FILE_ACTION_HANDLE_CLOSED, NULL);
      545 +                        mutex_enter(&of->f_mutex);
      546 +                        if (of->f_notify.nc_subscribed) {
      547 +                                of->f_notify.nc_subscribed = B_FALSE;
      548 +                                smb_node_fcn_unsubscribe(of->f_node);
      549 +                                of->f_notify.nc_filter = 0;
      550 +                        }
      551 +                        mutex_exit(&of->f_mutex);
 398  552                  }
 399  553                  if (smb_node_dec_open_ofiles(of->f_node) == 0) {
 400  554                          /*
 401      -                         * Last close. The f_pending_attr has
 402      -                         * only times (atime,ctime,mtime) so
 403      -                         * we can borrow it to commit the
 404      -                         * n_pending_dosattr from the node.
      555 +                         * Last close.  If we're not deleting
      556 +                         * the file, apply any pending attrs.
      557 +                         * Leave allocsz zero when no open files,
      558 +                         * just to avoid confusion, because it's
      559 +                         * only updated when there are opens.
      560 +                         * XXX: Just do this on _every_ close.
 405  561                           */
 406      -                        pa->sa_dosattr =
 407      -                            of->f_node->n_pending_dosattr;
 408      -                        if (pa->sa_dosattr != 0)
 409      -                                pa->sa_mask |= SMB_AT_DOSATTR;
 410      -                        /* Let's leave this zero when not in use. */
      562 +                        mutex_enter(&of->f_node->n_mutex);
      563 +                        if (of->f_node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
      564 +                                smb_node_delete_on_close(of->f_node);
      565 +                                pa->sa_mask = 0;
      566 +                        }
 411  567                          of->f_node->n_allocsz = 0;
      568 +                        mutex_exit(&of->f_node->n_mutex);
 412  569                  }
 413  570                  if (pa->sa_mask != 0) {
 414  571                          /*
 415  572                           * Commit any pending attributes from
 416  573                           * the ofile we're closing.  Note that
 417  574                           * we pass NULL as the ofile to setattr
 418  575                           * so it will write to the file system
 419  576                           * and not keep anything on the ofile.
 420      -                         * This clears n_pending_dosattr if
 421      -                         * there are no opens, otherwise the
 422      -                         * dosattr will be pending again.
 423  577                           */
 424  578                          (void) smb_node_setattr(NULL, of->f_node,
 425  579                              of->f_cr, NULL, pa);
 426  580                  }
 427  581  
 428      -                /*
 429      -                 * Cancel any notify change requests that
 430      -                 * may be using this open instance.
 431      -                 */
 432      -                if (of->f_node->n_fcn.fcn_count)
 433      -                        smb_notify_file_closed(of);
 434      -
 435  582                  smb_server_dec_files(of->f_server);
 436  583                  break;
 437  584          }
 438      -        atomic_dec_32(&of->f_tree->t_open_files);
 439  585  
 440      -        mutex_enter(&of->f_mutex);
 441      -        ASSERT(of->f_refcnt);
 442      -        ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
 443      -        of->f_state = SMB_OFILE_STATE_CLOSED;
 444      -        mutex_exit(&of->f_mutex);
      586 +        /*
      587 +         * Keep f_state == SMB_OFILE_STATE_CLOSING
      588 +         * until the last ref. is dropped, in
      589 +         * smb_ofile_release()
      590 +         */
 445  591  }
 446  592  
 447  593  /*
 448      - * smb_ofile_close_all
      594 + * "Destructor" function for smb_ofile_close_all, and
      595 + * smb_ofile_close_all_by_pid, called after the llist lock
      596 + * for tree list has been exited.  Our job is to either
      597 + * close this ofile, or (if durable) set state _SAVE_DH.
 449  598   *
      599 + * The next interesting thing happens when the last ref.
      600 + * on this ofile calls smb_ofile_release(), where we
      601 + * eihter delete the ofile, or (if durable) leave it
      602 + * in the persistid hash table for possible reclaim.
 450  603   *
      604 + * This is run via smb_llist_post (after smb_llist_exit)
      605 + * because smb_ofile_close can block, and we'd rather not
      606 + * block while holding the ofile list as reader.
 451  607   */
 452      -void
 453      -smb_ofile_close_all(
 454      -    smb_tree_t          *tree)
      608 +static void
      609 +smb_ofile_drop(void *arg)
 455  610  {
 456      -        smb_ofile_t     *of;
      611 +        smb_ofile_t     *of = arg;
 457  612  
 458      -        ASSERT(tree);
 459      -        ASSERT(tree->t_magic == SMB_TREE_MAGIC);
      613 +        mutex_enter(&of->f_mutex);
      614 +        switch (of->f_state) {
      615 +        case SMB_OFILE_STATE_OPEN:
      616 +                /* DH checks under mutex. */
      617 +                if (of->f_ftype == SMB_FTYPE_DISK &&
      618 +                    of->dh_vers != SMB2_NOT_DURABLE &&
      619 +                    smb_dh_should_save(of)) {
      620 +                        /*
      621 +                         * Tell smb_ofile_release() to
      622 +                         * make this an _ORPHANED DH.
      623 +                         */
      624 +                        of->f_state = SMB_OFILE_STATE_SAVE_DH;
      625 +                        mutex_exit(&of->f_mutex);
      626 +                        break;
      627 +                }
      628 +                /* OK close it. */
      629 +                mutex_exit(&of->f_mutex);
      630 +                smb_ofile_close(of, 0);
      631 +                break;
 460  632  
 461      -        smb_llist_enter(&tree->t_ofile_list, RW_READER);
 462      -        of = smb_llist_head(&tree->t_ofile_list);
 463      -        while (of) {
 464      -                ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 465      -                ASSERT(of->f_tree == tree);
 466      -                of = smb_ofile_close_and_next(of);
      633 +        default:
      634 +                /* Something else closed it already. */
      635 +                mutex_exit(&of->f_mutex);
      636 +                break;
 467  637          }
 468      -        smb_llist_exit(&tree->t_ofile_list);
      638 +
      639 +        /*
      640 +         * Release the ref acquired during the traversal loop.
      641 +         * Note that on the last ref, this ofile will be
      642 +         * removed from the tree list etc.
      643 +         * See: smb_llist_post, smb_ofile_delete
      644 +         */
      645 +        smb_ofile_release(of);
 469  646  }
 470  647  
 471  648  /*
 472      - * smb_ofiles_close_by_pid
      649 + * smb_ofile_close_all
 473  650   *
 474  651   *
 475  652   */
 476  653  void
 477      -smb_ofile_close_all_by_pid(
      654 +smb_ofile_close_all(
 478  655      smb_tree_t          *tree,
 479      -    uint16_t            pid)
      656 +    uint32_t            pid)
 480  657  {
 481  658          smb_ofile_t     *of;
      659 +        smb_llist_t     *ll;
 482  660  
 483  661          ASSERT(tree);
 484  662          ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 485  663  
 486      -        smb_llist_enter(&tree->t_ofile_list, RW_READER);
 487      -        of = smb_llist_head(&tree->t_ofile_list);
 488      -        while (of) {
      664 +        ll = &tree->t_ofile_list;
      665 +
      666 +        smb_llist_enter(ll, RW_READER);
      667 +        for (of = smb_llist_head(ll);
      668 +            of != NULL;
      669 +            of = smb_llist_next(ll, of)) {
 489  670                  ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 490  671                  ASSERT(of->f_tree == tree);
 491      -                if (of->f_opened_by_pid == pid) {
 492      -                        of = smb_ofile_close_and_next(of);
 493      -                } else {
 494      -                        of = smb_llist_next(&tree->t_ofile_list, of);
      672 +                if (pid != 0 && of->f_opened_by_pid != pid)
      673 +                        continue;
      674 +                if (smb_ofile_hold(of)) {
      675 +                        smb_llist_post(ll, of, smb_ofile_drop);
 495  676                  }
 496  677          }
 497      -        smb_llist_exit(&tree->t_ofile_list);
      678 +
      679 +        /*
      680 +         * Drop the lock and process the llist dtor queue.
      681 +         * Calls smb_ofile_drop on ofiles that were open.
      682 +         */
      683 +        smb_llist_exit(ll);
 498  684  }
 499  685  
 500  686  /*
 501  687   * If the enumeration request is for ofile data, handle it here.
 502  688   * Otherwise, return.
 503  689   *
 504  690   * This function should be called with a hold on the ofile.
 505  691   */
 506  692  int
 507  693  smb_ofile_enum(smb_ofile_t *of, smb_svcenum_t *svcenum)
 508  694  {
 509  695          uint8_t *pb;
 510  696          uint_t nbytes;
 511  697          int rc;
 512  698  
 513  699          ASSERT(of);
 514  700          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 515  701          ASSERT(of->f_refcnt);
 516  702  
 517  703          if (svcenum->se_type != SMB_SVCENUM_TYPE_FILE)
 518  704                  return (0);
 519  705  
 520  706          if (svcenum->se_nskip > 0) {
 521  707                  svcenum->se_nskip--;
 522  708                  return (0);
 523  709          }
 524  710  
 525  711          if (svcenum->se_nitems >= svcenum->se_nlimit) {
 526  712                  svcenum->se_nitems = svcenum->se_nlimit;
 527  713                  return (0);
 528  714          }
 529  715  
 530  716          pb = &svcenum->se_buf[svcenum->se_bused];
 531  717  
 532  718          rc = smb_ofile_netinfo_encode(of, pb, svcenum->se_bavail,
 533  719              &nbytes);
  
    | 
      ↓ open down ↓ | 
    26 lines elided | 
    
      ↑ open up ↑ | 
  
 534  720          if (rc == 0) {
 535  721                  svcenum->se_bavail -= nbytes;
 536  722                  svcenum->se_bused += nbytes;
 537  723                  svcenum->se_nitems++;
 538  724          }
 539  725  
 540  726          return (rc);
 541  727  }
 542  728  
 543  729  /*
      730 + * Take a reference on an open file, in any of the states:
      731 + *   RECONNECT, SAVE_DH, OPEN, ORPHANED.
      732 + * Return TRUE if ref taken.  Used for oplock breaks.
      733 + *
      734 + * Note: When the oplock break code calls this, it holds the
      735 + * node ofile list lock and node oplock mutex.  When we see
      736 + * an ofile in states RECONNECT or SAVING, we know the ofile
      737 + * is gaining or losing it's tree, and that happens quickly,
      738 + * so we just wait for that work to finish.  However, the
      739 + * waiting for state transitions here means we have to be
      740 + * careful not to re-enter the node list lock or otherwise
      741 + * block on things that could cause a deadlock.  Waiting
      742 + * just on of->f_mutex here is OK.
      743 + */
      744 +boolean_t
      745 +smb_ofile_hold_olbrk(smb_ofile_t *of)
      746 +{
      747 +        boolean_t ret = B_FALSE;
      748 +
      749 +        ASSERT(of);
      750 +        ASSERT(of->f_magic == SMB_OFILE_MAGIC);
      751 +
      752 +        mutex_enter(&of->f_mutex);
      753 +
      754 +again:
      755 +        switch (of->f_state) {
      756 +        case SMB_OFILE_STATE_RECONNECT:
      757 +        case SMB_OFILE_STATE_SAVING:
      758 +                cv_wait(&of->f_cv, &of->f_mutex);
      759 +                goto again;
      760 +
      761 +        case SMB_OFILE_STATE_OPEN:
      762 +        case SMB_OFILE_STATE_ORPHANED:
      763 +        case SMB_OFILE_STATE_SAVE_DH:
      764 +                of->f_refcnt++;
      765 +                ret = B_TRUE;
      766 +                break;
      767 +
      768 +        default:
      769 +                break;
      770 +        }
      771 +        mutex_exit(&of->f_mutex);
      772 +
      773 +        return (ret);
      774 +}
      775 +
      776 +/*
 544  777   * Take a reference on an open file.
 545  778   */
 546  779  boolean_t
 547  780  smb_ofile_hold(smb_ofile_t *of)
 548  781  {
 549  782          ASSERT(of);
 550  783          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 551  784  
 552  785          mutex_enter(&of->f_mutex);
 553  786  
 554  787          if (of->f_state != SMB_OFILE_STATE_OPEN) {
 555  788                  mutex_exit(&of->f_mutex);
 556  789                  return (B_FALSE);
 557  790          }
 558  791          of->f_refcnt++;
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
 559  792  
 560  793          mutex_exit(&of->f_mutex);
 561  794          return (B_TRUE);
 562  795  }
 563  796  
 564  797  /*
 565  798   * Release a reference on a file.  If the reference count falls to
 566  799   * zero and the file has been closed, post the object for deletion.
 567  800   * Object deletion is deferred to avoid modifying a list while an
 568  801   * iteration may be in progress.
      802 + *
      803 + * We're careful to avoid dropping f_session etc. until the last
      804 + * reference goes away.  The oplock break code depends on that
      805 + * not changing while it holds a ref. on an ofile.
 569  806   */
 570  807  void
 571  808  smb_ofile_release(smb_ofile_t *of)
 572  809  {
      810 +        smb_tree_t *tree = of->f_tree;
      811 +        boolean_t delete = B_FALSE;
      812 +
 573  813          SMB_OFILE_VALID(of);
 574  814  
 575  815          mutex_enter(&of->f_mutex);
 576      -        ASSERT(of->f_refcnt);
      816 +        ASSERT(of->f_refcnt > 0);
 577  817          of->f_refcnt--;
      818 +
 578  819          switch (of->f_state) {
 579  820          case SMB_OFILE_STATE_OPEN:
 580      -        case SMB_OFILE_STATE_CLOSING:
      821 +        case SMB_OFILE_STATE_ORPHANED:
      822 +        case SMB_OFILE_STATE_EXPIRED:
 581  823                  break;
 582  824  
 583      -        case SMB_OFILE_STATE_CLOSED:
 584      -                if (of->f_refcnt == 0)
 585      -                        smb_tree_post_ofile(of->f_tree, of);
      825 +        case SMB_OFILE_STATE_SAVE_DH:
      826 +                ASSERT(tree != NULL);
      827 +                if (of->f_refcnt == 0) {
      828 +                        of->f_state = SMB_OFILE_STATE_SAVING;
      829 +                        smb_llist_post(&tree->t_ofile_list, of,
      830 +                            smb_ofile_save_dh);
      831 +                }
 586  832                  break;
 587  833  
      834 +        case SMB_OFILE_STATE_CLOSING:
      835 +                /* Note, tree == NULL on _ORPHANED */
      836 +                if (of->f_refcnt == 0) {
      837 +                        of->f_state = SMB_OFILE_STATE_CLOSED;
      838 +                        if (tree == NULL) {
      839 +                                /* Skip smb_llist_post */
      840 +                                delete = B_TRUE;
      841 +                                break;
      842 +                        }
      843 +                        smb_llist_post(&tree->t_ofile_list, of,
      844 +                            smb_ofile_delete);
      845 +                }
      846 +                break;
      847 +
 588  848          default:
 589  849                  ASSERT(0);
 590  850                  break;
 591  851          }
 592  852          mutex_exit(&of->f_mutex);
 593      -}
 594  853  
 595      -/*
 596      - * smb_ofile_request_complete
 597      - *
 598      - * During oplock acquisition, all other oplock requests on the node
 599      - * are blocked until the acquire request completes and the response
 600      - * is on the wire.
 601      - * Call smb_oplock_broadcast to notify the node that the request
 602      - * has completed.
 603      - *
 604      - * THIS MECHANISM RELIES ON THE FACT THAT THE OFILE IS NOT REMOVED
 605      - * FROM THE SR UNTIL REQUEST COMPLETION (when the sr is destroyed)
 606      - */
 607      -void
 608      -smb_ofile_request_complete(smb_ofile_t *of)
 609      -{
 610      -        SMB_OFILE_VALID(of);
 611      -
 612      -        switch (of->f_ftype) {
 613      -        case SMB_FTYPE_DISK:
 614      -                ASSERT(of->f_node);
 615      -                smb_oplock_broadcast(of->f_node);
 616      -                break;
 617      -        case SMB_FTYPE_MESG_PIPE:
 618      -                break;
 619      -        default:
 620      -                break;
      854 +        /*
      855 +         * When we drop the last ref. on an expired DH, it's no longer
      856 +         * in any tree, so skip the smb_llist_post and just call
      857 +         * smb_ofile_delete directly.
      858 +         */
      859 +        if (delete) {
      860 +                smb_ofile_delete(of);
 621  861          }
 622  862  }
 623  863  
 624  864  /*
 625  865   * smb_ofile_lookup_by_fid
 626  866   *
 627  867   * Find the open file whose fid matches the one specified in the request.
 628  868   * If we can't find the fid or the shares (trees) don't match, we have a
 629  869   * bad fid.
 630  870   */
 631  871  smb_ofile_t *
 632  872  smb_ofile_lookup_by_fid(
 633  873      smb_request_t       *sr,
 634  874      uint16_t            fid)
 635  875  {
 636  876          smb_tree_t      *tree = sr->tid_tree;
 637  877          smb_llist_t     *of_list;
 638  878          smb_ofile_t     *of;
 639  879  
 640  880          ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 641  881  
 642  882          of_list = &tree->t_ofile_list;
 643  883  
 644  884          smb_llist_enter(of_list, RW_READER);
 645  885          of = smb_llist_head(of_list);
 646  886          while (of) {
 647  887                  ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 648  888                  ASSERT(of->f_tree == tree);
 649  889                  if (of->f_fid == fid)
 650  890                          break;
 651  891                  of = smb_llist_next(of_list, of);
 652  892          }
 653  893          if (of == NULL)
 654  894                  goto out;
  
    | 
      ↓ open down ↓ | 
    24 lines elided | 
    
      ↑ open up ↑ | 
  
 655  895  
 656  896          /*
 657  897           * Only allow use of a given FID with the same UID that
 658  898           * was used to open it.  MS-CIFS 3.3.5.14
 659  899           */
 660  900          if (of->f_user != sr->uid_user) {
 661  901                  of = NULL;
 662  902                  goto out;
 663  903          }
 664  904  
      905 +        /* inline smb_ofile_hold() */
 665  906          mutex_enter(&of->f_mutex);
 666  907          if (of->f_state != SMB_OFILE_STATE_OPEN) {
 667  908                  mutex_exit(&of->f_mutex);
 668  909                  of = NULL;
 669  910                  goto out;
 670  911          }
 671  912          of->f_refcnt++;
 672  913          mutex_exit(&of->f_mutex);
 673  914  
 674  915  out:
 675  916          smb_llist_exit(of_list);
 676  917          return (of);
 677  918  }
 678  919  
 679  920  /*
 680  921   * smb_ofile_lookup_by_uniqid
 681  922   *
 682  923   * Find the open file whose uniqid matches the one specified in the request.
 683  924   */
 684  925  smb_ofile_t *
 685  926  smb_ofile_lookup_by_uniqid(smb_tree_t *tree, uint32_t uniqid)
 686  927  {
 687  928          smb_llist_t     *of_list;
 688  929          smb_ofile_t     *of;
 689  930  
 690  931          ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 691  932  
 692  933          of_list = &tree->t_ofile_list;
 693  934          smb_llist_enter(of_list, RW_READER);
 694  935          of = smb_llist_head(of_list);
 695  936  
 696  937          while (of) {
 697  938                  ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 698  939                  ASSERT(of->f_tree == tree);
 699  940  
 700  941                  if (of->f_uniqid == uniqid) {
 701  942                          if (smb_ofile_hold(of)) {
 702  943                                  smb_llist_exit(of_list);
 703  944                                  return (of);
 704  945                          }
  
    | 
      ↓ open down ↓ | 
    30 lines elided | 
    
      ↑ open up ↑ | 
  
 705  946                  }
 706  947  
 707  948                  of = smb_llist_next(of_list, of);
 708  949          }
 709  950  
 710  951          smb_llist_exit(of_list);
 711  952          return (NULL);
 712  953  }
 713  954  
 714  955  /*
      956 + * Durable ID (or persistent ID)
      957 + */
      958 +
      959 +static smb_ofile_t *
      960 +smb_ofile_hold_cb(smb_ofile_t *of)
      961 +{
      962 +        smb_ofile_t *ret = of;
      963 +
      964 +        mutex_enter(&of->f_mutex);
      965 +        if (of->f_state == SMB_OFILE_STATE_ORPHANED)
      966 +                /* inline smb_ofile_hold() */
      967 +                of->f_refcnt++;
      968 +        else
      969 +                ret = NULL;
      970 +
      971 +        mutex_exit(&of->f_mutex);
      972 +        return (ret);
      973 +}
      974 +
      975 +/*
      976 + * Lookup an ofile by persistent ID, and return ONLY if in state ORPHANED
      977 + * This is used by SMB2 create "reclaim".
      978 + */
      979 +smb_ofile_t *
      980 +smb_ofile_lookup_by_persistid(smb_request_t *sr, uint64_t persistid)
      981 +{
      982 +        smb_hash_t *hash;
      983 +        smb_bucket_t *bucket;
      984 +        smb_llist_t *ll;
      985 +        smb_ofile_t *of;
      986 +        uint_t idx;
      987 +
      988 +        if (persistid == 0)
      989 +                return (NULL);
      990 +
      991 +        hash = sr->sr_server->sv_persistid_ht;
      992 +        idx = smb_hash_uint64(hash, persistid);
      993 +        bucket = &hash->buckets[idx];
      994 +        ll = &bucket->b_list;
      995 +
      996 +        smb_llist_enter(ll, RW_READER);
      997 +        of = smb_llist_head(ll);
      998 +        while (of != NULL) {
      999 +                if (of->f_persistid == persistid)
     1000 +                        break;
     1001 +                of = smb_llist_next(ll, of);
     1002 +        }
     1003 +        if (of != NULL)
     1004 +                of = smb_ofile_hold_cb(of);
     1005 +        smb_llist_exit(ll);
     1006 +
     1007 +        return (of);
     1008 +}
     1009 +
     1010 +/*
     1011 + * Create a (unique) durable/persistent ID for a new ofile,
     1012 + * and add this ofile to the persistid hash table.  This ID
     1013 + * is referred to as the persistent ID in the protocol spec,
     1014 + * so that's what we call it too, though the persistence may
     1015 + * vary.  "Durable" handles are persistent across reconnects
     1016 + * but not server reboots.  Persistent handles are persistent
     1017 + * across server reboots too.
     1018 + *
     1019 + * Note that persistent IDs need to be unique for the lifetime of
     1020 + * any given ofile.  For normal (non-persistent) ofiles we can just
     1021 + * use a persistent ID derived from the ofile memory address, as
     1022 + * these don't ever live beyond the current OS boot lifetime.
     1023 + *
     1024 + * Persistent handles are re-imported after server restart, and
     1025 + * generally have a different memory address after import than
     1026 + * they had in the previous OS boot lifetime, so for these we
     1027 + * use a randomly assigned value that won't conflict with any
     1028 + * non-persistent (durable) handles.  Ensuring that a randomly
     1029 + * generated ID is unique requres a search of the ofiles in one
     1030 + * hash bucket, which we'd rather avoid for non-persistent opens.
     1031 + *
     1032 + * The solution used here is to divide the persistent ID space
     1033 + * in half (odd and even values) where durable opens use an ID
     1034 + * derived from the ofile address (which is always even), and
     1035 + * persistent opens use an ID generated randomly (always odd).
     1036 + *
     1037 + * smb_ofile_set_persistid_dh() sets a durable handle ID and
     1038 + * smb_ofile_set_persistid_ph() sets a persistent handle ID.
     1039 + */
     1040 +void
     1041 +smb_ofile_set_persistid_dh(smb_ofile_t *of)
     1042 +{
     1043 +        smb_hash_t *hash = of->f_server->sv_persistid_ht;
     1044 +        smb_bucket_t *bucket;
     1045 +        smb_llist_t *ll;
     1046 +        uint64_t persistid;
     1047 +        uint_t idx;
     1048 +
     1049 +        persistid = (uintptr_t)of;
     1050 +        /* Avoid showing object addresses */
     1051 +        persistid ^= ((uintptr_t)&smb_cache_ofile);
     1052 +        /* make sure it's even */
     1053 +        persistid &= ~((uint64_t)1);
     1054 +
     1055 +        idx = smb_hash_uint64(hash, persistid);
     1056 +        bucket = &hash->buckets[idx];
     1057 +        ll = &bucket->b_list;
     1058 +        smb_llist_enter(ll, RW_WRITER);
     1059 +        if (of->f_persistid == 0) {
     1060 +                of->f_persistid = persistid;
     1061 +                smb_llist_insert_tail(ll, of);
     1062 +        }
     1063 +        smb_llist_exit(ll);
     1064 +}
     1065 +
     1066 +void
     1067 +smb_ofile_set_persistid_ph(smb_ofile_t *of)
     1068 +{
     1069 +        uint64_t persistid;
     1070 +        int rc;
     1071 +
     1072 +top:
     1073 +        (void) random_get_pseudo_bytes((uint8_t *)&persistid,
     1074 +            sizeof (persistid));
     1075 +        if (persistid == 0) {
     1076 +                cmn_err(CE_NOTE, "random gave all zeros!");
     1077 +                goto top;
     1078 +        }
     1079 +        /* make sure it's odd */
     1080 +        persistid |= (uint64_t)1;
     1081 +
     1082 +        /*
     1083 +         * Try inserting with this persistent ID.
     1084 +         */
     1085 +        rc = smb_ofile_insert_persistid(of, persistid);
     1086 +        if (rc == EEXIST)
     1087 +                goto top;
     1088 +        if (rc != 0) {
     1089 +                cmn_err(CE_NOTE, "set persistid rc=%d", rc);
     1090 +        }
     1091 +}
     1092 +
     1093 +/*
     1094 + * Insert an ofile into the persistid hash table.
     1095 + * If the persistent ID is in use, error.
     1096 + */
     1097 +int
     1098 +smb_ofile_insert_persistid(smb_ofile_t *new_of, uint64_t persistid)
     1099 +{
     1100 +        smb_hash_t *hash = new_of->f_server->sv_persistid_ht;
     1101 +        smb_bucket_t *bucket;
     1102 +        smb_llist_t *ll;
     1103 +        smb_ofile_t *of;
     1104 +        uint_t idx;
     1105 +
     1106 +        ASSERT(persistid != 0);
     1107 +
     1108 +        /*
     1109 +         * Look to see if this key alreay exists.
     1110 +         */
     1111 +        idx = smb_hash_uint64(hash, persistid);
     1112 +        bucket = &hash->buckets[idx];
     1113 +        ll = &bucket->b_list;
     1114 +
     1115 +        smb_llist_enter(ll, RW_WRITER);
     1116 +        of = smb_llist_head(ll);
     1117 +        while (of != NULL) {
     1118 +                if (of->f_persistid == persistid) {
     1119 +                        /* already in use */
     1120 +                        smb_llist_exit(ll);
     1121 +                        return (EEXIST);
     1122 +                }
     1123 +                of = smb_llist_next(ll, of);
     1124 +        }
     1125 +
     1126 +        /* Not found, so OK to insert. */
     1127 +        if (new_of->f_persistid == 0) {
     1128 +                new_of->f_persistid = persistid;
     1129 +                smb_llist_insert_tail(ll, new_of);
     1130 +        }
     1131 +        smb_llist_exit(ll);
     1132 +
     1133 +        return (0);
     1134 +}
     1135 +
     1136 +void
     1137 +smb_ofile_del_persistid(smb_ofile_t *of)
     1138 +{
     1139 +        smb_hash_t *hash = of->f_server->sv_persistid_ht;
     1140 +        smb_bucket_t *bucket;
     1141 +        smb_llist_t *ll;
     1142 +        uint_t idx;
     1143 +
     1144 +        idx = smb_hash_uint64(hash, of->f_persistid);
     1145 +        bucket = &hash->buckets[idx];
     1146 +        ll = &bucket->b_list;
     1147 +        smb_llist_enter(ll, RW_WRITER);
     1148 +        if (of->f_persistid != 0) {
     1149 +                smb_llist_remove(ll, of);
     1150 +                of->f_persistid = 0;
     1151 +        }
     1152 +        smb_llist_exit(ll);
     1153 +}
     1154 +
     1155 +
     1156 +/*
 715 1157   * Disallow NetFileClose on certain ofiles to avoid side-effects.
 716 1158   * Closing a tree root is not allowed: use NetSessionDel or NetShareDel.
 717 1159   * Closing SRVSVC connections is not allowed because this NetFileClose
 718 1160   * request may depend on this ofile.
 719 1161   */
 720 1162  boolean_t
 721 1163  smb_ofile_disallow_fclose(smb_ofile_t *of)
 722 1164  {
 723 1165          ASSERT(of);
 724 1166          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 725 1167          ASSERT(of->f_refcnt);
 726 1168  
 727 1169          switch (of->f_ftype) {
 728 1170          case SMB_FTYPE_DISK:
 729 1171                  ASSERT(of->f_tree);
 730 1172                  return (of->f_node == of->f_tree->t_snode);
 731 1173  
 732 1174          case SMB_FTYPE_MESG_PIPE:
 733 1175                  ASSERT(of->f_pipe);
 734 1176                  if (smb_strcasecmp(of->f_pipe->p_name, "SRVSVC", 0) == 0)
 735 1177                          return (B_TRUE);
 736 1178                  break;
 737 1179          default:
 738 1180                  break;
 739 1181          }
 740 1182  
 741 1183          return (B_FALSE);
 742 1184  }
 743 1185  
 744 1186  /*
 745 1187   * smb_ofile_set_flags
 746 1188   *
 747 1189   * Return value:
 748 1190   *
 749 1191   *      Current flags value
 750 1192   *
 751 1193   */
 752 1194  void
 753 1195  smb_ofile_set_flags(
 754 1196      smb_ofile_t         *of,
 755 1197      uint32_t            flags)
 756 1198  {
 757 1199          ASSERT(of);
 758 1200          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 759 1201          ASSERT(of->f_refcnt);
 760 1202  
 761 1203          mutex_enter(&of->f_mutex);
 762 1204          of->f_flags |= flags;
 763 1205          mutex_exit(&of->f_mutex);
 764 1206  }
 765 1207  
 766 1208  /*
 767 1209   * smb_ofile_seek
 768 1210   *
 769 1211   * Return value:
 770 1212   *
 771 1213   *      0               Success
 772 1214   *      EINVAL          Unknown mode
 773 1215   *      EOVERFLOW       offset too big
 774 1216   *
 775 1217   */
 776 1218  int
 777 1219  smb_ofile_seek(
 778 1220      smb_ofile_t         *of,
 779 1221      ushort_t            mode,
 780 1222      int32_t             off,
 781 1223      uint32_t            *retoff)
 782 1224  {
 783 1225          u_offset_t      newoff = 0;
 784 1226          int             rc = 0;
 785 1227          smb_attr_t      attr;
 786 1228  
 787 1229          ASSERT(of);
 788 1230          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 789 1231          ASSERT(of->f_refcnt);
 790 1232  
 791 1233          mutex_enter(&of->f_mutex);
 792 1234          switch (mode) {
 793 1235          case SMB_SEEK_SET:
 794 1236                  if (off < 0)
 795 1237                          newoff = 0;
 796 1238                  else
 797 1239                          newoff = (u_offset_t)off;
 798 1240                  break;
 799 1241  
 800 1242          case SMB_SEEK_CUR:
 801 1243                  if (off < 0 && (-off) > of->f_seek_pos)
 802 1244                          newoff = 0;
 803 1245                  else
 804 1246                          newoff = of->f_seek_pos + (u_offset_t)off;
 805 1247                  break;
 806 1248  
 807 1249          case SMB_SEEK_END:
 808 1250                  bzero(&attr, sizeof (smb_attr_t));
 809 1251                  attr.sa_mask |= SMB_AT_SIZE;
 810 1252                  rc = smb_fsop_getattr(NULL, zone_kcred(), of->f_node, &attr);
 811 1253                  if (rc != 0) {
 812 1254                          mutex_exit(&of->f_mutex);
 813 1255                          return (rc);
 814 1256                  }
 815 1257                  if (off < 0 && (-off) > attr.sa_vattr.va_size)
 816 1258                          newoff = 0;
 817 1259                  else
 818 1260                          newoff = attr.sa_vattr.va_size + (u_offset_t)off;
 819 1261                  break;
 820 1262  
 821 1263          default:
 822 1264                  mutex_exit(&of->f_mutex);
 823 1265                  return (EINVAL);
 824 1266          }
 825 1267  
 826 1268          /*
 827 1269           * See comments at the beginning of smb_seek.c.
 828 1270           * If the offset is greater than UINT_MAX, we will return an error.
 829 1271           */
 830 1272  
 831 1273          if (newoff > UINT_MAX) {
 832 1274                  rc = EOVERFLOW;
 833 1275          } else {
 834 1276                  of->f_seek_pos = newoff;
 835 1277                  *retoff = (uint32_t)newoff;
 836 1278          }
 837 1279          mutex_exit(&of->f_mutex);
 838 1280          return (rc);
 839 1281  }
 840 1282  
 841 1283  /*
 842 1284   * smb_ofile_flush
 843 1285   *
 844 1286   * If writes on this file are not synchronous, flush it using the NFSv3
 845 1287   * commit interface.
 846 1288   *
 847 1289   * XXX - todo: Flush named pipe should drain writes.
 848 1290   */
 849 1291  void
 850 1292  smb_ofile_flush(struct smb_request *sr, struct smb_ofile *of)
 851 1293  {
 852 1294          switch (of->f_ftype) {
 853 1295          case SMB_FTYPE_DISK:
 854 1296                  if ((of->f_node->flags & NODE_FLAGS_WRITE_THROUGH) == 0)
 855 1297                          (void) smb_fsop_commit(sr, of->f_cr, of->f_node);
 856 1298                  break;
 857 1299          default:
 858 1300                  break;
 859 1301          }
 860 1302  }
 861 1303  
 862 1304  /*
 863 1305   * smb_ofile_is_open
 864 1306   */
 865 1307  boolean_t
 866 1308  smb_ofile_is_open(smb_ofile_t *of)
 867 1309  {
 868 1310          boolean_t       rc;
 869 1311  
 870 1312          SMB_OFILE_VALID(of);
 871 1313  
 872 1314          mutex_enter(&of->f_mutex);
 873 1315          rc = smb_ofile_is_open_locked(of);
 874 1316          mutex_exit(&of->f_mutex);
 875 1317          return (rc);
 876 1318  }
  
    | 
      ↓ open down ↓ | 
    152 lines elided | 
    
      ↑ open up ↑ | 
  
 877 1319  
 878 1320  /* *************************** Static Functions ***************************** */
 879 1321  
 880 1322  /*
 881 1323   * Determine whether or not an ofile is open.
 882 1324   * This function must be called with the mutex held.
 883 1325   */
 884 1326  static boolean_t
 885 1327  smb_ofile_is_open_locked(smb_ofile_t *of)
 886 1328  {
     1329 +        ASSERT(MUTEX_HELD(&of->f_mutex));
     1330 +
 887 1331          switch (of->f_state) {
 888 1332          case SMB_OFILE_STATE_OPEN:
     1333 +        case SMB_OFILE_STATE_SAVE_DH:
     1334 +        case SMB_OFILE_STATE_SAVING:
     1335 +        case SMB_OFILE_STATE_ORPHANED:
     1336 +        case SMB_OFILE_STATE_RECONNECT:
 889 1337                  return (B_TRUE);
 890 1338  
 891 1339          case SMB_OFILE_STATE_CLOSING:
 892 1340          case SMB_OFILE_STATE_CLOSED:
     1341 +        case SMB_OFILE_STATE_EXPIRED:
 893 1342                  return (B_FALSE);
 894 1343  
 895 1344          default:
 896 1345                  ASSERT(0);
 897 1346                  return (B_FALSE);
 898 1347          }
 899 1348  }
 900 1349  
 901 1350  /*
 902      - * This function closes the file passed in (if appropriate) and returns the
 903      - * next open file in the list of open files of the tree of the open file passed
 904      - * in. It requires that the list of open files of the tree be entered in
 905      - * RW_READER mode before being called.
     1351 + * smb_ofile_save_dh
     1352 + *
     1353 + * Called via smb_llist_post (after smb_llist_exit) when the last ref.
     1354 + * on this ofile has gone, and this ofile is a "durable handle" (DH)
     1355 + * that has state we've decided to save.
     1356 + *
     1357 + * This does parts of what smb_ofile_delete would do, including:
     1358 + * remove the ofile from the tree ofile list and related.
     1359 + *
     1360 + * We leave the ofile in state ORPHANED, ready for reconnect
     1361 + * or expiration via smb2_dh_expire (see smb_ofile_delete).
 906 1362   */
 907      -static smb_ofile_t *
 908      -smb_ofile_close_and_next(smb_ofile_t *of)
     1363 +static void
     1364 +smb_ofile_save_dh(void *arg)
 909 1365  {
 910      -        smb_ofile_t     *next_of;
 911      -        smb_tree_t      *tree;
     1366 +        smb_ofile_t     *of = (smb_ofile_t *)arg;
     1367 +        smb_tree_t      *tree = of->f_tree;
 912 1368  
 913      -        ASSERT(of);
 914      -        ASSERT(of->f_magic == SMB_OFILE_MAGIC);
     1369 +        SMB_OFILE_VALID(of);
     1370 +        ASSERT(of->f_refcnt == 0);
     1371 +        ASSERT(of->f_ftype == SMB_FTYPE_DISK);
     1372 +        ASSERT(of->f_state == SMB_OFILE_STATE_SAVING);
 915 1373  
     1374 +        atomic_dec_32(&of->f_session->s_file_cnt);
     1375 +        atomic_dec_32(&of->f_tree->t_open_files);
     1376 +        smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
     1377 +        smb_llist_remove(&tree->t_ofile_list, of);
     1378 +        smb_llist_exit(&tree->t_ofile_list);
     1379 +
     1380 +        /*
     1381 +         * This ofile is no longer on t_ofile_list, however...
     1382 +         *
     1383 +         * This is called via smb_llist_post, which means it may run
     1384 +         * BEFORE smb_ofile_release drops f_mutex (if another thread
     1385 +         * flushes the delete queue before we do).  Synchronize.
     1386 +         */
 916 1387          mutex_enter(&of->f_mutex);
 917      -        switch (of->f_state) {
 918      -        case SMB_OFILE_STATE_OPEN:
 919      -                /* The file is still open. */
 920      -                of->f_refcnt++;
 921      -                ASSERT(of->f_refcnt);
 922      -                tree = of->f_tree;
 923      -                mutex_exit(&of->f_mutex);
 924      -                smb_llist_exit(&of->f_tree->t_ofile_list);
 925      -                smb_ofile_close(of, 0);
 926      -                smb_ofile_release(of);
 927      -                smb_llist_enter(&tree->t_ofile_list, RW_READER);
 928      -                next_of = smb_llist_head(&tree->t_ofile_list);
 929      -                break;
 930      -        case SMB_OFILE_STATE_CLOSING:
 931      -        case SMB_OFILE_STATE_CLOSED:
 932      -                /*
 933      -                 * The ofile exists but is closed or
 934      -                 * in the process being closed.
 935      -                 */
 936      -                mutex_exit(&of->f_mutex);
 937      -                next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
 938      -                break;
 939      -        default:
 940      -                ASSERT(0);
 941      -                mutex_exit(&of->f_mutex);
 942      -                next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
 943      -                break;
 944      -        }
 945      -        return (next_of);
     1388 +        DTRACE_PROBE1(ofile__exit, smb_ofile_t, of);
     1389 +        mutex_exit(&of->f_mutex);
     1390 +
     1391 +        /*
     1392 +         * Keep f_notify state, lease, and
     1393 +         * keep on node ofile list.
     1394 +         * Keep of->f_cr until reclaim.
     1395 +         */
     1396 +
     1397 +        ASSERT(of->f_fid != 0);
     1398 +        smb_idpool_free(&tree->t_fid_pool, of->f_fid);
     1399 +        of->f_fid = 0;
     1400 +        smb_tree_release(of->f_tree);
     1401 +        of->f_tree = NULL;
     1402 +        smb_user_release(of->f_user);
     1403 +        of->f_user = NULL;
     1404 +        of->f_session = NULL;
     1405 +
     1406 +        /*
     1407 +         * Make it "orphaned" so it can now be reclaimed.
     1408 +         * Note that smb_ofile_hold_olbrk() may have blocked
     1409 +         * for state SMB_OFILE_STATE_SAVING, so wake it.
     1410 +         */
     1411 +        mutex_enter(&of->f_mutex);
     1412 +        of->dh_expire_time = gethrtime() + of->dh_timeout_offset;
     1413 +        of->f_state = SMB_OFILE_STATE_ORPHANED;
     1414 +        cv_broadcast(&of->f_cv);
     1415 +        mutex_exit(&of->f_mutex);
 946 1416  }
 947 1417  
 948 1418  /*
 949 1419   * Delete an ofile.
 950 1420   *
 951      - * Remove the ofile from the tree list before freeing resources
 952      - * associated with the ofile.
     1421 + * Approximately the inverse of smb_ofile_alloc()
     1422 + * Called via smb_llist_post (after smb_llist_exit)
     1423 + * when the last ref. on this ofile has gone.
     1424 + *
     1425 + * Normally,this removes the ofile from the tree list and
     1426 + * then frees resources held on the ofile.  However, when
     1427 + * we're expiring an orphaned durable handle, the linkage
     1428 + * into the tree lists etc. have already been destroyed.
     1429 + * This case is distinguished by of->f_tree == NULL.
 953 1430   */
 954      -void
     1431 +static void
 955 1432  smb_ofile_delete(void *arg)
 956 1433  {
 957      -        smb_tree_t      *tree;
 958 1434          smb_ofile_t     *of = (smb_ofile_t *)arg;
     1435 +        smb_tree_t      *tree = of->f_tree;
 959 1436  
 960 1437          SMB_OFILE_VALID(of);
 961 1438          ASSERT(of->f_refcnt == 0);
 962 1439          ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
 963      -        ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of));
 964 1440  
 965      -        tree = of->f_tree;
 966      -        smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
 967      -        smb_llist_remove(&tree->t_ofile_list, of);
 968      -        smb_idpool_free(&tree->t_fid_pool, of->f_fid);
 969      -        atomic_dec_32(&tree->t_session->s_file_cnt);
 970      -        smb_llist_exit(&tree->t_ofile_list);
     1441 +        if (tree != NULL) {
     1442 +                ASSERT(of->f_user != NULL);
     1443 +                ASSERT(of->f_session != NULL);
     1444 +                atomic_dec_32(&of->f_session->s_file_cnt);
     1445 +                atomic_dec_32(&of->f_tree->t_open_files);
     1446 +                smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
     1447 +                smb_llist_remove(&tree->t_ofile_list, of);
     1448 +                smb_llist_exit(&tree->t_ofile_list);
     1449 +        }
 971 1450  
     1451 +        /*
     1452 +         * Remove this ofile from the node's n_ofile_list so it
     1453 +         * can't be found by list walkers like notify or oplock.
     1454 +         * Keep the node ref. until later in this function so
     1455 +         * of->f_node remains valid while we destroy the ofile.
     1456 +         */
     1457 +        if (of->f_ftype == SMB_FTYPE_DISK ||
     1458 +            of->f_ftype == SMB_FTYPE_PRINTER) {
     1459 +                ASSERT(of->f_node != NULL);
     1460 +                /*
     1461 +                 * Note smb_ofile_close did smb_node_dec_open_ofiles()
     1462 +                 */
     1463 +                smb_node_rem_ofile(of->f_node, of);
     1464 +        }
     1465 +
     1466 +        /*
     1467 +         * This ofile is no longer on any lists, however...
     1468 +         *
     1469 +         * This is called via smb_llist_post, which means it may run
     1470 +         * BEFORE smb_ofile_release drops f_mutex (if another thread
     1471 +         * flushes the delete queue before we do).  Synchronize.
     1472 +         */
 972 1473          mutex_enter(&of->f_mutex);
     1474 +        of->f_state = SMB_OFILE_STATE_ALLOC;
     1475 +        DTRACE_PROBE1(ofile__exit, smb_ofile_t, of);
 973 1476          mutex_exit(&of->f_mutex);
 974 1477  
 975 1478          switch (of->f_ftype) {
 976 1479          case SMB_FTYPE_BYTE_PIPE:
 977 1480          case SMB_FTYPE_MESG_PIPE:
 978 1481                  smb_opipe_dealloc(of->f_pipe);
 979 1482                  of->f_pipe = NULL;
 980 1483                  break;
 981 1484          case SMB_FTYPE_DISK:
     1485 +                ASSERT(of->f_notify.nc_subscribed == B_FALSE);
     1486 +                MBC_FLUSH(&of->f_notify.nc_buffer);
 982 1487                  if (of->f_odir != NULL)
 983 1488                          smb_odir_release(of->f_odir);
 984      -                smb_node_rem_ofile(of->f_node, of);
     1489 +                if (of->f_lease != NULL) {
     1490 +                        smb2_lease_rele(of->f_lease);
     1491 +                        of->f_lease = NULL;
     1492 +                }
     1493 +                /* FALLTHROUGH */
     1494 +        case SMB_FTYPE_PRINTER:
     1495 +                /*
     1496 +                 * Did smb_node_rem_ofile above.
     1497 +                 */
     1498 +                ASSERT(of->f_node != NULL);
 985 1499                  smb_node_release(of->f_node);
 986 1500                  break;
 987 1501          default:
 988 1502                  ASSERT(!"f_ftype");
 989 1503                  break;
 990 1504          }
 991 1505  
     1506 +        smb_ofile_free(of);
     1507 +}
     1508 +
     1509 +void
     1510 +smb_ofile_free(smb_ofile_t *of)
     1511 +{
     1512 +        smb_tree_t      *tree = of->f_tree;
     1513 +
     1514 +        ASSERT(of->f_state == SMB_OFILE_STATE_ALLOC);
     1515 +
     1516 +        /* Make sure it's not in the persistid hash. */
     1517 +        ASSERT(of->f_persistid == 0);
     1518 +
     1519 +        if (tree != NULL) {
     1520 +                if (of->f_fid != 0)
     1521 +                        smb_idpool_free(&tree->t_fid_pool, of->f_fid);
     1522 +                smb_tree_release(of->f_tree);
     1523 +                smb_user_release(of->f_user);
     1524 +        }
     1525 +
     1526 +        if (of->f_cr != NULL)
     1527 +                crfree(of->f_cr);
     1528 +
 992 1529          of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
     1530 +        list_destroy(&of->f_notify.nc_waiters);
     1531 +        mutex_destroy(&of->dh_nvlock);
 993 1532          mutex_destroy(&of->f_mutex);
 994      -        crfree(of->f_cr);
 995      -        smb_user_release(of->f_user);
 996 1533          kmem_cache_free(smb_cache_ofile, of);
 997 1534  }
 998 1535  
 999 1536  /*
1000 1537   * smb_ofile_access
1001 1538   *
1002 1539   * This function will check to see if the access requested is granted.
1003 1540   * Returns NT status codes.
1004 1541   */
1005 1542  uint32_t
1006 1543  smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access)
1007 1544  {
1008 1545  
1009 1546          if ((of == NULL) || (cr == zone_kcred()))
1010 1547                  return (NT_STATUS_SUCCESS);
1011 1548  
1012 1549          /*
1013 1550           * If the request is for something
1014 1551           * I don't grant it is an error
1015 1552           */
1016 1553          if (~(of->f_granted_access) & access) {
1017 1554                  if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) &&
1018 1555                      (access & ACCESS_SYSTEM_SECURITY)) {
1019 1556                          return (NT_STATUS_PRIVILEGE_NOT_HELD);
1020 1557                  }
1021 1558                  return (NT_STATUS_ACCESS_DENIED);
1022 1559          }
1023 1560  
1024 1561          return (NT_STATUS_SUCCESS);
1025 1562  }
1026 1563  
1027 1564  /*
1028 1565   * smb_ofile_share_check
1029 1566   *
1030 1567   * Check if ofile was opened with share access NONE (0).
1031 1568   * Returns: B_TRUE  - share access non-zero
1032 1569   *          B_FALSE - share access NONE
1033 1570   */
1034 1571  boolean_t
1035 1572  smb_ofile_share_check(smb_ofile_t *of)
1036 1573  {
1037 1574          return (!SMB_DENY_ALL(of->f_share_access));
1038 1575  }
1039 1576  
1040 1577  /*
  
    | 
      ↓ open down ↓ | 
    35 lines elided | 
    
      ↑ open up ↑ | 
  
1041 1578   * check file sharing rules for current open request
1042 1579   * against existing open instances of the same file
1043 1580   *
1044 1581   * Returns NT_STATUS_SHARING_VIOLATION if there is any
1045 1582   * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
1046 1583   */
1047 1584  uint32_t
1048 1585  smb_ofile_open_check(smb_ofile_t *of, uint32_t desired_access,
1049 1586      uint32_t share_access)
1050 1587  {
     1588 +        uint32_t ret;
     1589 +
1051 1590          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1052 1591  
1053 1592          mutex_enter(&of->f_mutex);
1054 1593  
1055      -        if (of->f_state != SMB_OFILE_STATE_OPEN) {
1056      -                mutex_exit(&of->f_mutex);
1057      -                return (NT_STATUS_INVALID_HANDLE);
     1594 +        if (!smb_ofile_is_open_locked(of)) {
     1595 +                ret = NT_STATUS_INVALID_HANDLE;
     1596 +                goto out;
1058 1597          }
1059 1598  
1060 1599          /* if it's just meta data */
1061 1600          if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
1062      -                mutex_exit(&of->f_mutex);
1063      -                return (NT_STATUS_SUCCESS);
     1601 +                ret = NT_STATUS_SUCCESS;
     1602 +                goto out;
1064 1603          }
1065 1604  
1066 1605          /*
1067 1606           * Check requested share access against the
1068 1607           * open granted (desired) access
1069 1608           */
1070 1609          if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) {
1071      -                mutex_exit(&of->f_mutex);
1072      -                return (NT_STATUS_SHARING_VIOLATION);
     1610 +                ret = NT_STATUS_SHARING_VIOLATION;
     1611 +                goto out;
1073 1612          }
1074 1613  
1075 1614          if (SMB_DENY_READ(share_access) &&
1076 1615              (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1077      -                mutex_exit(&of->f_mutex);
1078      -                return (NT_STATUS_SHARING_VIOLATION);
     1616 +                ret = NT_STATUS_SHARING_VIOLATION;
     1617 +                goto out;
1079 1618          }
1080 1619  
1081 1620          if (SMB_DENY_WRITE(share_access) &&
1082 1621              (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1083      -                mutex_exit(&of->f_mutex);
1084      -                return (NT_STATUS_SHARING_VIOLATION);
     1622 +                ret = NT_STATUS_SHARING_VIOLATION;
     1623 +                goto out;
1085 1624          }
1086 1625  
1087 1626          /* check requested desired access against the open share access */
1088 1627          if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) {
1089      -                mutex_exit(&of->f_mutex);
1090      -                return (NT_STATUS_SHARING_VIOLATION);
     1628 +                ret = NT_STATUS_SHARING_VIOLATION;
     1629 +                goto out;
1091 1630          }
1092 1631  
1093 1632          if (SMB_DENY_READ(of->f_share_access) &&
1094 1633              (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1095      -                mutex_exit(&of->f_mutex);
1096      -                return (NT_STATUS_SHARING_VIOLATION);
     1634 +                ret = NT_STATUS_SHARING_VIOLATION;
     1635 +                goto out;
1097 1636          }
1098 1637  
1099 1638          if (SMB_DENY_WRITE(of->f_share_access) &&
1100 1639              (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1101      -                mutex_exit(&of->f_mutex);
1102      -                return (NT_STATUS_SHARING_VIOLATION);
     1640 +                ret = NT_STATUS_SHARING_VIOLATION;
     1641 +                goto out;
1103 1642          }
1104 1643  
     1644 +        ret = NT_STATUS_SUCCESS;
     1645 +out:
1105 1646          mutex_exit(&of->f_mutex);
1106      -        return (NT_STATUS_SUCCESS);
     1647 +        return (ret);
1107 1648  }
1108 1649  
1109 1650  /*
1110 1651   * smb_ofile_rename_check
1111 1652   *
1112      - * An open file can be renamed if
1113      - *
1114      - *  1. isn't opened for data writing or deleting
1115      - *
1116      - *  2. Opened with "Deny Delete" share mode
1117      - *         But not opened for data reading or executing
1118      - *         (opened for accessing meta data)
     1653 + * This does the work described in MS-FSA 2.1.5.1.2.2 (Algorithm
     1654 + * to Check Sharing Access to an Existing Stream or Directory),
     1655 + * where the "open in-progress" has DesiredAccess = DELETE and
     1656 + * SharingMode = SHARE_READ | SHARE_WRITE | SHARE_DELETE.
1119 1657   */
1120 1658  
1121 1659  uint32_t
1122 1660  smb_ofile_rename_check(smb_ofile_t *of)
1123 1661  {
     1662 +        uint32_t ret;
     1663 +
1124 1664          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1125 1665  
1126 1666          mutex_enter(&of->f_mutex);
1127 1667  
1128      -        if (of->f_state != SMB_OFILE_STATE_OPEN) {
1129      -                mutex_exit(&of->f_mutex);
1130      -                return (NT_STATUS_INVALID_HANDLE);
     1668 +        if (!smb_ofile_is_open_locked(of)) {
     1669 +                ret = NT_STATUS_INVALID_HANDLE;
     1670 +                goto out;
1131 1671          }
1132 1672  
1133      -        if (of->f_granted_access &
1134      -            (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) {
1135      -                mutex_exit(&of->f_mutex);
1136      -                return (NT_STATUS_SHARING_VIOLATION);
     1673 +        if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
     1674 +                ret = NT_STATUS_SUCCESS;
     1675 +                goto out;
1137 1676          }
1138 1677  
1139 1678          if ((of->f_share_access & FILE_SHARE_DELETE) == 0) {
1140      -                if (of->f_granted_access &
1141      -                    (FILE_READ_DATA | FILE_EXECUTE)) {
1142      -                        mutex_exit(&of->f_mutex);
1143      -                        return (NT_STATUS_SHARING_VIOLATION);
1144      -                }
     1679 +                ret = NT_STATUS_SHARING_VIOLATION;
     1680 +                goto out;
1145 1681          }
1146 1682  
     1683 +        ret = NT_STATUS_SUCCESS;
     1684 +out:
1147 1685          mutex_exit(&of->f_mutex);
1148      -        return (NT_STATUS_SUCCESS);
     1686 +        return (ret);
1149 1687  }
1150 1688  
1151 1689  /*
1152 1690   * smb_ofile_delete_check
1153 1691   *
1154 1692   * An open file can be deleted only if opened for
1155 1693   * accessing meta data. Share modes aren't important
1156 1694   * in this case.
1157 1695   *
1158 1696   * NOTE: there is another mechanism for deleting an
1159 1697   * open file that NT clients usually use.
1160 1698   * That's setting "Delete on close" flag for an open
1161 1699   * file.  In this way the file will be deleted after
  
    | 
      ↓ open down ↓ | 
    3 lines elided | 
    
      ↑ open up ↑ | 
  
1162 1700   * last close. This flag can be set by SmbTrans2SetFileInfo
1163 1701   * with FILE_DISPOSITION_INFO information level.
1164 1702   * For setting this flag, the file should be opened by
1165 1703   * DELETE access in the FID that is passed in the Trans2
1166 1704   * request.
1167 1705   */
1168 1706  
1169 1707  uint32_t
1170 1708  smb_ofile_delete_check(smb_ofile_t *of)
1171 1709  {
     1710 +        uint32_t ret;
     1711 +
1172 1712          ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1173 1713  
1174 1714          mutex_enter(&of->f_mutex);
1175 1715  
1176      -        if (of->f_state != SMB_OFILE_STATE_OPEN) {
1177      -                mutex_exit(&of->f_mutex);
1178      -                return (NT_STATUS_INVALID_HANDLE);
     1716 +        if (!smb_ofile_is_open_locked(of)) {
     1717 +                ret = NT_STATUS_INVALID_HANDLE;
     1718 +                goto out;
1179 1719          }
1180 1720  
1181 1721          if (of->f_granted_access &
1182 1722              (FILE_READ_DATA | FILE_WRITE_DATA |
1183 1723              FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) {
1184      -                mutex_exit(&of->f_mutex);
1185      -                return (NT_STATUS_SHARING_VIOLATION);
     1724 +                ret = NT_STATUS_SHARING_VIOLATION;
     1725 +                goto out;
1186 1726          }
1187 1727  
     1728 +        ret = NT_STATUS_SUCCESS;
     1729 +out:
1188 1730          mutex_exit(&of->f_mutex);
1189      -        return (NT_STATUS_SUCCESS);
     1731 +        return (ret);
1190 1732  }
1191 1733  
1192 1734  cred_t *
1193 1735  smb_ofile_getcred(smb_ofile_t *of)
1194 1736  {
1195 1737          return (of->f_cr);
1196 1738  }
1197 1739  
1198 1740  /*
1199 1741   * smb_ofile_set_delete_on_close
1200 1742   *
1201 1743   * Set the DeleteOnClose flag on the smb file. When the file is closed,
  
    | 
      ↓ open down ↓ | 
    2 lines elided | 
    
      ↑ open up ↑ | 
  
1202 1744   * the flag will be transferred to the smb node, which will commit the
1203 1745   * delete operation and inhibit subsequent open requests.
1204 1746   *
1205 1747   * When DeleteOnClose is set on an smb_node, the common open code will
1206 1748   * reject subsequent open requests for the file. Observation of Windows
1207 1749   * 2000 indicates that subsequent opens should be allowed (assuming
1208 1750   * there would be no sharing violation) until the file is closed using
1209 1751   * the fid on which the DeleteOnClose was requested.
1210 1752   */
1211 1753  void
1212      -smb_ofile_set_delete_on_close(smb_ofile_t *of)
     1754 +smb_ofile_set_delete_on_close(smb_request_t *sr, smb_ofile_t *of)
1213 1755  {
     1756 +        uint32_t        status;
     1757 +
     1758 +        /*
     1759 +         * Break any oplock handle caching.
     1760 +         */
     1761 +        status = smb_oplock_break_SETINFO(of->f_node, of,
     1762 +            FileDispositionInformation);
     1763 +        if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
     1764 +                if (sr->session->dialect >= SMB_VERS_2_BASE)
     1765 +                        (void) smb2sr_go_async(sr);
     1766 +                (void) smb_oplock_wait_break(of->f_node, 0);
     1767 +        }
     1768 +
1214 1769          mutex_enter(&of->f_mutex);
1215 1770          of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
1216 1771          mutex_exit(&of->f_mutex);
1217 1772  }
1218 1773  
1219 1774  /*
1220 1775   * Encode open file information into a buffer; needed in user space to
1221 1776   * support RPC requests.
1222 1777   */
1223 1778  static int
1224 1779  smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen,
1225 1780      uint32_t *nbytes)
1226 1781  {
1227 1782          smb_netfileinfo_t       fi;
1228 1783          int                     rc;
1229 1784  
1230 1785          rc = smb_ofile_netinfo_init(of, &fi);
1231 1786          if (rc == 0) {
1232 1787                  rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes);
1233 1788                  smb_ofile_netinfo_fini(&fi);
1234 1789          }
1235 1790  
1236 1791          return (rc);
1237 1792  }
1238 1793  
1239 1794  static int
1240 1795  smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi)
1241 1796  {
1242 1797          smb_user_t      *user;
1243 1798          smb_tree_t      *tree;
1244 1799          smb_node_t      *node;
1245 1800          char            *path;
1246 1801          char            *buf;
1247 1802          int             rc;
1248 1803  
1249 1804          ASSERT(of);
1250 1805          user = of->f_user;
1251 1806          tree = of->f_tree;
1252 1807          ASSERT(user);
1253 1808          ASSERT(tree);
1254 1809  
1255 1810          buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1256 1811  
1257 1812          switch (of->f_ftype) {
1258 1813          case SMB_FTYPE_DISK:
1259 1814                  node = of->f_node;
1260 1815                  ASSERT(node);
1261 1816  
1262 1817                  fi->fi_permissions = of->f_granted_access;
1263 1818                  fi->fi_numlocks = smb_lock_get_lock_count(node, of);
1264 1819  
1265 1820                  path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1266 1821  
1267 1822                  if (node != tree->t_snode) {
1268 1823                          rc = smb_node_getshrpath(node, tree, path, MAXPATHLEN);
1269 1824                          if (rc != 0)
1270 1825                                  (void) strlcpy(path, node->od_name, MAXPATHLEN);
1271 1826                  }
1272 1827  
1273 1828                  (void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename,
1274 1829                      path);
1275 1830                  kmem_free(path, MAXPATHLEN);
1276 1831                  break;
1277 1832  
1278 1833          case SMB_FTYPE_MESG_PIPE:
1279 1834                  ASSERT(of->f_pipe);
1280 1835  
1281 1836                  fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA |
1282 1837                      FILE_EXECUTE;
1283 1838                  fi->fi_numlocks = 0;
1284 1839                  (void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s",
1285 1840                      of->f_pipe->p_name);
1286 1841                  break;
1287 1842  
1288 1843          default:
1289 1844                  kmem_free(buf, MAXPATHLEN);
1290 1845                  return (-1);
1291 1846          }
1292 1847  
1293 1848          fi->fi_fid = of->f_fid;
1294 1849          fi->fi_uniqid = of->f_uniqid;
1295 1850          fi->fi_pathlen = strlen(buf) + 1;
1296 1851          fi->fi_path = smb_mem_strdup(buf);
1297 1852          kmem_free(buf, MAXPATHLEN);
1298 1853  
1299 1854          fi->fi_namelen = user->u_domain_len + user->u_name_len + 2;
1300 1855          fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP);
1301 1856          (void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s",
1302 1857              user->u_domain, user->u_name);
1303 1858          return (0);
1304 1859  }
1305 1860  
1306 1861  static void
1307 1862  smb_ofile_netinfo_fini(smb_netfileinfo_t *fi)
1308 1863  {
1309 1864          if (fi == NULL)
1310 1865                  return;
1311 1866  
1312 1867          if (fi->fi_path)
1313 1868                  smb_mem_free(fi->fi_path);
1314 1869          if (fi->fi_username)
1315 1870                  kmem_free(fi->fi_username, fi->fi_namelen);
1316 1871  
1317 1872          bzero(fi, sizeof (smb_netfileinfo_t));
1318 1873  }
1319 1874  
1320 1875  /*
1321 1876   * A query of user and group quotas may span multiple requests.
1322 1877   * f_quota_resume is used to determine where the query should
1323 1878   * be resumed, in a subsequent request. f_quota_resume contains
1324 1879   * the SID of the last quota entry returned to the client.
1325 1880   */
1326 1881  void
1327 1882  smb_ofile_set_quota_resume(smb_ofile_t *ofile, char *resume)
1328 1883  {
1329 1884          ASSERT(ofile);
1330 1885          mutex_enter(&ofile->f_mutex);
1331 1886          if (resume == NULL)
1332 1887                  bzero(ofile->f_quota_resume, SMB_SID_STRSZ);
1333 1888          else
1334 1889                  (void) strlcpy(ofile->f_quota_resume, resume, SMB_SID_STRSZ);
1335 1890          mutex_exit(&ofile->f_mutex);
1336 1891  }
1337 1892  
1338 1893  void
1339 1894  smb_ofile_get_quota_resume(smb_ofile_t *ofile, char *buf, int bufsize)
1340 1895  {
1341 1896          ASSERT(ofile);
1342 1897          mutex_enter(&ofile->f_mutex);
1343 1898          (void) strlcpy(buf, ofile->f_quota_resume, bufsize);
1344 1899          mutex_exit(&ofile->f_mutex);
1345 1900  }
  
    | 
      ↓ open down ↓ | 
    122 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX