Print this page
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-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-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-6858 Non-admin users unable to mount CIFS shares
Reviewed by: Gordon Ross <gwr@nexenta.com>
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-6276 SMB sparse file support
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5737 mutex_enter: bad mutex in smb2 causes panic in mutex_vector_enter
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-3553 SMB2/3 durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5537 Want reference counts for users, trees...
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-4313 want iops, bandwidth, and latency kstats for smb
Portions contributed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-3863 Would like an SMB share property to enable/disable quotas
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3441 CLONE - PORT NEX-3398 Restore SMB map/unmap upcall feature
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-74 Process oplock breaks as session requests (part two)
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (use zone_kcred())
SUP-694 panic on bad mutex in smb_event_wait()
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
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 #13470 rb4432 Sync some SMB differences from illumos
re #6813 rb1757 port 2976 Child folder visibility through shares
re #6812 rb1753 backport illumos 1604 smbd print_enable doesn't really work

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_tree.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_tree.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  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  /*
  23   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  25   25   * Copyright (c) 2016 by Delphix. 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   *
↓ open down ↓ 80 lines elided ↑ open up ↑
 115  115   *
 116  116   *    This transition occurs in smb_tree_connect(). A new tree is created and
 117  117   *    added to the list of trees of a user.
 118  118   *
 119  119   * Transition T1
 120  120   *
 121  121   *    This transition occurs in smb_tree_disconnect().
 122  122   *
 123  123   * Transition T2
 124  124   *
      125 + *    This transition occurs in smb_tree_disconnect()
      126 + *
      127 + * Transition T3
      128 + *
 125  129   *    This transition occurs in smb_tree_release(). The resources associated
 126  130   *    with the tree are freed as well as the tree structure. For the transition
 127      - *    to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED state and
 128      - *    the reference count be zero.
      131 + *    to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the
      132 + *    reference count must be zero.
 129  133   *
 130  134   * Comments
 131  135   * --------
 132  136   *
 133  137   *    The state machine of the tree structures is controlled by 3 elements:
 134  138   *      - The list of trees of the user it belongs to.
 135  139   *      - The mutex embedded in the structure itself.
 136  140   *      - The reference count.
 137  141   *
 138  142   *    There's a mutex embedded in the tree structure used to protect its fields
 139  143   *    and there's a lock embedded in the list of trees of a user. To
 140  144   *    increment or to decrement the reference count the mutex must be entered.
 141  145   *    To insert the tree into the list of trees of the user and to remove
 142  146   *    the tree from it, the lock must be entered in RW_WRITER mode.
 143  147   *
 144  148   *    Rules of access to a tree structure:
 145  149   *
 146  150   *    1) In order to avoid deadlocks, when both (mutex and lock of the user
 147      - *       list) have to be entered, the lock must be entered first.
      151 + *       list) have to be entered, the lock must be entered first. Additionally,
      152 + *       when both the (mutex and lock of the ofile list) have to be entered,
      153 + *       the mutex must be entered first. However, the ofile list lock must NOT
      154 + *       be dropped while the mutex is held in such a way that the ofile deleteq
      155 + *       is flushed.
 148  156   *
 149  157   *    2) All actions applied to a tree require a reference count.
 150  158   *
 151  159   *    3) There are 2 ways of getting a reference count: when a tree is
 152  160   *       connected and when a tree is looked up.
 153  161   *
 154  162   *    It should be noted that the reference count of a tree registers the
 155  163   *    number of references to the tree in other structures (such as an smb
 156  164   *    request). The reference count is not incremented in these 2 instances:
 157  165   *
↓ open down ↓ 11 lines elided ↑ open up ↑
 169  177  #include <smbsrv/smb_ktypes.h>
 170  178  #include <smbsrv/smb_fsops.h>
 171  179  #include <smbsrv/smb_share.h>
 172  180  
 173  181  int smb_tcon_mute = 0;
 174  182  
 175  183  uint32_t        smb_tree_connect_core(smb_request_t *);
 176  184  uint32_t        smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
 177  185  uint32_t        smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
 178  186  uint32_t        smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
 179      -static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *,
 180      -    smb_node_t *, uint32_t, uint32_t);
      187 +static void smb_tree_dealloc(void *);
 181  188  static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
 182      -static boolean_t smb_tree_is_disconnected(smb_tree_t *);
 183  189  static char *smb_tree_get_sharename(char *);
 184  190  static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
 185  191  static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
 186  192  static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
 187  193  static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
 188      -static void smb_tree_close_odirs(smb_tree_t *, uint16_t);
 189      -static smb_ofile_t *smb_tree_get_ofile(smb_tree_t *, smb_ofile_t *);
 190      -static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *);
      194 +static void smb_tree_close_odirs(smb_tree_t *, uint32_t);
 191  195  static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
 192  196  static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
 193  197  static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
 194  198  static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
 195  199  static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
 196  200  
 197  201  uint32_t
 198  202  smb_tree_connect(smb_request_t *sr)
 199  203  {
 200  204          smb_server_t    *sv = sr->sr_server;
↓ open down ↓ 44 lines elided ↑ open up ↑
 245  249          if (!strcasecmp(SMB_SHARE_PRINT, name)) {
 246  250                  smb_kshare_release(sr->sr_server, si);
 247  251                  smb_tree_log(sr, name, "access not permitted");
 248  252                  return (NT_STATUS_ACCESS_DENIED);
 249  253          }
 250  254  
 251  255          /* NB: name points into tcon->path - don't free it. */
 252  256          tcon->name = name;
 253  257          sr->sr_tcon.si = si;
 254  258  
      259 +        /*
      260 +         * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request
      261 +         *
      262 +         * If we support 3.x, RejectUnencryptedAccess is TRUE,
      263 +         * if Tcon.EncryptData is TRUE or global EncryptData is TRUE,
      264 +         * and the connection doesn't support encryption,
      265 +         * return ACCESS_DENIED.
      266 +         *
      267 +         * If RejectUnencryptedAccess is TRUE, we force max_protocol
      268 +         * to at least 3.0. Additionally, if the tree requires encryption,
      269 +         * we don't care what we support, we still enforce encryption.
      270 +         */
      271 +        if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED ||
      272 +            si->shr_encrypt == SMB_CONFIG_REQUIRED) &&
      273 +            (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) {
      274 +                status = NT_STATUS_ACCESS_DENIED;
      275 +                goto out;
      276 +        }
      277 +
 255  278          switch (si->shr_type & STYPE_MASK) {
 256  279          case STYPE_DISKTREE:
 257  280                  status = smb_tree_connect_disk(sr, &sr->sr_tcon);
 258  281                  break;
 259  282          case STYPE_IPC:
 260  283                  status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
 261  284                  break;
 262  285          case STYPE_PRINTQ:
 263  286                  status = smb_tree_connect_printq(sr, &sr->sr_tcon);
 264  287                  break;
 265  288          default:
 266  289                  status = NT_STATUS_BAD_DEVICE_TYPE;
 267  290                  break;
 268  291          }
 269  292  
 270      -        smb_kshare_release(sr->sr_server, si);
      293 +out:
      294 +        /*
      295 +         * On return from smb_tree_connect_* sr->tid_tree is filled in
      296 +         * and valid for all share types.  We can't call smb_kshare_release
      297 +         * until we disconnect the tree or we will invalidate the reference
      298 +         * we have here.
      299 +         */
      300 +        if (sr->tid_tree != NULL) {
      301 +                sr->tid_tree->t_kshare = si;
      302 +        } else {
      303 +                smb_kshare_release(sr->sr_server, si);
      304 +        }
      305 +
 271  306          sr->sr_tcon.si = NULL;
 272  307  
 273  308          return (status);
 274  309  }
 275  310  
 276  311  /*
 277  312   * Disconnect a tree.
      313 + *
      314 + * The "do_exec" arg is obsolete and ignored.
 278  315   */
 279  316  void
 280  317  smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
 281  318  {
      319 +        _NOTE(ARGUNUSED(do_exec))
 282  320          smb_shr_execinfo_t execinfo;
 283  321  
 284  322          ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 285  323  
 286  324          mutex_enter(&tree->t_mutex);
 287  325          ASSERT(tree->t_refcnt);
 288  326  
 289      -        if (smb_tree_is_connected_locked(tree)) {
 290      -                /*
 291      -                 * Indicate that the disconnect process has started.
 292      -                 */
 293      -                tree->t_state = SMB_TREE_STATE_DISCONNECTING;
      327 +        if (!smb_tree_is_connected_locked(tree)) {
 294  328                  mutex_exit(&tree->t_mutex);
 295      -
 296      -                if (do_exec) {
 297      -                        /*
 298      -                         * The files opened under this tree are closed.
 299      -                         */
 300      -                        smb_ofile_close_all(tree);
 301      -                        /*
 302      -                         * The directories opened under this tree are closed.
 303      -                         */
 304      -                        smb_tree_close_odirs(tree, 0);
 305      -                }
 306      -
 307      -                mutex_enter(&tree->t_mutex);
 308      -                tree->t_state = SMB_TREE_STATE_DISCONNECTED;
 309      -                smb_server_dec_trees(tree->t_server);
      329 +                return;
 310  330          }
 311  331  
      332 +        /*
      333 +         * Indicate that the disconnect process has started.
      334 +         */
      335 +        tree->t_state = SMB_TREE_STATE_DISCONNECTING;
 312  336          mutex_exit(&tree->t_mutex);
 313  337  
 314      -        if (do_exec && (tree->t_state == SMB_TREE_STATE_DISCONNECTED) &&
 315      -            (tree->t_execflags & SMB_EXEC_UNMAP)) {
      338 +        /*
      339 +         * The files opened under this tree are closed.
      340 +         */
      341 +        smb_ofile_close_all(tree, 0);
      342 +        /*
      343 +         * The directories opened under this tree are closed.
      344 +         */
      345 +        smb_tree_close_odirs(tree, 0);
 316  346  
      347 +        if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) {
 317  348                  smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
 318  349                  (void) smb_kshare_exec(tree->t_server, &execinfo);
 319  350          }
 320  351  }
 321  352  
 322  353  /*
 323  354   * Take a reference on a tree.
 324  355   */
 325  356  boolean_t
 326  357  smb_tree_hold(
↓ open down ↓ 37 lines elided ↑ open up ↑
 364  395   * reference count falls to zero, post the object for deletion.
 365  396   * Object deletion is deferred to avoid modifying a list while an
 366  397   * iteration may be in progress.
 367  398   */
 368  399  void
 369  400  smb_tree_release(
 370  401      smb_tree_t          *tree)
 371  402  {
 372  403          SMB_TREE_VALID(tree);
 373  404  
 374      -        mutex_enter(&tree->t_mutex);
 375      -        ASSERT(tree->t_refcnt);
 376      -        tree->t_refcnt--;
 377      -
 378  405          /* flush the ofile and odir lists' delete queues */
 379  406          smb_llist_flush(&tree->t_ofile_list);
 380  407          smb_llist_flush(&tree->t_odir_list);
 381  408  
 382      -        if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0))
 383      -                smb_session_post_tree(tree->t_session, tree);
      409 +        mutex_enter(&tree->t_mutex);
      410 +        ASSERT(tree->t_refcnt);
      411 +        tree->t_refcnt--;
 384  412  
      413 +        switch (tree->t_state) {
      414 +        case SMB_TREE_STATE_DISCONNECTING:
      415 +                if (tree->t_refcnt == 0) {
      416 +                        smb_session_t *ssn = tree->t_session;
      417 +                        tree->t_state = SMB_TREE_STATE_DISCONNECTED;
      418 +                        smb_llist_post(&ssn->s_tree_list, tree,
      419 +                            smb_tree_dealloc);
      420 +                }
      421 +                break;
      422 +        case SMB_TREE_STATE_CONNECTED:
      423 +                break;
      424 +        default:
      425 +                ASSERT(0);
      426 +                break;
      427 +        }
      428 +
 385  429          mutex_exit(&tree->t_mutex);
 386  430  }
 387  431  
 388      -void
 389      -smb_tree_post_ofile(smb_tree_t *tree, smb_ofile_t *of)
 390      -{
 391      -        SMB_TREE_VALID(tree);
 392      -        SMB_OFILE_VALID(of);
 393      -        ASSERT(of->f_refcnt == 0);
 394      -        ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
 395      -        ASSERT(of->f_tree == tree);
 396      -
 397      -        smb_llist_post(&tree->t_ofile_list, of, smb_ofile_delete);
 398      -}
 399      -
 400      -void
 401      -smb_tree_post_odir(smb_tree_t *tree, smb_odir_t *od)
 402      -{
 403      -        SMB_TREE_VALID(tree);
 404      -        SMB_ODIR_VALID(od);
 405      -        ASSERT(od->d_refcnt == 0);
 406      -        ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);
 407      -        ASSERT(od->d_tree == tree);
 408      -
 409      -        smb_llist_post(&tree->t_odir_list, od, smb_odir_delete);
 410      -}
 411      -
 412  432  /*
 413  433   * Close ofiles and odirs that match pid.
 414  434   */
 415  435  void
 416  436  smb_tree_close_pid(
 417  437      smb_tree_t          *tree,
 418  438      uint32_t            pid)
 419  439  {
 420  440          ASSERT(tree);
 421  441          ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 422  442  
 423      -        smb_ofile_close_all_by_pid(tree, pid);
      443 +        smb_ofile_close_all(tree, pid);
 424  444          smb_tree_close_odirs(tree, pid);
 425  445  }
 426  446  
 427  447  /*
 428  448   * Check whether or not a tree supports the features identified by flags.
 429  449   */
 430  450  boolean_t
 431  451  smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
 432  452  {
 433  453          ASSERT(tree);
↓ open down ↓ 4 lines elided ↑ open up ↑
 438  458  
 439  459  /*
 440  460   * If the enumeration request is for tree data, handle the request
 441  461   * here.  Otherwise, pass it on to the ofiles.
 442  462   *
 443  463   * This function should be called with a hold on the tree.
 444  464   */
 445  465  int
 446  466  smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
 447  467  {
      468 +        smb_llist_t     *of_list;
 448  469          smb_ofile_t     *of;
 449      -        smb_ofile_t     *next;
 450  470          int             rc = 0;
 451  471  
 452      -        ASSERT(tree);
 453      -        ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 454      -
 455  472          if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
 456  473                  return (smb_tree_enum_private(tree, svcenum));
 457  474  
 458      -        of = smb_tree_get_ofile(tree, NULL);
 459      -        while (of) {
 460      -                ASSERT(of->f_tree == tree);
      475 +        of_list = &tree->t_ofile_list;
      476 +        smb_llist_enter(of_list, RW_READER);
 461  477  
 462      -                rc = smb_ofile_enum(of, svcenum);
 463      -                if (rc != 0) {
      478 +        of = smb_llist_head(of_list);
      479 +        while (of) {
      480 +                if (smb_ofile_hold(of)) {
      481 +                        rc = smb_ofile_enum(of, svcenum);
 464  482                          smb_ofile_release(of);
 465      -                        break;
 466  483                  }
 467      -
 468      -                next = smb_tree_get_ofile(tree, of);
 469      -                smb_ofile_release(of);
 470      -                of = next;
      484 +                if (rc != 0)
      485 +                        break;
      486 +                of = smb_llist_next(of_list, of);
 471  487          }
 472  488  
      489 +        smb_llist_exit(of_list);
      490 +
 473  491          return (rc);
 474  492  }
 475  493  
 476  494  /*
 477  495   * Close a file by its unique id.
 478  496   */
 479  497  int
 480  498  smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
 481  499  {
 482  500          smb_ofile_t     *of;
 483  501  
 484  502          ASSERT(tree);
 485  503          ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 486  504  
      505 +        /*
      506 +         * Note that ORPHANED ofiles aren't fclosable, as they have
      507 +         * no session, user, or tree by which they might be found.
      508 +         * They will eventually expire.
      509 +         */
 487  510          if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
 488  511                  return (ENOENT);
 489  512  
 490  513          if (smb_ofile_disallow_fclose(of)) {
 491  514                  smb_ofile_release(of);
 492  515                  return (EACCES);
 493  516          }
 494  517  
 495  518          smb_ofile_close(of, 0);
 496  519          smb_ofile_release(of);
↓ open down ↓ 135 lines elided ↑ open up ↑
 632  655  
 633  656          access = host_access & acl_access;
 634  657          if ((access & ACE_ALL_PERMS) == 0) {
 635  658                  smb_tree_log(sr, sharename, "access denied");
 636  659                  return (0);
 637  660          }
 638  661  
 639  662          return (access);
 640  663  }
 641  664  
      665 +/* How long should tree connect wait for DH import to complete? */
      666 +int smb_tcon_import_wait = 20; /* sec. */
      667 +
 642  668  /*
 643  669   * Connect a share for use with files and directories.
 644  670   */
 645  671  uint32_t
 646  672  smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
 647  673  {
 648  674          char                    *sharename = tcon->path;
 649  675          const char              *any = "?????";
 650  676          smb_user_t              *user = sr->uid_user;
 651      -        smb_node_t              *dnode = NULL;
 652  677          smb_node_t              *snode = NULL;
 653      -        smb_kshare_t            *si = tcon->si;
      678 +        smb_kshare_t            *si = tcon->si;
 654  679          char                    *service = tcon->service;
 655      -        char                    last_component[MAXNAMELEN];
 656  680          smb_tree_t              *tree;
 657  681          int                     rc;
 658  682          uint32_t                access;
 659  683          smb_shr_execinfo_t      execinfo;
      684 +        clock_t time;
 660  685  
 661  686          ASSERT(user);
 662  687          ASSERT(user->u_cred);
 663  688  
 664  689          if (service != NULL &&
 665  690              strcmp(service, any) != 0 &&
 666  691              strcasecmp(service, "A:") != 0) {
 667  692                  smb_tree_log(sr, sharename, "invalid service (%s)", service);
 668  693                  return (NT_STATUS_BAD_DEVICE_TYPE);
 669  694          }
 670  695  
 671  696          /*
 672  697           * Check that the shared directory exists.
 673  698           */
 674      -        rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
 675      -            last_component);
 676      -        if (rc == 0) {
 677      -                rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
 678      -                    sr->sr_server->si_root_smb_node, dnode, last_component,
 679      -                    &snode);
 680      -
 681      -                smb_node_release(dnode);
 682      -        }
 683      -
 684      -        if (rc) {
 685      -                if (snode)
 686      -                        smb_node_release(snode);
 687      -
      699 +        snode = si->shr_root_node;
      700 +        if (snode == NULL) {
 688  701                  smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
 689  702                  return (NT_STATUS_BAD_NETWORK_NAME);
 690  703          }
 691  704  
 692  705          if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
 693      -                smb_node_release(snode);
 694  706                  return (NT_STATUS_ACCESS_DENIED);
 695  707          }
 696  708  
 697  709          /*
      710 +         * Wait for DH import of persistent handles to finish.
      711 +         * If we timeout, it's not clear what status to return,
      712 +         * but as the share is not really availale yet, let's
      713 +         * return the status for "no such share".
      714 +         */
      715 +        time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt();
      716 +        mutex_enter(&si->shr_mutex);
      717 +        while (si->shr_import_busy != NULL) {
      718 +                if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) {
      719 +                        mutex_exit(&si->shr_mutex);
      720 +                        return (NT_STATUS_BAD_NETWORK_NAME);
      721 +                }
      722 +        }
      723 +        mutex_exit(&si->shr_mutex);
      724 +
      725 +        /*
 698  726           * Set up the OptionalSupport for this share.
 699  727           */
 700  728          tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
 701  729  
 702  730          switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
 703  731          case SMB_SHRF_CSC_DISABLED:
 704  732                  tcon->optional_support |= SMB_CSC_CACHE_NONE;
 705  733                  break;
 706  734          case SMB_SHRF_CSC_AUTO:
 707  735                  tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
↓ open down ↓ 16 lines elided ↑ open up ↑
 724  752  
 725  753          if (si->shr_flags & SMB_SHRF_DFSROOT)
 726  754                  tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
 727  755  
 728  756          /* if 'smb' zfs property: shortnames=disabled */
 729  757          if (!smb_shortnames)
 730  758                  sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
 731  759  
 732  760          tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
 733  761  
 734      -        smb_node_release(snode);
 735      -
 736  762          if (tree == NULL)
 737  763                  return (NT_STATUS_INSUFF_SERVER_RESOURCES);
 738  764  
 739  765          if (tree->t_execflags & SMB_EXEC_MAP) {
 740  766                  smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
 741  767  
 742  768                  rc = smb_kshare_exec(tree->t_server, &execinfo);
 743  769  
 744  770                  if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
 745      -                        smb_tree_disconnect(tree, B_FALSE);
      771 +                        /*
      772 +                         * Inline parts of: smb_tree_disconnect()
      773 +                         * Not using smb_tree_disconnect() for cleanup
      774 +                         * here because: we don't want an exec up-call,
      775 +                         * and there can't be any opens as we never
      776 +                         * returned this TID to the client.
      777 +                         */
      778 +                        mutex_enter(&tree->t_mutex);
      779 +                        tree->t_state = SMB_TREE_STATE_DISCONNECTING;
      780 +                        mutex_enter(&tree->t_mutex);
      781 +
 746  782                          smb_tree_release(tree);
 747  783                          return (NT_STATUS_ACCESS_DENIED);
 748  784                  }
 749  785          }
 750  786  
 751  787          sr->tid_tree = tree;
 752  788          sr->smb_tid  = tree->t_tid;
 753  789  
 754  790          return (0);
 755  791  }
↓ open down ↓ 5 lines elided ↑ open up ↑
 761  797   * share ACL).
 762  798   */
 763  799  uint32_t
 764  800  smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
 765  801  {
 766  802          char                    *sharename = tcon->path;
 767  803          const char              *any = "?????";
 768  804          smb_user_t              *user = sr->uid_user;
 769  805          smb_node_t              *dnode = NULL;
 770  806          smb_node_t              *snode = NULL;
 771      -        smb_kshare_t            *si = tcon->si;
      807 +        smb_kshare_t            *si = tcon->si;
 772  808          char                    *service = tcon->service;
 773  809          char                    last_component[MAXNAMELEN];
 774  810          smb_tree_t              *tree;
 775  811          int                     rc;
 776  812          uint32_t                access;
 777  813  
 778  814          ASSERT(user);
 779  815          ASSERT(user->u_cred);
 780  816  
 781  817          if (sr->sr_server->sv_cfg.skc_print_enable == 0) {
↓ open down ↓ 85 lines elided ↑ open up ↑
 867  903  
 868  904          sr->tid_tree = tree;
 869  905          sr->smb_tid  = tree->t_tid;
 870  906  
 871  907          return (0);
 872  908  }
 873  909  
 874  910  /*
 875  911   * Allocate a tree.
 876  912   */
 877      -static smb_tree_t *
      913 +smb_tree_t *
 878  914  smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
 879  915      smb_node_t *snode, uint32_t access, uint32_t execflags)
 880  916  {
 881  917          smb_session_t   *session = sr->session;
 882  918          smb_tree_t      *tree;
 883  919          uint32_t        stype = si->shr_type;
 884  920          uint16_t        tid;
 885  921  
 886  922          if (smb_idpool_alloc(&session->s_tid_pool, &tid))
 887  923                  return (NULL);
↓ open down ↓ 23 lines elided ↑ open up ↑
 911  947          }
 912  948  
 913  949          if (smb_idpool_constructor(&tree->t_odid_pool)) {
 914  950                  smb_idpool_destructor(&tree->t_fid_pool);
 915  951                  smb_idpool_free(&session->s_tid_pool, tid);
 916  952                  kmem_cache_free(smb_cache_tree, tree);
 917  953                  return (NULL);
 918  954          }
 919  955  
 920  956          smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
 921      -            offsetof(smb_ofile_t, f_lnd));
      957 +            offsetof(smb_ofile_t, f_tree_lnd));
 922  958  
 923  959          smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
 924  960              offsetof(smb_odir_t, d_lnd));
 925  961  
 926  962          (void) strlcpy(tree->t_sharename, si->shr_name,
 927  963              sizeof (tree->t_sharename));
 928  964          (void) strlcpy(tree->t_resource, si->shr_path,
 929  965              sizeof (tree->t_resource));
 930  966  
 931  967          mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
↓ open down ↓ 25 lines elided ↑ open up ↑
 957  993          return (tree);
 958  994  }
 959  995  
 960  996  /*
 961  997   * Deallocate a tree.  The open file and open directory lists should be
 962  998   * empty.
 963  999   *
 964 1000   * Remove the tree from the user's tree list before freeing resources
 965 1001   * associated with the tree.
 966 1002   */
 967      -void
     1003 +static void
 968 1004  smb_tree_dealloc(void *arg)
 969 1005  {
 970 1006          smb_session_t   *session;
 971 1007          smb_tree_t      *tree = (smb_tree_t *)arg;
 972 1008  
 973 1009          SMB_TREE_VALID(tree);
 974 1010          ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
 975 1011          ASSERT(tree->t_refcnt == 0);
 976 1012  
     1013 +        smb_server_dec_trees(tree->t_server);
     1014 +
 977 1015          session = tree->t_session;
 978 1016          smb_llist_enter(&session->s_tree_list, RW_WRITER);
 979 1017          smb_llist_remove(&session->s_tree_list, tree);
 980 1018          smb_idpool_free(&session->s_tid_pool, tree->t_tid);
 981 1019          atomic_dec_32(&session->s_tree_cnt);
 982 1020          smb_llist_exit(&session->s_tree_list);
 983 1021  
     1022 +        /*
     1023 +         * This tree is no longer on s_tree_list, however...
     1024 +         *
     1025 +         * This is called via smb_llist_post, which means it may run
     1026 +         * BEFORE smb_tree_release drops t_mutex (if another thread
     1027 +         * flushes the delete queue before we do).  Synchronize.
     1028 +         */
 984 1029          mutex_enter(&tree->t_mutex);
 985 1030          mutex_exit(&tree->t_mutex);
 986 1031  
 987 1032          tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
 988 1033  
     1034 +        if (tree->t_kshare != NULL) {
     1035 +                smb_kshare_release(tree->t_server, tree->t_kshare);
     1036 +                tree->t_kshare = NULL;
     1037 +        }
     1038 +
 989 1039          if (tree->t_snode)
 990 1040                  smb_node_release(tree->t_snode);
 991 1041  
 992 1042          mutex_destroy(&tree->t_mutex);
 993 1043          smb_llist_destructor(&tree->t_ofile_list);
 994 1044          smb_llist_destructor(&tree->t_odir_list);
 995 1045          smb_idpool_destructor(&tree->t_fid_pool);
 996 1046          smb_idpool_destructor(&tree->t_odid_pool);
 997 1047  
 998 1048          SMB_USER_VALID(tree->t_owner);
↓ open down ↓ 9 lines elided ↑ open up ↑
1008 1058  static boolean_t
1009 1059  smb_tree_is_connected_locked(smb_tree_t *tree)
1010 1060  {
1011 1061          switch (tree->t_state) {
1012 1062          case SMB_TREE_STATE_CONNECTED:
1013 1063                  return (B_TRUE);
1014 1064  
1015 1065          case SMB_TREE_STATE_DISCONNECTING:
1016 1066          case SMB_TREE_STATE_DISCONNECTED:
1017 1067                  /*
1018      -                 * The tree exists but being diconnected or destroyed.
     1068 +                 * The tree exists but is being disconnected or destroyed.
1019 1069                   */
1020 1070                  return (B_FALSE);
1021 1071  
1022 1072          default:
1023 1073                  ASSERT(0);
1024 1074                  return (B_FALSE);
1025 1075          }
1026 1076  }
1027 1077  
1028 1078  /*
1029      - * Determine whether or not a tree is disconnected.
1030      - * This function must be called with the tree mutex held.
1031      - */
1032      -static boolean_t
1033      -smb_tree_is_disconnected(smb_tree_t *tree)
1034      -{
1035      -        switch (tree->t_state) {
1036      -        case SMB_TREE_STATE_DISCONNECTED:
1037      -                return (B_TRUE);
1038      -
1039      -        case SMB_TREE_STATE_CONNECTED:
1040      -        case SMB_TREE_STATE_DISCONNECTING:
1041      -                return (B_FALSE);
1042      -
1043      -        default:
1044      -                ASSERT(0);
1045      -                return (B_FALSE);
1046      -        }
1047      -}
1048      -
1049      -/*
1050 1079   * Return a pointer to the share name within a share resource path.
1051 1080   *
1052 1081   * The share path may be a Uniform Naming Convention (UNC) string
1053 1082   * (\\server\share) or simply the share name.  We validate the UNC
1054 1083   * format but we don't look at the server name.
1055 1084   */
1056 1085  static char *
1057 1086  smb_tree_get_sharename(char *unc_path)
1058 1087  {
1059 1088          char *sharename = unc_path;
↓ open down ↓ 19 lines elided ↑ open up ↑
1079 1108          return (sharename);
1080 1109  }
1081 1110  
1082 1111  /*
1083 1112   * Obtain the tree attributes: volume name, typename and flags.
1084 1113   */
1085 1114  static int
1086 1115  smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1087 1116  {
1088 1117          vfs_t *vfsp = SMB_NODE_VFS(node);
     1118 +        smb_cfg_val_t srv_encrypt;
1089 1119  
1090 1120          ASSERT(vfsp);
1091 1121  
1092 1122          if (getvfs(&vfsp->vfs_fsid) != vfsp)
1093 1123                  return (ESTALE);
1094 1124  
1095 1125          smb_tree_get_volname(vfsp, tree);
1096 1126          smb_tree_get_flags(si, vfsp, tree);
1097 1127  
     1128 +        srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt;
     1129 +        if (tree->t_session->dialect >= SMB_VERS_3_0) {
     1130 +                if (si->shr_encrypt == SMB_CONFIG_REQUIRED ||
     1131 +                    srv_encrypt == SMB_CONFIG_REQUIRED)
     1132 +                        tree->t_encrypt = SMB_CONFIG_REQUIRED;
     1133 +                else if (si->shr_encrypt == SMB_CONFIG_ENABLED ||
     1134 +                    srv_encrypt == SMB_CONFIG_ENABLED)
     1135 +                        tree->t_encrypt = SMB_CONFIG_ENABLED;
     1136 +                else
     1137 +                        tree->t_encrypt = SMB_CONFIG_DISABLED;
     1138 +        } else
     1139 +                tree->t_encrypt = SMB_CONFIG_DISABLED;
     1140 +
1098 1141          VFS_RELE(vfsp);
1099 1142          return (0);
1100 1143  }
1101 1144  
1102 1145  /*
1103 1146   * Extract the volume name.
1104 1147   */
1105 1148  static void
1106 1149  smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1107 1150  {
↓ open down ↓ 32 lines elided ↑ open up ↑
1140 1183          smb_session_t *ssn = tree->t_session;
1141 1184          struct vfssw    *vswp;
1142 1185  
1143 1186          typedef struct smb_mtype {
1144 1187                  char            *mt_name;
1145 1188                  size_t          mt_namelen;
1146 1189                  uint32_t        mt_flags;
1147 1190          } smb_mtype_t;
1148 1191  
1149 1192          static smb_mtype_t smb_mtype[] = {
     1193 +#ifdef  _FAKE_KERNEL
     1194 +                /* See libfksmbsrv:fake_vfs.c */
     1195 +                { "fake",    3, SMB_TREE_SPARSE},
     1196 +#endif  /* _FAKE_KERNEL */
1150 1197                  { "zfs",    3,  SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1151 1198                  { "ufs",    3,  0 },
1152 1199                  { "nfs",    3,  SMB_TREE_NFS_MOUNTED },
1153 1200                  { "tmpfs",  5,  SMB_TREE_NO_EXPORT }
1154 1201          };
1155 1202          smb_mtype_t     *mtype;
1156 1203          char            *name;
1157 1204          uint32_t        flags =
1158 1205              SMB_TREE_SUPPORTS_ACLS |
1159 1206              SMB_TREE_UNICODE_ON_DISK;
↓ open down ↓ 1 lines elided ↑ open up ↑
1161 1208  
1162 1209          if (si->shr_flags & SMB_SHRF_DFSROOT)
1163 1210                  flags |= SMB_TREE_DFSROOT;
1164 1211  
1165 1212          if (si->shr_flags & SMB_SHRF_CATIA)
1166 1213                  flags |= SMB_TREE_CATIA;
1167 1214  
1168 1215          if (si->shr_flags & SMB_SHRF_ABE)
1169 1216                  flags |= SMB_TREE_ABE;
1170 1217  
     1218 +        if (si->shr_flags & SMB_SHRF_CA)
     1219 +                flags |= SMB_TREE_CA;
     1220 +
     1221 +        if (si->shr_flags & SMB_SHRF_FSO)
     1222 +                flags |= SMB_TREE_FORCE_L2_OPLOCK;
     1223 +
1171 1224          if (ssn->s_cfg.skc_oplock_enable) {
1172 1225                  /* if 'smb' zfs property: oplocks=enabled */
1173 1226                  flags |= SMB_TREE_OPLOCKS;
1174 1227          }
1175 1228  
1176 1229          /* Global config option for now.  Later make per-share. */
1177 1230          if (ssn->s_cfg.skc_traverse_mounts)
1178 1231                  flags |= SMB_TREE_TRAVERSE_MOUNTS;
1179 1232  
1180 1233          /* if 'smb' zfs property: shortnames=enabled */
↓ open down ↓ 13 lines elided ↑ open up ↑
1194 1247          } else {
1195 1248                  name = "?";
1196 1249          }
1197 1250  
1198 1251          for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1199 1252                  mtype = &smb_mtype[i];
1200 1253                  if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1201 1254                          flags |= mtype->mt_flags;
1202 1255          }
1203 1256  
     1257 +        /*
     1258 +         * SMB_TREE_QUOTA will be on here if the FS is ZFS.  We want to
     1259 +         * turn it OFF when the share property says false.
     1260 +         */
     1261 +        if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
     1262 +                flags &= ~SMB_TREE_QUOTA;
     1263 +
1204 1264          (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1205 1265          (void) smb_strupr((char *)tree->t_typename);
1206 1266  
1207 1267          if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1208 1268                  flags |= SMB_TREE_XVATTR;
1209 1269  
1210 1270          if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1211 1271                  flags |= SMB_TREE_CASEINSENSITIVE;
1212 1272  
1213 1273          if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
↓ open down ↓ 99 lines elided ↑ open up ↑
1313 1373  {
1314 1374          boolean_t       rb;
1315 1375  
1316 1376          mutex_enter(&tree->t_mutex);
1317 1377          rb = smb_tree_is_connected_locked(tree);
1318 1378          mutex_exit(&tree->t_mutex);
1319 1379          return (rb);
1320 1380  }
1321 1381  
1322 1382  /*
1323      - * Get the next open ofile in the list.  A reference is taken on
1324      - * the ofile, which can be released later with smb_ofile_release().
1325      - *
1326      - * If the specified ofile is NULL, search from the beginning of the
1327      - * list.  Otherwise, the search starts just after that ofile.
1328      - *
1329      - * Returns NULL if there are no open files in the list.
1330      - */
1331      -static smb_ofile_t *
1332      -smb_tree_get_ofile(smb_tree_t *tree, smb_ofile_t *of)
1333      -{
1334      -        smb_llist_t *ofile_list;
1335      -
1336      -        ASSERT(tree);
1337      -        ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1338      -
1339      -        ofile_list = &tree->t_ofile_list;
1340      -        smb_llist_enter(ofile_list, RW_READER);
1341      -
1342      -        if (of) {
1343      -                ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1344      -                of = smb_llist_next(ofile_list, of);
1345      -        } else {
1346      -                of = smb_llist_head(ofile_list);
1347      -        }
1348      -
1349      -        while (of) {
1350      -                if (smb_ofile_hold(of))
1351      -                        break;
1352      -
1353      -                of = smb_llist_next(ofile_list, of);
1354      -        }
1355      -
1356      -        smb_llist_exit(ofile_list);
1357      -        return (of);
1358      -}
1359      -
1360      -/*
1361      - * smb_tree_get_odir
1362      - *
1363      - * Find the next odir in the tree's list of odirs, and obtain a
1364      - * hold on it.
1365      - * If the specified odir is NULL the search starts at the beginning
1366      - * of the tree's odir list, otherwise the search starts after the
1367      - * specified odir.
1368      - */
1369      -static smb_odir_t *
1370      -smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od)
1371      -{
1372      -        smb_llist_t *od_list;
1373      -
1374      -        ASSERT(tree);
1375      -        ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1376      -
1377      -        od_list = &tree->t_odir_list;
1378      -        smb_llist_enter(od_list, RW_READER);
1379      -
1380      -        if (od) {
1381      -                ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1382      -                od = smb_llist_next(od_list, od);
1383      -        } else {
1384      -                od = smb_llist_head(od_list);
1385      -        }
1386      -
1387      -        while (od) {
1388      -                ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1389      -
1390      -                if (smb_odir_hold(od))
1391      -                        break;
1392      -                od = smb_llist_next(od_list, od);
1393      -        }
1394      -
1395      -        smb_llist_exit(od_list);
1396      -        return (od);
1397      -}
1398      -
1399      -/*
1400 1383   * smb_tree_close_odirs
1401 1384   *
1402 1385   * Close all open odirs in the tree's list which were opened by
1403 1386   * the process identified by pid.
1404 1387   * If pid is zero, close all open odirs in the tree's list.
1405 1388   */
1406 1389  static void
1407      -smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid)
     1390 +smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid)
1408 1391  {
1409      -        smb_odir_t *od, *next_od;
     1392 +        smb_llist_t     *od_list;
     1393 +        smb_odir_t      *od;
1410 1394  
1411 1395          ASSERT(tree);
1412 1396          ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1413 1397  
1414      -        od = smb_tree_get_odir(tree, NULL);
1415      -        while (od) {
     1398 +        od_list = &tree->t_odir_list;
     1399 +        smb_llist_enter(od_list, RW_READER);
     1400 +
     1401 +        for (od = smb_llist_head(od_list);
     1402 +            od != NULL;
     1403 +            od = smb_llist_next(od_list, od)) {
     1404 +
1416 1405                  ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1417 1406                  ASSERT(od->d_tree == tree);
1418 1407  
1419      -                next_od = smb_tree_get_odir(tree, od);
1420      -                if ((pid == 0) || (od->d_opened_by_pid == pid))
1421      -                        smb_odir_close(od);
1422      -                smb_odir_release(od);
     1408 +                if (pid != 0 && od->d_opened_by_pid != pid)
     1409 +                        continue;
1423 1410  
1424      -                od = next_od;
     1411 +                if (smb_odir_hold(od)) {
     1412 +                        smb_odir_close(od);
     1413 +                        smb_odir_release(od);
     1414 +                }
1425 1415          }
     1416 +
     1417 +        smb_llist_exit(od_list);
1426 1418  }
1427 1419  
1428 1420  static void
1429 1421  smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
1430 1422      int exec_type)
1431 1423  {
1432 1424          exec->e_sharename = tree->t_sharename;
1433 1425          exec->e_winname = tree->t_owner->u_name;
1434 1426          exec->e_userdom = tree->t_owner->u_domain;
1435 1427          exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
↓ open down ↓ 110 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX