Print this page
    
NEX-17095 illumos 8935 SMB ioctl fixes incomplete
8935 SMB ioctl fixes incomplete
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Rui Loura <rui.loura@joyent.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dominik Hassler <hasslerd@gmx.li>
Approved by: Garrett D'Amore <garrett@damore.org>
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-9808 SMB3 persistent handles
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-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-7490 read_kstat_data panic in smb_named_kstat_update
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexent.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-6308 namespace collision for per-share kstats when changing sharesmb property
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-6266 SMB kstats namespace collision for share names longer than 28 characters (follow-up)
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-6266 SMB kstats namespace collision for share names longer than 28 characters
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-5175 want SMB statistics separately for reads, writes, other
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-4844 assertion failed: kshare->shr_magic == SMB_SHARE_MAGIC
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>
SMB-74 Process oplock breaks as session requests
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 (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-64 smbsrv workers run at excessively high priority
re #9812 rb3153 System panic'd with assertion failed: sl->sl_count == 0 in smb_slist_destructor after hostname change, smbd restart and attempts to rejoin active directory domain
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb_kshare.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_kshare.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   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ 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 2017 Nexenta Systems, Inc.  All rights reserved.
  25   25   * Copyright 2017 Joyent, Inc.
  26   26   */
  27   27  
  28   28  #include <smbsrv/smb_door.h>
  29      -#include <smbsrv/smb_kproto.h>
  30   29  #include <smbsrv/smb_ktypes.h>
       30 +#include <smbsrv/smb2_kproto.h>
       31 +#include <smbsrv/smb_kstat.h>
  31   32  
  32   33  typedef struct smb_unshare {
  33   34          list_node_t     us_lnd;
  34   35          char            us_sharename[MAXNAMELEN];
  35   36  } smb_unshare_t;
  36   37  
  37   38  static kmem_cache_t     *smb_kshare_cache_share;
  38   39  static kmem_cache_t     *smb_kshare_cache_unexport;
  39      -kmem_cache_t    *smb_kshare_cache_vfs;
  40   40  
  41   41  static int smb_kshare_cmp(const void *, const void *);
  42   42  static void smb_kshare_hold(const void *);
  43   43  static boolean_t smb_kshare_rele(const void *);
  44   44  static void smb_kshare_destroy(void *);
  45   45  static char *smb_kshare_oemname(const char *);
  46   46  static int smb_kshare_is_special(const char *);
  47   47  static boolean_t smb_kshare_is_admin(const char *);
  48   48  static smb_kshare_t *smb_kshare_decode(nvlist_t *);
  49   49  static uint32_t smb_kshare_decode_bool(nvlist_t *, const char *, uint32_t);
  50   50  static void smb_kshare_unexport_thread(smb_thread_t *, void *);
  51   51  static int smb_kshare_export(smb_server_t *, smb_kshare_t *);
  52   52  static int smb_kshare_unexport(smb_server_t *, const char *);
  53   53  static int smb_kshare_export_trans(smb_server_t *, char *, char *, char *);
  54   54  static void smb_kshare_csc_flags(smb_kshare_t *, const char *);
       55 +static int smb_named_kstat_update(kstat_t *ks, int rw);
       56 +static int smb_kshare_kstat_update(kstat_t *, int);
       57 +void kshare_stats_init(smb_server_t *, smb_kshare_t *);
       58 +void kshare_stats_fini(smb_kshare_t *);
  55   59  
  56   60  static boolean_t smb_export_isready(smb_server_t *);
  57   61  
  58   62  #ifdef  _KERNEL
  59   63  static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
  60   64  #endif  /* _KERNEL */
  61   65  
  62   66  static const smb_avl_nops_t smb_kshare_avlops = {
  63   67          smb_kshare_cmp,
  64   68          smb_kshare_hold,
  65   69          smb_kshare_rele,
  66   70          smb_kshare_destroy
  67   71  };
  68   72  
  69   73  #ifdef  _KERNEL
  70   74  /*
  71   75   * This function is not MultiThread safe. The caller has to make sure only one
  72   76   * thread calls this function.
  73   77   */
  74   78  door_handle_t
  75   79  smb_kshare_door_init(int door_id)
  76   80  {
  77   81          return (door_ki_lookup(door_id));
  78   82  }
  79   83  
  80   84  /*
  81   85   * This function is not MultiThread safe. The caller has to make sure only one
  82   86   * thread calls this function.
  83   87   */
  84   88  void
  85   89  smb_kshare_door_fini(door_handle_t dhdl)
  86   90  {
  87   91          if (dhdl)
  88   92                  door_ki_rele(dhdl);
  89   93  }
  90   94  
  91   95  /*
  92   96   * This is a special interface that will be utilized by ZFS to cause
  93   97   * a share to be added/removed
  94   98   *
  95   99   * arg is either a smb_share_t or share_name from userspace.
  96  100   * It will need to be copied into the kernel.   It is smb_share_t
  97  101   * for add operations and share_name for delete operations.
  98  102   */
  99  103  int
 100  104  smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
 101  105  {
 102  106          door_arg_t      doorarg = { 0 };
 103  107          char            *buf = NULL;
 104  108          char            *str = NULL;
 105  109          int             error;
 106  110          int             rc;
 107  111          unsigned int    used;
 108  112          smb_dr_ctx_t    *dec_ctx;
 109  113          smb_dr_ctx_t    *enc_ctx;
 110  114          smb_share_t     *lmshare = NULL;
 111  115          int             opcode;
 112  116  
 113  117          opcode = (add_share) ? SMB_SHROP_ADD : SMB_SHROP_DELETE;
 114  118  
 115  119          buf = kmem_alloc(SMB_SHARE_DSIZE, KM_SLEEP);
 116  120          enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE);
 117  121          smb_dr_put_uint32(enc_ctx, opcode);
 118  122  
 119  123          switch (opcode) {
 120  124          case SMB_SHROP_ADD:
 121  125                  lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP);
 122  126                  error = xcopyin(arg, lmshare, sizeof (smb_share_t));
 123  127                  if (error != 0) {
 124  128                          kmem_free(lmshare, sizeof (smb_share_t));
 125  129                          kmem_free(buf, SMB_SHARE_DSIZE);
 126  130                          return (error);
 127  131                  }
 128  132                  smb_dr_put_share(enc_ctx, lmshare);
 129  133                  break;
 130  134  
 131  135          case SMB_SHROP_DELETE:
 132  136                  str = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 133  137                  error = copyinstr(arg, str, MAXPATHLEN, NULL);
 134  138                  if (error != 0) {
 135  139                          kmem_free(str, MAXPATHLEN);
 136  140                          kmem_free(buf, SMB_SHARE_DSIZE);
 137  141                          return (error);
 138  142                  }
 139  143                  smb_dr_put_string(enc_ctx, str);
 140  144                  kmem_free(str, MAXPATHLEN);
 141  145                  break;
 142  146          }
 143  147  
 144  148          if ((error = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
 145  149                  kmem_free(buf, SMB_SHARE_DSIZE);
 146  150                  if (lmshare)
 147  151                          kmem_free(lmshare, sizeof (smb_share_t));
 148  152                  return (NERR_InternalError);
 149  153          }
 150  154  
 151  155          doorarg.data_ptr = buf;
 152  156          doorarg.data_size = used;
 153  157          doorarg.rbuf = buf;
 154  158          doorarg.rsize = SMB_SHARE_DSIZE;
 155  159  
 156  160          error = door_ki_upcall_limited(dhdl, &doorarg, NULL, SIZE_MAX, 0);
 157  161  
 158  162          if (error) {
 159  163                  kmem_free(buf, SMB_SHARE_DSIZE);
 160  164                  if (lmshare)
 161  165                          kmem_free(lmshare, sizeof (smb_share_t));
 162  166                  return (error);
 163  167          }
 164  168  
 165  169          dec_ctx = smb_dr_decode_start(doorarg.data_ptr, doorarg.data_size);
 166  170          if (smb_kshare_chk_dsrv_status(opcode, dec_ctx) != 0) {
 167  171                  kmem_free(buf, SMB_SHARE_DSIZE);
 168  172                  if (lmshare)
 169  173                          kmem_free(lmshare, sizeof (smb_share_t));
 170  174                  return (NERR_InternalError);
 171  175          }
 172  176  
 173  177          rc = smb_dr_get_uint32(dec_ctx);
 174  178          if (opcode == SMB_SHROP_ADD)
 175  179                  smb_dr_get_share(dec_ctx, lmshare);
 176  180  
 177  181          if (smb_dr_decode_finish(dec_ctx))
 178  182                  rc = NERR_InternalError;
 179  183  
 180  184          kmem_free(buf, SMB_SHARE_DSIZE);
 181  185          if (lmshare)
 182  186                  kmem_free(lmshare, sizeof (smb_share_t));
 183  187  
 184  188          return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc);
 185  189  }
 186  190  #endif  /* _KERNEL */
 187  191  
 188  192  /*
 189  193   * Executes map and unmap command for shares.
 190  194   */
 191  195  int
 192  196  smb_kshare_exec(smb_server_t *sv, smb_shr_execinfo_t *execinfo)
 193  197  {
 194  198          int exec_rc = 0;
 195  199  
 196  200          (void) smb_kdoor_upcall(sv, SMB_DR_SHR_EXEC,
 197  201              execinfo, smb_shr_execinfo_xdr, &exec_rc, xdr_int);
 198  202  
 199  203          return (exec_rc);
 200  204  }
 201  205  
 202  206  /*
 203  207   * Obtains any host access restriction on the specified
 204  208   * share for the given host (ipaddr) by calling smbd
 205  209   */
 206  210  uint32_t
 207  211  smb_kshare_hostaccess(smb_kshare_t *shr, smb_session_t *session)
 208  212  {
 209  213          smb_shr_hostaccess_query_t req;
 210  214          smb_inaddr_t *ipaddr = &session->ipaddr;
 211  215          uint32_t host_access = SMB_SHRF_ACC_OPEN;
 212  216          uint32_t flag = SMB_SHRF_ACC_OPEN;
 213  217          uint32_t access;
 214  218  
 215  219          if (smb_inet_iszero(ipaddr))
 216  220                  return (ACE_ALL_PERMS);
 217  221  
 218  222          if ((shr->shr_access_none == NULL || *shr->shr_access_none == '\0') &&
 219  223              (shr->shr_access_ro == NULL || *shr->shr_access_ro == '\0') &&
 220  224              (shr->shr_access_rw == NULL || *shr->shr_access_rw == '\0'))
 221  225                  return (ACE_ALL_PERMS);
 222  226  
 223  227          if (shr->shr_access_none != NULL)
 224  228                  flag |= SMB_SHRF_ACC_NONE;
 225  229          if (shr->shr_access_ro != NULL)
 226  230                  flag |= SMB_SHRF_ACC_RO;
 227  231          if (shr->shr_access_rw != NULL)
 228  232                  flag |= SMB_SHRF_ACC_RW;
 229  233  
 230  234          req.shq_none = shr->shr_access_none;
 231  235          req.shq_ro = shr->shr_access_ro;
 232  236          req.shq_rw = shr->shr_access_rw;
 233  237          req.shq_flag = flag;
 234  238          req.shq_ipaddr = *ipaddr;
 235  239  
 236  240          (void) smb_kdoor_upcall(session->s_server, SMB_DR_SHR_HOSTACCESS,
 237  241              &req, smb_shr_hostaccess_query_xdr, &host_access, xdr_uint32_t);
 238  242  
 239  243          switch (host_access) {
 240  244          case SMB_SHRF_ACC_RO:
 241  245                  access = ACE_ALL_PERMS & ~ACE_ALL_WRITE_PERMS;
 242  246                  break;
 243  247          case SMB_SHRF_ACC_OPEN:
 244  248          case SMB_SHRF_ACC_RW:
 245  249                  access = ACE_ALL_PERMS;
 246  250                  break;
 247  251          case SMB_SHRF_ACC_NONE:
 248  252          default:
 249  253                  access = 0;
 250  254          }
 251  255  
 252  256          return (access);
 253  257  }
 254  258  
 255  259  /*
 256  260   * This function is called when smb_server_t is
 257  261   * created which means smb/service is ready for
 258  262   * exporting SMB shares
 259  263   */
 260  264  void
 261  265  smb_export_start(smb_server_t *sv)
 262  266  {
 263  267          mutex_enter(&sv->sv_export.e_mutex);
 264  268          if (sv->sv_export.e_ready) {
 265  269                  mutex_exit(&sv->sv_export.e_mutex);
 266  270                  return;
 267  271          }
 268  272  
 269  273          sv->sv_export.e_ready = B_TRUE;
 270  274          mutex_exit(&sv->sv_export.e_mutex);
 271  275  
 272  276          smb_avl_create(&sv->sv_export.e_share_avl, sizeof (smb_kshare_t),
 273  277              offsetof(smb_kshare_t, shr_link), &smb_kshare_avlops);
 274  278  
 275  279          (void) smb_kshare_export_trans(sv, "IPC$", "IPC$", "Remote IPC");
 276  280          (void) smb_kshare_export_trans(sv, "c$", SMB_CVOL, "Default Share");
 277  281          (void) smb_kshare_export_trans(sv, "vss$", SMB_VSS, "VSS");
 278  282  }
 279  283  
 280  284  /*
 281  285   * This function is called when smb_server_t goes
 282  286   * away which means SMB shares should not be made
 283  287   * available to clients
 284  288   */
 285  289  void
 286  290  smb_export_stop(smb_server_t *sv)
  
    | 
      ↓ open down ↓ | 
    222 lines elided | 
    
      ↑ open up ↑ | 
  
 287  291  {
 288  292          mutex_enter(&sv->sv_export.e_mutex);
 289  293          if (!sv->sv_export.e_ready) {
 290  294                  mutex_exit(&sv->sv_export.e_mutex);
 291  295                  return;
 292  296          }
 293  297          sv->sv_export.e_ready = B_FALSE;
 294  298          mutex_exit(&sv->sv_export.e_mutex);
 295  299  
 296  300          smb_avl_destroy(&sv->sv_export.e_share_avl);
 297      -        smb_vfs_rele_all(&sv->sv_export);
 298  301  }
 299  302  
 300  303  void
 301  304  smb_kshare_g_init(void)
 302  305  {
 303  306          smb_kshare_cache_share = kmem_cache_create("smb_share_cache",
 304  307              sizeof (smb_kshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 305  308  
 306  309          smb_kshare_cache_unexport = kmem_cache_create("smb_unexport_cache",
 307  310              sizeof (smb_unshare_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 308      -
 309      -        smb_kshare_cache_vfs = kmem_cache_create("smb_vfs_cache",
 310      -            sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 311  311  }
 312  312  
 313  313  void
 314  314  smb_kshare_init(smb_server_t *sv)
 315  315  {
 316  316  
 317      -        smb_llist_constructor(&sv->sv_export.e_vfs_list, sizeof (smb_vfs_t),
 318      -            offsetof(smb_vfs_t, sv_lnd));
 319      -
 320  317          smb_slist_constructor(&sv->sv_export.e_unexport_list,
 321  318              sizeof (smb_unshare_t), offsetof(smb_unshare_t, us_lnd));
 322  319  }
 323  320  
 324  321  int
 325  322  smb_kshare_start(smb_server_t *sv)
 326  323  {
 327  324          smb_thread_init(&sv->sv_export.e_unexport_thread, "smb_kshare_unexport",
 328  325              smb_kshare_unexport_thread, sv, smbsrv_base_pri);
 329  326  
 330  327          return (smb_thread_start(&sv->sv_export.e_unexport_thread));
 331  328  }
 332  329  
 333  330  void
 334  331  smb_kshare_stop(smb_server_t *sv)
 335  332  {
 336  333          smb_thread_stop(&sv->sv_export.e_unexport_thread);
 337  334          smb_thread_destroy(&sv->sv_export.e_unexport_thread);
 338  335  }
 339  336  
 340  337  void
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
 341  338  smb_kshare_fini(smb_server_t *sv)
 342  339  {
 343  340          smb_unshare_t *ux;
 344  341  
 345  342          while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
 346  343              != NULL) {
 347  344                  smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
 348  345                  kmem_cache_free(smb_kshare_cache_unexport, ux);
 349  346          }
 350  347          smb_slist_destructor(&sv->sv_export.e_unexport_list);
 351      -
 352      -        smb_vfs_rele_all(&sv->sv_export);
 353      -
 354      -        smb_llist_destructor(&sv->sv_export.e_vfs_list);
 355  348  }
 356  349  
 357  350  void
 358  351  smb_kshare_g_fini(void)
 359  352  {
 360  353          kmem_cache_destroy(smb_kshare_cache_unexport);
 361  354          kmem_cache_destroy(smb_kshare_cache_share);
 362      -        kmem_cache_destroy(smb_kshare_cache_vfs);
 363  355  }
 364  356  
 365  357  /*
 366  358   * A list of shares in nvlist format can be sent down
 367  359   * from userspace thourgh the IOCTL interface. The nvlist
 368  360   * is unpacked here and all the shares in the list will
 369  361   * be exported.
 370  362   */
 371  363  int
 372  364  smb_kshare_export_list(smb_ioc_share_t *ioc)
 373  365  {
 374  366          smb_server_t    *sv = NULL;
 375  367          nvlist_t        *shrlist = NULL;
 376  368          nvlist_t         *share;
 377  369          nvpair_t         *nvp;
 378  370          smb_kshare_t     *shr;
 379  371          char            *shrname;
 380  372          int             rc;
 381  373  
 382  374          if ((rc = smb_server_lookup(&sv)) != 0)
 383  375                  return (rc);
 384  376  
 385  377          if (!smb_export_isready(sv)) {
 386  378                  rc = ENOTACTIVE;
 387  379                  goto out;
 388  380          }
 389  381  
 390  382          /*
 391  383           * Reality check that the nvlist's reported length doesn't exceed the
 392  384           * ioctl's total length.  We then assume the nvlist_unpack() will
 393  385           * sanity check the nvlist itself.
 394  386           */
 395  387          if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) {
 396  388                  rc = EINVAL;
 397  389                  goto out;
 398  390          }
 399  391          rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP);
 400  392          if (rc != 0)
 401  393                  goto out;
 402  394  
 403  395          for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL;
 404  396              nvp = nvlist_next_nvpair(shrlist, nvp)) {
 405  397  
 406  398                  /*
 407  399                   * Since this loop can run for a while we want to exit
 408  400                   * as soon as the server state is anything but RUNNING
 409  401                   * to allow shutdown to proceed.
 410  402                   */
 411  403                  if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
 412  404                          goto out;
 413  405  
 414  406                  if (nvpair_type(nvp) != DATA_TYPE_NVLIST)
 415  407                          continue;
 416  408  
 417  409                  shrname = nvpair_name(nvp);
 418  410                  ASSERT(shrname);
 419  411  
 420  412                  if ((rc = nvpair_value_nvlist(nvp, &share)) != 0) {
 421  413                          cmn_err(CE_WARN, "export[%s]: failed accessing",
 422  414                              shrname);
 423  415                          continue;
 424  416                  }
 425  417  
 426  418                  if ((shr = smb_kshare_decode(share)) == NULL) {
 427  419                          cmn_err(CE_WARN, "export[%s]: failed decoding",
 428  420                              shrname);
 429  421                          continue;
 430  422                  }
 431  423  
 432  424                  /* smb_kshare_export consumes shr so it's not leaked */
 433  425                  if ((rc = smb_kshare_export(sv, shr)) != 0) {
 434  426                          smb_kshare_destroy(shr);
 435  427                          continue;
 436  428                  }
 437  429          }
 438  430          rc = 0;
 439  431  
 440  432  out:
 441  433          nvlist_free(shrlist);
 442  434          smb_server_release(sv);
 443  435          return (rc);
 444  436  }
 445  437  
 446  438  /*
 447  439   * This function is invoked when a share is disabled to disconnect trees
 448  440   * and close files.  Cleaning up may involve VOP and/or VFS calls, which
 449  441   * may conflict/deadlock with stuck threads if something is amiss with the
 450  442   * file system.  Queueing the request for asynchronous processing allows the
 451  443   * call to return immediately so that, if the unshare is being done in the
 452  444   * context of a forced unmount, the forced unmount will always be able to
 453  445   * proceed (unblocking stuck I/O and eventually allowing all blocked unshare
 454  446   * processes to complete).
 455  447   *
 456  448   * The path lookup to find the root vnode of the VFS in question and the
 457  449   * release of this vnode are done synchronously prior to any associated
 458  450   * unmount.  Doing these asynchronous to an associated unmount could run
 459  451   * the risk of a spurious EBUSY for a standard unmount or an EIO during
 460  452   * the path lookup due to a forced unmount finishing first.
 461  453   */
 462  454  int
 463  455  smb_kshare_unexport_list(smb_ioc_share_t *ioc)
 464  456  {
 465  457          smb_server_t    *sv = NULL;
 466  458          smb_unshare_t   *ux;
 467  459          nvlist_t        *shrlist = NULL;
 468  460          nvpair_t        *nvp;
 469  461          boolean_t       unexport = B_FALSE;
 470  462          char            *shrname;
 471  463          int             rc;
 472  464  
 473  465          if ((rc = smb_server_lookup(&sv)) != 0)
 474  466                  return (rc);
 475  467  
 476  468          /*
 477  469           * Reality check that the nvlist's reported length doesn't exceed the
 478  470           * ioctl's total length.  We then assume the nvlist_unpack() will
 479  471           * sanity check the nvlist itself.
 480  472           */
 481  473          if ((ioc->shrlen + offsetof(smb_ioc_share_t, shr)) > ioc->hdr.len) {
 482  474                  rc = EINVAL;
 483  475                  goto out;
 484  476          }
 485  477          if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, 0)) != 0)
 486  478                  goto out;
 487  479  
 488  480          for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL;
 489  481              nvp = nvlist_next_nvpair(shrlist, nvp)) {
 490  482                  if (nvpair_type(nvp) != DATA_TYPE_NVLIST)
 491  483                          continue;
 492  484  
 493  485                  shrname = nvpair_name(nvp);
 494  486                  ASSERT(shrname);
 495  487  
 496  488                  if ((rc = smb_kshare_unexport(sv, shrname)) != 0)
 497  489                          continue;
 498  490  
 499  491                  ux = kmem_cache_alloc(smb_kshare_cache_unexport, KM_SLEEP);
 500  492                  (void) strlcpy(ux->us_sharename, shrname, MAXNAMELEN);
 501  493  
 502  494                  smb_slist_insert_tail(&sv->sv_export.e_unexport_list, ux);
 503  495                  unexport = B_TRUE;
 504  496          }
 505  497  
 506  498          if (unexport)
 507  499                  smb_thread_signal(&sv->sv_export.e_unexport_thread);
 508  500          rc = 0;
 509  501  
 510  502  out:
 511  503          nvlist_free(shrlist);
 512  504          smb_server_release(sv);
 513  505          return (rc);
 514  506  }
 515  507  
 516  508  /*
 517  509   * Get properties (currently only shortname enablement)
 518  510   * of specified share.
 519  511   */
 520  512  int
 521  513  smb_kshare_info(smb_ioc_shareinfo_t *ioc)
 522  514  {
 523  515          ioc->shortnames = smb_shortnames;
 524  516          return (0);
 525  517  }
 526  518  
 527  519  /*
 528  520   * This function builds a response for a NetShareEnum RAP request.
 529  521   * List of shares is scanned twice. In the first round the total number
 530  522   * of shares which their OEM name is shorter than 13 chars (esi->es_ntotal)
 531  523   * and also the number of shares that fit in the given buffer are calculated.
 532  524   * In the second round the shares data are encoded in the buffer.
 533  525   *
 534  526   * The data associated with each share has two parts, a fixed size part and
 535  527   * a variable size part which is share's comment. The outline of the response
 536  528   * buffer is so that fixed part for all the shares will appear first and follows
 537  529   * with the comments for all those shares and that's why the data cannot be
 538  530   * encoded in one round without unnecessarily complicating the code.
 539  531   */
 540  532  void
 541  533  smb_kshare_enum(smb_server_t *sv, smb_enumshare_info_t *esi)
 542  534  {
 543  535          smb_avl_t *share_avl;
 544  536          smb_avl_cursor_t cursor;
 545  537          smb_kshare_t *shr;
 546  538          int remained;
 547  539          uint16_t infolen = 0;
 548  540          uint16_t cmntlen = 0;
 549  541          uint16_t sharelen;
 550  542          uint16_t clen;
 551  543          uint32_t cmnt_offs;
 552  544          smb_msgbuf_t info_mb;
 553  545          smb_msgbuf_t cmnt_mb;
 554  546          boolean_t autohome_added = B_FALSE;
 555  547  
 556  548          if (!smb_export_isready(sv)) {
 557  549                  esi->es_ntotal = esi->es_nsent = 0;
 558  550                  esi->es_datasize = 0;
 559  551                  return;
 560  552          }
 561  553  
 562  554          esi->es_ntotal = esi->es_nsent = 0;
 563  555          remained = esi->es_bufsize;
 564  556          share_avl = &sv->sv_export.e_share_avl;
 565  557  
 566  558          /* Do the necessary calculations in the first round */
 567  559          smb_avl_iterinit(share_avl, &cursor);
 568  560  
 569  561          while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) {
 570  562                  if (shr->shr_oemname == NULL) {
 571  563                          smb_avl_release(share_avl, shr);
 572  564                          continue;
 573  565                  }
 574  566  
 575  567                  if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
 576  568                          if (esi->es_posix_uid == shr->shr_uid) {
 577  569                                  autohome_added = B_TRUE;
 578  570                          } else {
 579  571                                  smb_avl_release(share_avl, shr);
 580  572                                  continue;
 581  573                          }
 582  574                  }
 583  575  
 584  576                  esi->es_ntotal++;
 585  577  
 586  578                  if (remained <= 0) {
 587  579                          smb_avl_release(share_avl, shr);
 588  580                          continue;
 589  581                  }
 590  582  
 591  583                  clen = strlen(shr->shr_cmnt) + 1;
 592  584                  sharelen = SHARE_INFO_1_SIZE + clen;
 593  585  
 594  586                  if (sharelen <= remained) {
 595  587                          infolen += SHARE_INFO_1_SIZE;
 596  588                          cmntlen += clen;
 597  589                  }
 598  590  
 599  591                  remained -= sharelen;
 600  592                  smb_avl_release(share_avl, shr);
 601  593          }
 602  594  
 603  595          esi->es_datasize = infolen + cmntlen;
 604  596  
 605  597          smb_msgbuf_init(&info_mb, (uint8_t *)esi->es_buf, infolen, 0);
 606  598          smb_msgbuf_init(&cmnt_mb, (uint8_t *)esi->es_buf + infolen, cmntlen, 0);
 607  599          cmnt_offs = infolen;
 608  600  
 609  601          /* Encode the data in the second round */
 610  602          smb_avl_iterinit(share_avl, &cursor);
 611  603          autohome_added = B_FALSE;
 612  604  
 613  605          while ((shr = smb_avl_iterate(share_avl, &cursor)) != NULL) {
 614  606                  if (shr->shr_oemname == NULL) {
 615  607                          smb_avl_release(share_avl, shr);
 616  608                          continue;
 617  609                  }
 618  610  
 619  611                  if ((shr->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) {
 620  612                          if (esi->es_posix_uid == shr->shr_uid) {
 621  613                                  autohome_added = B_TRUE;
 622  614                          } else {
 623  615                                  smb_avl_release(share_avl, shr);
 624  616                                  continue;
 625  617                          }
 626  618                  }
 627  619  
 628  620                  if (smb_msgbuf_encode(&info_mb, "13c.wl",
 629  621                      shr->shr_oemname, shr->shr_type, cmnt_offs) < 0) {
 630  622                          smb_avl_release(share_avl, shr);
 631  623                          break;
 632  624                  }
 633  625  
 634  626                  if (smb_msgbuf_encode(&cmnt_mb, "s", shr->shr_cmnt) < 0) {
 635  627                          smb_avl_release(share_avl, shr);
 636  628                          break;
 637  629                  }
 638  630  
 639  631                  cmnt_offs += strlen(shr->shr_cmnt) + 1;
 640  632                  esi->es_nsent++;
 641  633  
 642  634                  smb_avl_release(share_avl, shr);
 643  635          }
 644  636  
 645  637          smb_msgbuf_term(&info_mb);
 646  638          smb_msgbuf_term(&cmnt_mb);
 647  639  }
 648  640  
 649  641  /*
 650  642   * Looks up the given share and returns a pointer
 651  643   * to its definition if it's found. A hold on the
 652  644   * object is taken before the pointer is returned
 653  645   * in which case the caller MUST always call
 654  646   * smb_kshare_release().
 655  647   */
 656  648  smb_kshare_t *
 657  649  smb_kshare_lookup(smb_server_t *sv, const char *shrname)
 658  650  {
 659  651          smb_kshare_t key;
 660  652          smb_kshare_t *shr;
 661  653  
 662  654          ASSERT(shrname);
 663  655  
 664  656          if (!smb_export_isready(sv))
 665  657                  return (NULL);
 666  658  
 667  659          key.shr_name = (char *)shrname;
 668  660          shr = smb_avl_lookup(&sv->sv_export.e_share_avl, &key);
 669  661          return (shr);
 670  662  }
 671  663  
 672  664  /*
 673  665   * Releases the hold taken on the specified share object
 674  666   */
 675  667  void
  
    | 
      ↓ open down ↓ | 
    303 lines elided | 
    
      ↑ open up ↑ | 
  
 676  668  smb_kshare_release(smb_server_t *sv, smb_kshare_t *shr)
 677  669  {
 678  670          ASSERT(shr);
 679  671          ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
 680  672  
 681  673          smb_avl_release(&sv->sv_export.e_share_avl, shr);
 682  674  }
 683  675  
 684  676  /*
 685  677   * Add the given share in the specified server.
 686      - * If the share is a disk share, smb_vfs_hold() is
 687      - * invoked to ensure that there is a hold on the
 688      - * corresponding file system before the share is
 689      - * added to shares AVL.
      678 + * If the share is a disk share, lookup the share path
      679 + * and hold the smb_node_t for the share root.
 690  680   *
 691  681   * If the share is an Autohome share and it is
 692  682   * already in the AVL only a reference count for
 693  683   * that share is incremented.
 694  684   */
 695  685  static int
 696  686  smb_kshare_export(smb_server_t *sv, smb_kshare_t *shr)
 697  687  {
 698  688          smb_avl_t       *share_avl;
 699  689          smb_kshare_t    *auto_shr;
 700      -        vnode_t         *vp;
      690 +        smb_node_t      *snode = NULL;
 701  691          int             rc = 0;
 702  692  
 703  693          share_avl = &sv->sv_export.e_share_avl;
 704  694  
 705  695          if (!STYPE_ISDSK(shr->shr_type)) {
 706  696                  if ((rc = smb_avl_add(share_avl, shr)) != 0) {
 707  697                          cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
 708  698                              shr->shr_name, rc);
 709  699                  }
 710  700  
 711  701                  return (rc);
 712  702          }
 713  703  
 714  704          if ((auto_shr = smb_avl_lookup(share_avl, shr)) != NULL) {
 715      -                if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) == 0) {
 716      -                        smb_avl_release(share_avl, auto_shr);
 717      -                        return (EEXIST);
      705 +                rc = EEXIST;
      706 +                if ((auto_shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
      707 +                        mutex_enter(&auto_shr->shr_mutex);
      708 +                        auto_shr->shr_autocnt++;
      709 +                        mutex_exit(&auto_shr->shr_mutex);
      710 +                        rc = 0;
 718  711                  }
 719      -
 720      -                mutex_enter(&auto_shr->shr_mutex);
 721      -                auto_shr->shr_autocnt++;
 722      -                mutex_exit(&auto_shr->shr_mutex);
 723  712                  smb_avl_release(share_avl, auto_shr);
 724      -                return (0);
      713 +                return (rc);
 725  714          }
 726  715  
 727      -        if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) {
 728      -                cmn_err(CE_WARN, "export[%s(%s)]: failed obtaining vnode (%d)",
      716 +        /*
      717 +         * Get the root smb_node_t for this share, held.
      718 +         * This hold is normally released during AVL destroy,
      719 +         * via the element destructor:  smb_kshare_destroy
      720 +         */
      721 +        rc = smb_server_share_lookup(sv, shr->shr_path, &snode);
      722 +        if (rc != 0) {
      723 +                cmn_err(CE_WARN, "export[%s(%s)]: lookup failed (%d)",
 729  724                      shr->shr_name, shr->shr_path, rc);
 730  725                  return (rc);
 731  726          }
 732  727  
 733      -        if ((rc = smb_vfs_hold(&sv->sv_export, vp->v_vfsp)) == 0) {
 734      -                if ((rc = smb_avl_add(share_avl, shr)) != 0) {
 735      -                        cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
 736      -                            shr->shr_name, rc);
 737      -                        smb_vfs_rele(&sv->sv_export, vp->v_vfsp);
      728 +        shr->shr_root_node = snode;
      729 +        if ((rc = smb_avl_add(share_avl, shr)) != 0) {
      730 +                cmn_err(CE_WARN, "export[%s]: failed caching (%d)",
      731 +                    shr->shr_name, rc);
      732 +                shr->shr_root_node = NULL;
      733 +                smb_node_release(snode);
      734 +                return (rc);
      735 +        }
      736 +
      737 +        kshare_stats_init(sv, shr);
      738 +
      739 +        /*
      740 +         * For CA shares, find or create the CA handle dir,
      741 +         * and (if restarted) import persistent handles.
      742 +         */
      743 +        if ((shr->shr_flags & SMB_SHRF_CA) != 0) {
      744 +                rc = smb2_dh_new_ca_share(sv, shr);
      745 +                if (rc != 0) {
      746 +                        /* Just make it a non-CA share. */
      747 +                        mutex_enter(&shr->shr_mutex);
      748 +                        shr->shr_flags &= ~SMB_SHRF_CA;
      749 +                        mutex_exit(&shr->shr_mutex);
      750 +                        rc = 0;
 738  751                  }
 739      -        } else {
 740      -                cmn_err(CE_WARN, "export[%s(%s)]: failed holding VFS (%d)",
 741      -                    shr->shr_name, shr->shr_path, rc);
 742  752          }
 743  753  
 744      -        VN_RELE(vp);
 745  754          return (rc);
 746  755  }
 747  756  
      757 +
 748  758  /*
      759 + * Following a pattern somewhat similar to smb_server_kstat_init,
      760 + * but organized a little differently.
      761 + */
      762 +void
      763 +kshare_stats_init(smb_server_t *sv, smb_kshare_t *ks)
      764 +{
      765 +        static const char       *kr_names[] = SMBSRV_CLSH__NAMES;
      766 +        char                    ks_name[KSTAT_STRLEN];
      767 +        smbsrv_clsh_kstats_t    *ksr;
      768 +        int                     idx;
      769 +        smb_named_stats_t       *smbnsp;
      770 +        kstat_t                 *kstat = NULL;
      771 +        int                     namelen;
      772 +
      773 +        /*
      774 +         * Most share names are short, and we'd like to allow consumers like
      775 +         * the smbstat command to compose the kstat names for short share names
      776 +         * directly.  In the (rare) case where we have longer share names, we
      777 +         * need an indirection scheme to get around the limited (31 chars) size
      778 +         * of kstat names. So for share names 24 chars or shorter, we compose
      779 +         * the kstat name directly as "smbsrv:0:sh/sharename" and when the share
      780 +         * name is longer, compose the kstat name using an arbitrary
      781 +         * (but unique) identifier like: "smbsrv:0:sh/:ffffff0009560a98".  To
      782 +         * find the unique identifier given a (long) share name, the consumer
      783 +         * has to enumerate the (fake) "smbsrvshr" kstat module, looking for the
      784 +         * kstat with the sharename element matching the one they want.  Both
      785 +         * direct and indirect names are instantiated under the "smbsrvshr"
      786 +         * module, so a consumer that wants all the share kstats could always
      787 +         * lookup the kstat names using the indirection scheme if that's easier.
      788 +         * (Nothing forces the consumer to directly compose kstat names when the
      789 +         * share name happens to be short -- they can always enumerate to find
      790 +         * it.)
      791 +         *
      792 +         * SMB share names are not allowed to contain a colon.  The naming
      793 +         * scheme here uses a colon at the beginning of what would otherwise be
      794 +         * the share name part of the kstat name to indicate that this name uses
      795 +         * the "indirection" scheme.  With indirection, the part after the colon
      796 +         * is an arbitrary (but unique per share) identifier of some other
      797 +         * kstat, and a consumer needs to fetch that kstat to get the real share
      798 +         * name.
      799 +         */
      800 +        namelen = strlen(ks->shr_name);
      801 +        if (namelen <= 24) {
      802 +                (void) snprintf(ks_name, sizeof (ks_name), "sh/%s",
      803 +                    ks->shr_name);
      804 +
      805 +                kstat = kstat_hold_byname("smbsrvshr", 0, ks_name, sv->sv_zid);
      806 +        }
      807 +
      808 +        if (namelen > 24 || kstat != NULL) {
      809 +                (void) snprintf(ks_name, sizeof (ks_name), "sh/:%p",
      810 +                    (void *)ks);
      811 +
      812 +                if (kstat != NULL)
      813 +                        kstat_rele(kstat);
      814 +        }
      815 +
      816 +        ks->shr_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0,
      817 +            ks_name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW,
      818 +            sizeof (smbsrv_clsh_kstats_t), 0, sv->sv_zid);
      819 +
      820 +        if (ks->shr_ksp == NULL)
      821 +                return;
      822 +
      823 +        ks->stats.ksns = kstat_create_zone("smbsrvshr", 0,
      824 +            ks_name, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED,
      825 +            0, KSTAT_FLAG_VIRTUAL, sv->sv_zid);
      826 +
      827 +        if (ks->stats.ksns == NULL) {
      828 +                kstat_delete(ks->shr_ksp);
      829 +                ks->shr_ksp = NULL;
      830 +                return;
      831 +        }
      832 +
      833 +        ks->shr_ksp->ks_update = smb_kshare_kstat_update;
      834 +        ks->shr_ksp->ks_private = ks;
      835 +
      836 +        /*
      837 +         * In-line equivalent of smb_dispatch_stats_init
      838 +         */
      839 +        ksr = (smbsrv_clsh_kstats_t *)ks->shr_ksp->ks_data;
      840 +        for (idx = 0; idx < SMBSRV_CLSH__NREQ; idx++) {
      841 +                smb_latency_init(&ks->shr_stats[idx].sdt_lat);
      842 +                (void) strlcpy(ksr->ks_clsh[idx].kr_name, kr_names[idx],
      843 +                    KSTAT_STRLEN);
      844 +        }
      845 +
      846 +        /*
      847 +         * SMB named kstats setup for > KSTAT_STRLEN name to short name mapping.
      848 +         */
      849 +        smbnsp = &ks->stats.ks_data;
      850 +        ks->stats.ksns->ks_data = &ks->stats.ks_data;
      851 +        ks->stats.ksns->ks_data_size = sizeof (ks->stats.ks_data);
      852 +        ks->stats.ksns->ks_ndata = 1;
      853 +        kstat_named_init(smbnsp->kn, "share name",
      854 +            KSTAT_DATA_STRING);
      855 +        ks->stats.ksns->ks_update = smb_named_kstat_update;
      856 +        ks->stats.ksns->ks_private = (void *)ks;
      857 +
      858 +        kstat_install(ks->shr_ksp);
      859 +        kstat_install(ks->stats.ksns);
      860 +}
      861 +
      862 +void
      863 +kshare_stats_fini(smb_kshare_t *ks)
      864 +{
      865 +        int idx;
      866 +
      867 +        for (idx = 0; idx < SMBSRV_CLSH__NREQ; idx++)
      868 +                smb_latency_destroy(&ks->shr_stats[idx].sdt_lat);
      869 +}
      870 +
      871 +static int
      872 +smb_named_kstat_update(kstat_t *ks, int rw)
      873 +{
      874 +        smb_kshare_t            *smbksp = (smb_kshare_t *)ks->ks_private;
      875 +        smb_named_stats_t       *smbnsp = &smbksp->stats.ks_data;
      876 +
      877 +        if (rw == KSTAT_READ) {
      878 +                (void) strlcpy(smbnsp->name, smbksp->shr_name,
      879 +                    sizeof (smbnsp->name));
      880 +
      881 +                kstat_named_setstr(&smbnsp->kn[0],
      882 +                    (const char *)smbksp->shr_name);
      883 +        }
      884 +        return (0);
      885 +}
      886 +
      887 +/*
      888 + * Update the kstat data from our private stats.
      889 + */
      890 +static int
      891 +smb_kshare_kstat_update(kstat_t *ksp, int rw)
      892 +{
      893 +        smb_kshare_t *kshare;
      894 +        smb_disp_stats_t *sds;
      895 +        smbsrv_clsh_kstats_t    *clsh;
      896 +        smb_kstat_req_t *ksr;
      897 +        int i;
      898 +
      899 +        if (rw == KSTAT_WRITE)
      900 +                return (EACCES);
      901 +
      902 +        kshare = ksp->ks_private;
      903 +        ASSERT(kshare->shr_magic == SMB_SHARE_MAGIC);
      904 +        sds = kshare->shr_stats;
      905 +
      906 +        clsh = (smbsrv_clsh_kstats_t *)ksp->ks_data;
      907 +        ksr = clsh->ks_clsh;
      908 +
      909 +        for (i = 0; i < SMBSRV_CLSH__NREQ; i++, ksr++, sds++) {
      910 +                ksr->kr_rxb = sds->sdt_rxb;
      911 +                ksr->kr_txb = sds->sdt_txb;
      912 +                mutex_enter(&sds->sdt_lat.ly_mutex);
      913 +                ksr->kr_nreq = sds->sdt_lat.ly_a_nreq;
      914 +                ksr->kr_sum = sds->sdt_lat.ly_a_sum;
      915 +                ksr->kr_a_mean = sds->sdt_lat.ly_a_mean;
      916 +                ksr->kr_a_stddev = sds->sdt_lat.ly_a_stddev;
      917 +                ksr->kr_d_mean = sds->sdt_lat.ly_d_mean;
      918 +                ksr->kr_d_stddev = sds->sdt_lat.ly_d_stddev;
      919 +                sds->sdt_lat.ly_d_mean = 0;
      920 +                sds->sdt_lat.ly_d_nreq = 0;
      921 +                sds->sdt_lat.ly_d_stddev = 0;
      922 +                sds->sdt_lat.ly_d_sum = 0;
      923 +                mutex_exit(&sds->sdt_lat.ly_mutex);
      924 +        }
      925 +
      926 +        return (0);
      927 +}
      928 +
      929 +/*
 749  930   * Removes the share specified by 'shrname' from the AVL
 750  931   * tree of the given server if it's there.
 751  932   *
 752  933   * If the share is an Autohome share, the autohome count
 753  934   * is decremented and the share is only removed if the
 754  935   * count goes to zero.
 755  936   *
 756  937   * If the share is a disk share, the hold on the corresponding
 757  938   * file system is released before removing the share from
 758  939   * the AVL tree.
 759  940   */
 760  941  static int
 761  942  smb_kshare_unexport(smb_server_t *sv, const char *shrname)
 762  943  {
 763  944          smb_avl_t       *share_avl;
 764  945          smb_kshare_t    key;
 765  946          smb_kshare_t    *shr;
 766      -        vnode_t         *vp;
 767      -        int             rc;
 768  947          boolean_t       auto_unexport;
 769  948  
 770  949          share_avl = &sv->sv_export.e_share_avl;
 771  950  
 772  951          key.shr_name = (char *)shrname;
 773  952          if ((shr = smb_avl_lookup(share_avl, &key)) == NULL)
 774  953                  return (ENOENT);
 775  954  
 776  955          if ((shr->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
 777  956                  mutex_enter(&shr->shr_mutex);
 778  957                  shr->shr_autocnt--;
 779  958                  auto_unexport = (shr->shr_autocnt == 0);
 780  959                  mutex_exit(&shr->shr_mutex);
 781  960                  if (!auto_unexport) {
 782  961                          smb_avl_release(share_avl, shr);
 783  962                          return (0);
 784  963                  }
 785  964          }
 786  965  
 787      -        if (STYPE_ISDSK(shr->shr_type)) {
 788      -                if ((rc = smb_server_sharevp(sv, shr->shr_path, &vp)) != 0) {
 789      -                        smb_avl_release(share_avl, shr);
 790      -                        cmn_err(CE_WARN, "unexport[%s]: failed obtaining vnode"
 791      -                            " (%d)", shrname, rc);
 792      -                        return (rc);
 793      -                }
      966 +        smb_avl_remove(share_avl, shr);
 794  967  
 795      -                smb_vfs_rele(&sv->sv_export, vp->v_vfsp);
 796      -                VN_RELE(vp);
 797      -        }
      968 +        mutex_enter(&shr->shr_mutex);
      969 +        shr->shr_flags |= SMB_SHRF_REMOVED;
      970 +        mutex_exit(&shr->shr_mutex);
 798  971  
 799      -        smb_avl_remove(share_avl, shr);
 800  972          smb_avl_release(share_avl, shr);
 801  973  
 802  974          return (0);
 803  975  }
 804  976  
 805  977  /*
 806  978   * Exports IPC$ or Admin shares
 807  979   */
 808  980  static int
 809  981  smb_kshare_export_trans(smb_server_t *sv, char *name, char *path, char *cmnt)
 810  982  {
 811  983          smb_kshare_t *shr;
 812  984  
 813  985          ASSERT(name);
 814  986          ASSERT(path);
 815  987  
 816  988          shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
 817  989          bzero(shr, sizeof (smb_kshare_t));
 818  990  
 819  991          shr->shr_magic = SMB_SHARE_MAGIC;
 820  992          shr->shr_refcnt = 1;
 821  993          shr->shr_flags = SMB_SHRF_TRANS | smb_kshare_is_admin(shr->shr_name);
 822  994          if (strcasecmp(name, "IPC$") == 0)
 823  995                  shr->shr_type = STYPE_IPC;
 824  996          else
 825  997                  shr->shr_type = STYPE_DISKTREE;
 826  998  
 827  999          shr->shr_type |= smb_kshare_is_special(shr->shr_name);
 828 1000  
 829 1001          shr->shr_name = smb_mem_strdup(name);
 830 1002          if (path)
 831 1003                  shr->shr_path = smb_mem_strdup(path);
 832 1004          if (cmnt)
 833 1005                  shr->shr_cmnt = smb_mem_strdup(cmnt);
 834 1006          shr->shr_oemname = smb_kshare_oemname(name);
 835 1007  
 836 1008          return (smb_kshare_export(sv, shr));
 837 1009  }
 838 1010  
 839 1011  /*
 840 1012   * Decodes share information in an nvlist format into a smb_kshare_t
 841 1013   * structure.
  
    | 
      ↓ open down ↓ | 
    32 lines elided | 
    
      ↑ open up ↑ | 
  
 842 1014   *
 843 1015   * This is a temporary function and will be replaced by functions
 844 1016   * provided by libsharev2 code after it's available.
 845 1017   */
 846 1018  static smb_kshare_t *
 847 1019  smb_kshare_decode(nvlist_t *share)
 848 1020  {
 849 1021          smb_kshare_t tmp;
 850 1022          smb_kshare_t *shr;
 851 1023          nvlist_t *smb;
 852      -        char *csc_name = NULL;
     1024 +        char *csc_name = NULL, *strbuf = NULL;
 853 1025          int rc;
 854 1026  
 855 1027          ASSERT(share);
 856 1028  
 857 1029          bzero(&tmp, sizeof (smb_kshare_t));
 858 1030  
 859 1031          rc = nvlist_lookup_string(share, "name", &tmp.shr_name);
 860 1032          rc |= nvlist_lookup_string(share, "path", &tmp.shr_path);
 861 1033          (void) nvlist_lookup_string(share, "desc", &tmp.shr_cmnt);
 862 1034  
 863 1035          ASSERT(tmp.shr_name && tmp.shr_path);
 864 1036  
 865 1037          rc |= nvlist_lookup_nvlist(share, "smb", &smb);
 866 1038          if (rc != 0) {
 867 1039                  cmn_err(CE_WARN, "kshare: failed looking up SMB properties"
 868 1040                      " (%d)", rc);
 869 1041                  return (NULL);
 870 1042          }
 871 1043  
 872 1044          rc = nvlist_lookup_uint32(smb, "type", &tmp.shr_type);
 873 1045          if (rc != 0) {
 874 1046                  cmn_err(CE_WARN, "kshare[%s]: failed getting the share type"
 875 1047                      " (%d)", tmp.shr_name, rc);
 876 1048                  return (NULL);
 877 1049          }
 878 1050  
 879 1051          (void) nvlist_lookup_string(smb, SHOPT_AD_CONTAINER,
 880 1052              &tmp.shr_container);
 881 1053          (void) nvlist_lookup_string(smb, SHOPT_NONE, &tmp.shr_access_none);
  
    | 
      ↓ open down ↓ | 
    19 lines elided | 
    
      ↑ open up ↑ | 
  
 882 1054          (void) nvlist_lookup_string(smb, SHOPT_RO, &tmp.shr_access_ro);
 883 1055          (void) nvlist_lookup_string(smb, SHOPT_RW, &tmp.shr_access_rw);
 884 1056  
 885 1057          tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_ABE, SMB_SHRF_ABE);
 886 1058          tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CATIA,
 887 1059              SMB_SHRF_CATIA);
 888 1060          tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_GUEST,
 889 1061              SMB_SHRF_GUEST_OK);
 890 1062          tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT,
 891 1063              SMB_SHRF_DFSROOT);
 892      -        tmp.shr_flags |= smb_kshare_decode_bool(smb, "Autohome",
     1064 +        tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_QUOTAS,
     1065 +            SMB_SHRF_QUOTAS);
     1066 +        tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_CA, SMB_SHRF_CA);
     1067 +        tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_FSO, SMB_SHRF_FSO);
     1068 +        tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_AUTOHOME,
 893 1069              SMB_SHRF_AUTOHOME);
 894 1070  
 895 1071          if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) {
 896 1072                  rc = nvlist_lookup_uint32(smb, "uid", &tmp.shr_uid);
 897 1073                  rc |= nvlist_lookup_uint32(smb, "gid", &tmp.shr_gid);
 898 1074                  if (rc != 0) {
 899 1075                          cmn_err(CE_WARN, "kshare: failed looking up uid/gid"
 900 1076                              " (%d)", rc);
 901 1077                          return (NULL);
 902 1078                  }
 903 1079          }
 904 1080  
     1081 +        (void) nvlist_lookup_string(smb, SHOPT_ENCRYPT, &strbuf);
     1082 +        smb_cfg_set_require(strbuf, &tmp.shr_encrypt);
     1083 +
 905 1084          (void) nvlist_lookup_string(smb, SHOPT_CSC, &csc_name);
 906 1085          smb_kshare_csc_flags(&tmp, csc_name);
 907 1086  
 908 1087          shr = kmem_cache_alloc(smb_kshare_cache_share, KM_SLEEP);
 909 1088          bzero(shr, sizeof (smb_kshare_t));
 910 1089  
 911 1090          shr->shr_magic = SMB_SHARE_MAGIC;
 912 1091          shr->shr_refcnt = 1;
 913 1092  
 914 1093          shr->shr_name = smb_mem_strdup(tmp.shr_name);
 915 1094          shr->shr_path = smb_mem_strdup(tmp.shr_path);
 916 1095          if (tmp.shr_cmnt)
 917 1096                  shr->shr_cmnt = smb_mem_strdup(tmp.shr_cmnt);
 918 1097          if (tmp.shr_container)
 919 1098                  shr->shr_container = smb_mem_strdup(tmp.shr_container);
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
 920 1099          if (tmp.shr_access_none)
 921 1100                  shr->shr_access_none = smb_mem_strdup(tmp.shr_access_none);
 922 1101          if (tmp.shr_access_ro)
 923 1102                  shr->shr_access_ro = smb_mem_strdup(tmp.shr_access_ro);
 924 1103          if (tmp.shr_access_rw)
 925 1104                  shr->shr_access_rw = smb_mem_strdup(tmp.shr_access_rw);
 926 1105  
 927 1106          shr->shr_oemname = smb_kshare_oemname(shr->shr_name);
 928 1107          shr->shr_flags = tmp.shr_flags | smb_kshare_is_admin(shr->shr_name);
 929 1108          shr->shr_type = tmp.shr_type | smb_kshare_is_special(shr->shr_name);
     1109 +        shr->shr_encrypt = tmp.shr_encrypt;
 930 1110  
 931 1111          shr->shr_uid = tmp.shr_uid;
 932 1112          shr->shr_gid = tmp.shr_gid;
 933 1113  
 934 1114          if ((shr->shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME)
 935 1115                  shr->shr_autocnt = 1;
 936      -
 937 1116          return (shr);
 938 1117  }
 939 1118  
 940 1119  #if 0
 941 1120  static void
 942 1121  smb_kshare_log(smb_kshare_t *shr)
 943 1122  {
 944 1123          cmn_err(CE_NOTE, "Share info:");
 945 1124          cmn_err(CE_NOTE, "\tname: %s", (shr->shr_name) ? shr->shr_name : "");
 946 1125          cmn_err(CE_NOTE, "\tpath: %s", (shr->shr_path) ? shr->shr_path : "");
 947 1126          cmn_err(CE_NOTE, "\tcmnt: (%s)",
 948 1127              (shr->shr_cmnt) ? shr->shr_cmnt : "NULL");
 949 1128          cmn_err(CE_NOTE, "\toemname: (%s)",
 950 1129              (shr->shr_oemname) ? shr->shr_oemname : "NULL");
 951 1130          cmn_err(CE_NOTE, "\tflags: %X", shr->shr_flags);
 952 1131          cmn_err(CE_NOTE, "\ttype: %d", shr->shr_type);
 953 1132  }
 954 1133  #endif
 955 1134  
 956 1135  /*
 957 1136   * Compare function used by shares AVL
 958 1137   */
 959 1138  static int
 960 1139  smb_kshare_cmp(const void *p1, const void *p2)
 961 1140  {
 962 1141          smb_kshare_t *shr1 = (smb_kshare_t *)p1;
 963 1142          smb_kshare_t *shr2 = (smb_kshare_t *)p2;
 964 1143          int rc;
 965 1144  
 966 1145          ASSERT(shr1);
 967 1146          ASSERT(shr1->shr_name);
 968 1147  
 969 1148          ASSERT(shr2);
 970 1149          ASSERT(shr2->shr_name);
 971 1150  
 972 1151          rc = smb_strcasecmp(shr1->shr_name, shr2->shr_name, 0);
 973 1152  
 974 1153          if (rc < 0)
 975 1154                  return (-1);
 976 1155  
 977 1156          if (rc > 0)
 978 1157                  return (1);
 979 1158  
 980 1159          return (0);
 981 1160  }
 982 1161  
 983 1162  /*
 984 1163   * This function is called by smb_avl routines whenever
 985 1164   * there is a need to take a hold on a share structure
 986 1165   * inside AVL
 987 1166   */
 988 1167  static void
 989 1168  smb_kshare_hold(const void *p)
 990 1169  {
 991 1170          smb_kshare_t *shr = (smb_kshare_t *)p;
 992 1171  
 993 1172          ASSERT(shr);
 994 1173          ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
 995 1174  
 996 1175          mutex_enter(&shr->shr_mutex);
 997 1176          shr->shr_refcnt++;
 998 1177          mutex_exit(&shr->shr_mutex);
 999 1178  }
1000 1179  
1001 1180  /*
1002 1181   * This function must be called by smb_avl routines whenever
1003 1182   * smb_kshare_hold is called and the hold needs to be released.
1004 1183   */
1005 1184  static boolean_t
1006 1185  smb_kshare_rele(const void *p)
1007 1186  {
1008 1187          smb_kshare_t *shr = (smb_kshare_t *)p;
1009 1188          boolean_t destroy;
1010 1189  
1011 1190          ASSERT(shr);
1012 1191          ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1013 1192  
1014 1193          mutex_enter(&shr->shr_mutex);
1015 1194          ASSERT(shr->shr_refcnt > 0);
1016 1195          shr->shr_refcnt--;
1017 1196          destroy = (shr->shr_refcnt == 0);
1018 1197          mutex_exit(&shr->shr_mutex);
1019 1198  
1020 1199          return (destroy);
1021 1200  }
1022 1201  
1023 1202  /*
1024 1203   * Frees all the memory allocated for the given
1025 1204   * share structure. It also removes the structure
  
    | 
      ↓ open down ↓ | 
    79 lines elided | 
    
      ↑ open up ↑ | 
  
1026 1205   * from the share cache.
1027 1206   */
1028 1207  static void
1029 1208  smb_kshare_destroy(void *p)
1030 1209  {
1031 1210          smb_kshare_t *shr = (smb_kshare_t *)p;
1032 1211  
1033 1212          ASSERT(shr);
1034 1213          ASSERT(shr->shr_magic == SMB_SHARE_MAGIC);
1035 1214  
     1215 +        if (shr->shr_ksp != NULL) {
     1216 +                kstat_delete(shr->shr_ksp);
     1217 +                shr->shr_ksp = NULL;
     1218 +                kshare_stats_fini(shr);
     1219 +        }
     1220 +
     1221 +        if (shr->stats.ksns != NULL) {
     1222 +                kstat_delete(shr->stats.ksns);
     1223 +        }
     1224 +
     1225 +        if (shr->shr_ca_dir != NULL)
     1226 +                smb_node_release(shr->shr_ca_dir);
     1227 +        if (shr->shr_root_node)
     1228 +                smb_node_release(shr->shr_root_node);
     1229 +
1036 1230          smb_mem_free(shr->shr_name);
1037 1231          smb_mem_free(shr->shr_path);
1038 1232          smb_mem_free(shr->shr_cmnt);
1039 1233          smb_mem_free(shr->shr_container);
1040 1234          smb_mem_free(shr->shr_oemname);
1041 1235          smb_mem_free(shr->shr_access_none);
1042 1236          smb_mem_free(shr->shr_access_ro);
1043 1237          smb_mem_free(shr->shr_access_rw);
1044 1238  
1045 1239          kmem_cache_free(smb_kshare_cache_share, shr);
1046 1240  }
1047 1241  
1048 1242  
1049 1243  /*
1050 1244   * Generate an OEM name for the given share name.  If the name is
1051 1245   * shorter than 13 bytes the oemname will be returned; otherwise NULL
1052 1246   * is returned.
1053 1247   */
1054 1248  static char *
1055 1249  smb_kshare_oemname(const char *shrname)
1056 1250  {
1057 1251          smb_wchar_t *unibuf;
1058 1252          char *oem_name;
1059 1253          int length;
1060 1254  
1061 1255          length = strlen(shrname) + 1;
1062 1256  
1063 1257          oem_name = smb_mem_alloc(length);
1064 1258          unibuf = smb_mem_alloc(length * sizeof (smb_wchar_t));
1065 1259  
1066 1260          (void) smb_mbstowcs(unibuf, shrname, length);
1067 1261  
1068 1262          if (ucstooem(oem_name, unibuf, length, OEM_CPG_850) == 0)
1069 1263                  (void) strcpy(oem_name, shrname);
1070 1264  
1071 1265          smb_mem_free(unibuf);
1072 1266  
1073 1267          if (strlen(oem_name) + 1 > SMB_SHARE_OEMNAME_MAX) {
1074 1268                  smb_mem_free(oem_name);
1075 1269                  return (NULL);
1076 1270          }
1077 1271  
1078 1272          return (oem_name);
1079 1273  }
1080 1274  
1081 1275  /*
1082 1276   * Special share reserved for interprocess communication (IPC$) or
1083 1277   * remote administration of the server (ADMIN$). Can also refer to
1084 1278   * administrative shares such as C$, D$, E$, and so forth.
1085 1279   */
1086 1280  static int
1087 1281  smb_kshare_is_special(const char *sharename)
1088 1282  {
1089 1283          int len;
1090 1284  
1091 1285          if (sharename == NULL)
1092 1286                  return (0);
1093 1287  
1094 1288          if ((len = strlen(sharename)) == 0)
1095 1289                  return (0);
1096 1290  
1097 1291          if (sharename[len - 1] == '$')
1098 1292                  return (STYPE_SPECIAL);
1099 1293  
1100 1294          return (0);
1101 1295  }
1102 1296  
1103 1297  /*
1104 1298   * Check whether or not this is a default admin share: C$, D$ etc.
1105 1299   */
1106 1300  static boolean_t
1107 1301  smb_kshare_is_admin(const char *sharename)
1108 1302  {
1109 1303          if (sharename == NULL)
1110 1304                  return (B_FALSE);
1111 1305  
1112 1306          if (strlen(sharename) == 2 &&
1113 1307              smb_isalpha(sharename[0]) && sharename[1] == '$') {
1114 1308                  return (B_TRUE);
1115 1309          }
1116 1310  
1117 1311          return (B_FALSE);
1118 1312  }
1119 1313  
1120 1314  /*
1121 1315   * Decodes the given boolean share option.
1122 1316   * If the option is present in the nvlist and it's value is true
1123 1317   * returns the corresponding flag value, otherwise returns 0.
1124 1318   */
1125 1319  static uint32_t
1126 1320  smb_kshare_decode_bool(nvlist_t *nvl, const char *propname, uint32_t flag)
1127 1321  {
1128 1322          char *boolp;
1129 1323  
1130 1324          if (nvlist_lookup_string(nvl, propname, &boolp) == 0)
1131 1325                  if (strcasecmp(boolp, "true") == 0)
1132 1326                          return (flag);
1133 1327  
1134 1328          return (0);
1135 1329  }
1136 1330  
1137 1331  /*
1138 1332   * Map a client-side caching (CSC) option to the appropriate share
1139 1333   * flag.  Only one option is allowed; an error will be logged if
1140 1334   * multiple options have been specified.  We don't need to do anything
1141 1335   * about multiple values here because the SRVSVC will not recognize
1142 1336   * a value containing multiple flags and will return the default value.
1143 1337   *
1144 1338   * If the option value is not recognized, it will be ignored: invalid
1145 1339   * values will typically be caught and rejected by sharemgr.
1146 1340   */
1147 1341  static void
1148 1342  smb_kshare_csc_flags(smb_kshare_t *shr, const char *value)
1149 1343  {
1150 1344          int i;
1151 1345          static struct {
1152 1346                  char *value;
1153 1347                  uint32_t flag;
1154 1348          } cscopt[] = {
1155 1349                  { "disabled",   SMB_SHRF_CSC_DISABLED },
1156 1350                  { "manual",     SMB_SHRF_CSC_MANUAL },
1157 1351                  { "auto",       SMB_SHRF_CSC_AUTO },
1158 1352                  { "vdo",        SMB_SHRF_CSC_VDO }
1159 1353          };
1160 1354  
1161 1355          if (value == NULL)
1162 1356                  return;
1163 1357  
1164 1358          for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1165 1359                  if (strcasecmp(value, cscopt[i].value) == 0) {
1166 1360                          shr->shr_flags |= cscopt[i].flag;
1167 1361                          break;
1168 1362                  }
1169 1363          }
1170 1364  
1171 1365          switch (shr->shr_flags & SMB_SHRF_CSC_MASK) {
1172 1366          case 0:
1173 1367          case SMB_SHRF_CSC_DISABLED:
1174 1368          case SMB_SHRF_CSC_MANUAL:
1175 1369          case SMB_SHRF_CSC_AUTO:
1176 1370          case SMB_SHRF_CSC_VDO:
1177 1371                  break;
1178 1372  
1179 1373          default:
1180 1374                  cmn_err(CE_NOTE, "csc option conflict: 0x%08x",
1181 1375                      shr->shr_flags & SMB_SHRF_CSC_MASK);
1182 1376                  break;
1183 1377          }
1184 1378  }
1185 1379  
1186 1380  /*
1187 1381   * This function processes the unexport event list and disconnects shares
1188 1382   * asynchronously.  The function executes as a zone-specific thread.
1189 1383   *
1190 1384   * The server arg passed in is safe to use without a reference count, because
1191 1385   * the server cannot be deleted until smb_thread_stop()/destroy() return,
1192 1386   * which is also when the thread exits.
1193 1387   */
1194 1388  /*ARGSUSED*/
1195 1389  static void
1196 1390  smb_kshare_unexport_thread(smb_thread_t *thread, void *arg)
1197 1391  {
1198 1392          smb_server_t    *sv = arg;
1199 1393          smb_unshare_t   *ux;
1200 1394  
1201 1395          while (smb_thread_continue(thread)) {
1202 1396                  while ((ux = list_head(&sv->sv_export.e_unexport_list.sl_list))
1203 1397                      != NULL) {
1204 1398                          smb_slist_remove(&sv->sv_export.e_unexport_list, ux);
1205 1399                          (void) smb_server_unshare(ux->us_sharename);
1206 1400                          kmem_cache_free(smb_kshare_cache_unexport, ux);
1207 1401                  }
1208 1402          }
1209 1403  }
1210 1404  
1211 1405  static boolean_t
1212 1406  smb_export_isready(smb_server_t *sv)
1213 1407  {
1214 1408          boolean_t ready;
1215 1409  
1216 1410          mutex_enter(&sv->sv_export.e_mutex);
1217 1411          ready = sv->sv_export.e_ready;
1218 1412          mutex_exit(&sv->sv_export.e_mutex);
1219 1413  
1220 1414          return (ready);
1221 1415  }
1222 1416  
1223 1417  #ifdef  _KERNEL
1224 1418  /*
1225 1419   * Return 0 upon success. Otherwise > 0
1226 1420   */
1227 1421  static int
1228 1422  smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx)
1229 1423  {
1230 1424          int status = smb_dr_get_int32(dec_ctx);
1231 1425          int err;
1232 1426  
1233 1427          switch (status) {
1234 1428          case SMB_SHARE_DSUCCESS:
1235 1429                  return (0);
1236 1430  
1237 1431          case SMB_SHARE_DERROR:
1238 1432                  err = smb_dr_get_uint32(dec_ctx);
1239 1433                  cmn_err(CE_WARN, "%d: Encountered door server error %d",
1240 1434                      opcode, err);
1241 1435                  (void) smb_dr_decode_finish(dec_ctx);
1242 1436                  return (err);
1243 1437          }
1244 1438  
1245 1439          ASSERT(0);
1246 1440          return (EINVAL);
1247 1441  }
1248 1442  #endif  /* _KERNEL */
  
    | 
      ↓ open down ↓ | 
    203 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX