1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 /*
  26  * SMB Node State Machine
  27  * ----------------------
  28  *
  29  *
  30  *                  +----------- Creation/Allocation
  31  *                  |
  32  *                  | T0
  33  *                  |
  34  *                  v
  35  *    +----------------------------+
  36  *    |  SMB_NODE_STATE_AVAILABLE  |
  37  *    +----------------------------+
  38  *                  |
  39  *                  | T1
  40  *                  |
  41  *                  v
  42  *    +-----------------------------+
  43  *    |  SMB_NODE_STATE_DESTROYING  |
  44  *    +-----------------------------+
  45  *                  |
  46  *                  |
  47  *                  | T2
  48  *                  |
  49  *                  +----------> Deletion/Free
  50  *
  51  * Transition T0
  52  *
  53  *    This transition occurs in smb_node_lookup(). If the node looked for is
  54  *    not found in the has table a new node is created. The reference count is
  55  *    initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE.
  56  *
  57  * Transition T1
  58  *
  59  *    This transition occurs in smb_node_release(). If the reference count
  60  *    drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more
  61  *    reference count will be given out for that node.
  62  *
  63  * Transition T2
  64  *
  65  *    This transition occurs in smb_node_release(). The structure is deleted.
  66  *
  67  * Comments
  68  * --------
  69  *
  70  *    The reason the smb node has 2 states is the following synchronization
  71  *    rule:
  72  *
  73  *    There's a mutex embedded in the node used to protect its fields and
  74  *    there's a lock embedded in the bucket of the hash table the node belongs
  75  *    to. To increment or to decrement the reference count the mutex must be
  76  *    entered. To insert the node into the bucket and to remove it from the
  77  *    bucket the lock must be entered in RW_WRITER mode. When both (mutex and
  78  *    lock) have to be entered, the lock has always to be entered first then
  79  *    the mutex. This prevents a deadlock between smb_node_lookup() and
  80  *    smb_node_release() from occurring. However, in smb_node_release() when the
  81  *    reference count drops to zero and triggers the deletion of the node, the
  82  *    mutex has to be released before entering the lock of the bucket (to
  83  *    remove the node). This creates a window during which the node that is
  84  *    about to be freed could be given out by smb_node_lookup(). To close that
  85  *    window the node is moved to the state SMB_NODE_STATE_DESTROYING before
  86  *    releasing the mutex. That way, even if smb_node_lookup() finds it, the
  87  *    state will indicate that the node should be treated as non existent (of
  88  *    course the state of the node should be tested/updated under the
  89  *    protection of the mutex).
  90  */
  91 #include <smbsrv/smb_kproto.h>
  92 #include <smbsrv/smb_fsops.h>
  93 #include <smbsrv/smb_kstat.h>
  94 #include <sys/ddi.h>
  95 #include <sys/extdirent.h>
  96 #include <sys/pathname.h>
  97 #include <sys/sdt.h>
  98 #include <sys/nbmlock.h>
  99 #include <fs/fs_reparse.h>
 100 
 101 uint32_t smb_is_executable(char *);
 102 static void smb_node_delete_on_close(smb_node_t *);
 103 static void smb_node_create_audit_buf(smb_node_t *, int);
 104 static void smb_node_destroy_audit_buf(smb_node_t *);
 105 static void smb_node_audit(smb_node_t *);
 106 static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t);
 107 static void smb_node_free(smb_node_t *);
 108 static int smb_node_constructor(void *, void *, int);
 109 static void smb_node_destructor(void *, void *);
 110 static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
 111 
 112 static void smb_node_init_reparse(smb_node_t *, smb_attr_t *);
 113 static void smb_node_init_system(smb_node_t *);
 114 
 115 #define VALIDATE_DIR_NODE(_dir_, _node_) \
 116     ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \
 117     ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \
 118     ASSERT((_dir_)->n_dnode != (_node_));
 119 
 120 /* round sz to DEV_BSIZE block */
 121 #define SMB_ALLOCSZ(sz) (((sz) + DEV_BSIZE-1) & ~(DEV_BSIZE-1))
 122 
 123 static kmem_cache_t     *smb_node_cache = NULL;
 124 static smb_llist_t      smb_node_hash_table[SMBND_HASH_MASK+1];
 125 static smb_node_t       *smb_root_node;
 126 
 127 /*
 128  * smb_node_init
 129  *
 130  * Initialization of the SMB node layer.
 131  *
 132  * This function is not multi-thread safe. The caller must make sure only one
 133  * thread makes the call.
 134  */
 135 void
 136 smb_node_init(void)
 137 {
 138         smb_attr_t      attr;
 139         smb_llist_t     *node_hdr;
 140         smb_node_t      *node;
 141         uint32_t        hashkey;
 142         int             i;
 143 
 144         if (smb_node_cache != NULL)
 145                 return;
 146 
 147         smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE,
 148             sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor,
 149             NULL, NULL, NULL, 0);
 150 
 151         for (i = 0; i <= SMBND_HASH_MASK; i++) {
 152                 smb_llist_constructor(&smb_node_hash_table[i],
 153                     sizeof (smb_node_t), offsetof(smb_node_t, n_lnd));
 154         }
 155 
 156         /*
 157          * The node cache is shared by all zones, so the smb_root_node
 158          * must represent the real (global zone) rootdir.
 159          * Note intentional use of kcred here.
 160          */
 161         attr.sa_mask = SMB_AT_ALL;
 162         VERIFY0(smb_vop_getattr(rootdir, NULL, &attr, 0, kcred));
 163         node_hdr = smb_node_get_hash(&rootdir->v_vfsp->vfs_fsid, &attr,
 164             &hashkey);
 165         node = smb_node_alloc("/", rootdir, node_hdr, hashkey);
 166         smb_llist_enter(node_hdr, RW_WRITER);
 167         smb_llist_insert_head(node_hdr, node);
 168         smb_llist_exit(node_hdr);
 169         smb_root_node = node;   /* smb_node_release in smb_node_fini */
 170 }
 171 
 172 /*
 173  * smb_node_fini
 174  *
 175  * This function is not multi-thread safe. The caller must make sure only one
 176  * thread makes the call.
 177  */
 178 void
 179 smb_node_fini(void)
 180 {
 181         int     i;
 182 
 183         if (smb_root_node != NULL) {
 184                 smb_node_release(smb_root_node);
 185                 smb_root_node = NULL;
 186         }
 187 
 188         if (smb_node_cache == NULL)
 189                 return;
 190 
 191 #ifdef DEBUG
 192         for (i = 0; i <= SMBND_HASH_MASK; i++) {
 193                 smb_node_t      *node;
 194 
 195                 /*
 196                  * The following sequence is just intended for sanity check.
 197                  * This will have to be modified when the code goes into
 198                  * production.
 199                  *
 200                  * The SMB node hash table should be emtpy at this point. If the
 201                  * hash table is not empty a panic will be triggered.
 202                  *
 203                  * The reason why SMB nodes are still remaining in the hash
 204                  * table is problably due to a mismatch between calls to
 205                  * smb_node_lookup() and smb_node_release(). You must track that
 206                  * down.
 207                  */
 208                 node = smb_llist_head(&smb_node_hash_table[i]);
 209                 ASSERT(node == NULL);
 210         }
 211 #endif
 212 
 213         for (i = 0; i <= SMBND_HASH_MASK; i++) {
 214                 smb_llist_destructor(&smb_node_hash_table[i]);
 215         }
 216         kmem_cache_destroy(smb_node_cache);
 217         smb_node_cache = NULL;
 218 }
 219 
 220 /*
 221  * smb_node_lookup()
 222  *
 223  * NOTE: This routine should only be called by the file system interface layer,
 224  * and not by SMB.
 225  *
 226  * smb_node_lookup() is called upon successful lookup, mkdir, and create
 227  * (for both non-streams and streams).  In each of these cases, a held vnode is
 228  * passed into this routine.  If a new smb_node is created it will take its
 229  * own hold on the vnode.  The caller's hold therefore still belongs to, and
 230  * should be released by, the caller.
 231  *
 232  * A reference is taken on the smb_node whether found in the hash table
 233  * or newly created.
 234  *
 235  * If an smb_node needs to be created, a reference is also taken on the
 236  * dnode (if passed in).
 237  *
 238  * See smb_node_release() for details on the release of these references.
 239  */
 240 
 241 /*ARGSUSED*/
 242 smb_node_t *
 243 smb_node_lookup(
 244     struct smb_request  *sr,
 245     struct open_param   *op,
 246     cred_t              *cred,
 247     vnode_t             *vp,
 248     char                *od_name,
 249     smb_node_t          *dnode,
 250     smb_node_t          *unode)
 251 {
 252         smb_llist_t             *node_hdr;
 253         smb_node_t              *node;
 254         smb_attr_t              attr;
 255         uint32_t                hashkey = 0;
 256         fsid_t                  fsid;
 257         int                     error;
 258         krw_t                   lock_mode;
 259         vnode_t                 *unnamed_vp = NULL;
 260 
 261         /*
 262          * smb_vop_getattr() is called here instead of smb_fsop_getattr(),
 263          * because the node may not yet exist.  We also do not want to call
 264          * it with the list lock held.
 265          */
 266 
 267         if (unode)
 268                 unnamed_vp = unode->vp;
 269 
 270         /*
 271          * This getattr is performed on behalf of the server
 272          * that's why kcred is used not the user's cred
 273          */
 274         attr.sa_mask = SMB_AT_ALL;
 275         error = smb_vop_getattr(vp, unnamed_vp, &attr, 0, zone_kcred());
 276         if (error)
 277                 return (NULL);
 278 
 279         if (sr && sr->tid_tree) {
 280                 /*
 281                  * The fsid for a file is that of the tree, even
 282                  * if the file resides in a different mountpoint
 283                  * under the share.
 284                  */
 285                 fsid = SMB_TREE_FSID(sr->tid_tree);
 286         } else {
 287                 /*
 288                  * This should be getting executed only for the
 289                  * tree root smb_node.
 290                  */
 291                 fsid = vp->v_vfsp->vfs_fsid;
 292         }
 293 
 294         node_hdr = smb_node_get_hash(&fsid, &attr, &hashkey);
 295         lock_mode = RW_READER;
 296 
 297         smb_llist_enter(node_hdr, lock_mode);
 298         for (;;) {
 299                 node = list_head(&node_hdr->ll_list);
 300                 while (node) {
 301                         ASSERT(node->n_magic == SMB_NODE_MAGIC);
 302                         ASSERT(node->n_hash_bucket == node_hdr);
 303                         if ((node->n_hashkey == hashkey) && (node->vp == vp)) {
 304                                 mutex_enter(&node->n_mutex);
 305                                 DTRACE_PROBE1(smb_node_lookup_hit,
 306                                     smb_node_t *, node);
 307                                 switch (node->n_state) {
 308                                 case SMB_NODE_STATE_AVAILABLE:
 309                                         /* The node was found. */
 310                                         node->n_refcnt++;
 311                                         if ((node->n_dnode == NULL) &&
 312                                             (dnode != NULL) &&
 313                                             (node != dnode) &&
 314                                             (strcmp(od_name, "..") != 0) &&
 315                                             (strcmp(od_name, ".") != 0)) {
 316                                                 VALIDATE_DIR_NODE(dnode, node);
 317                                                 node->n_dnode = dnode;
 318                                                 smb_node_ref(dnode);
 319                                         }
 320 
 321                                         smb_node_audit(node);
 322                                         mutex_exit(&node->n_mutex);
 323                                         smb_llist_exit(node_hdr);
 324                                         return (node);
 325 
 326                                 case SMB_NODE_STATE_DESTROYING:
 327                                         /*
 328                                          * Although the node exists it is about
 329                                          * to be destroyed. We act as it hasn't
 330                                          * been found.
 331                                          */
 332                                         mutex_exit(&node->n_mutex);
 333                                         break;
 334                                 default:
 335                                         /*
 336                                          * Although the node exists it is in an
 337                                          * unknown state. We act as it hasn't
 338                                          * been found.
 339                                          */
 340                                         ASSERT(0);
 341                                         mutex_exit(&node->n_mutex);
 342                                         break;
 343                                 }
 344                         }
 345                         node = smb_llist_next(node_hdr, node);
 346                 }
 347                 if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) {
 348                         lock_mode = RW_WRITER;
 349                         continue;
 350                 }
 351                 break;
 352         }
 353         node = smb_node_alloc(od_name, vp, node_hdr, hashkey);
 354         smb_node_init_reparse(node, &attr);
 355 
 356         if (op)
 357                 node->flags |= smb_is_executable(op->fqi.fq_last_comp);
 358 
 359         if (dnode) {
 360                 smb_node_ref(dnode);
 361                 node->n_dnode = dnode;
 362                 ASSERT(dnode->n_dnode != node);
 363                 ASSERT((dnode->vp->v_xattrdir) ||
 364                     (dnode->vp->v_type == VDIR));
 365         }
 366 
 367         if (unode) {
 368                 smb_node_ref(unode);
 369                 node->n_unode = unode;
 370         }
 371 
 372         smb_node_init_system(node);
 373 
 374         DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node);
 375         smb_node_audit(node);
 376         smb_llist_insert_head(node_hdr, node);
 377         smb_llist_exit(node_hdr);
 378         return (node);
 379 }
 380 
 381 /*
 382  * smb_stream_node_lookup()
 383  *
 384  * Note: stream_name (the name that will be stored in the "od_name" field
 385  * of a stream's smb_node) is the same as the on-disk name for the stream
 386  * except that it does not have SMB_STREAM_PREFIX prepended.
 387  */
 388 
 389 smb_node_t *
 390 smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode,
 391     vnode_t *xattrdirvp, vnode_t *vp, char *stream_name)
 392 {
 393         smb_node_t      *xattrdir_node;
 394         smb_node_t      *snode;
 395 
 396         xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR,
 397             fnode, NULL);
 398 
 399         if (xattrdir_node == NULL)
 400                 return (NULL);
 401 
 402         snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node,
 403             fnode);
 404 
 405         (void) smb_node_release(xattrdir_node);
 406         return (snode);
 407 }
 408 
 409 
 410 /*
 411  * This function should be called whenever a reference is needed on an
 412  * smb_node pointer.  The copy of an smb_node pointer from one non-local
 413  * data structure to another requires a reference to be taken on the smb_node
 414  * (unless the usage is localized).  Each data structure deallocation routine
 415  * will call smb_node_release() on its smb_node pointers.
 416  *
 417  * In general, an smb_node pointer residing in a structure should never be
 418  * stale.  A node pointer may be NULL, however, and care should be taken
 419  * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid.
 420  * Care also needs to be taken with respect to racing deallocations of a
 421  * structure.
 422  */
 423 void
 424 smb_node_ref(smb_node_t *node)
 425 {
 426         SMB_NODE_VALID(node);
 427 
 428         mutex_enter(&node->n_mutex);
 429         switch (node->n_state) {
 430         case SMB_NODE_STATE_AVAILABLE:
 431                 node->n_refcnt++;
 432                 ASSERT(node->n_refcnt);
 433                 DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node);
 434                 smb_node_audit(node);
 435                 break;
 436         default:
 437                 SMB_PANIC();
 438         }
 439         mutex_exit(&node->n_mutex);
 440 }
 441 
 442 /*
 443  * smb_node_lookup() takes a hold on an smb_node, whether found in the
 444  * hash table or newly created.  This hold is expected to be released
 445  * in the following manner.
 446  *
 447  * smb_node_lookup() takes an address of an smb_node pointer.  This should
 448  * be getting passed down via a lookup (whether path name or component), mkdir,
 449  * create.  If the original smb_node pointer resides in a data structure, then
 450  * the deallocation routine for the data structure is responsible for calling
 451  * smb_node_release() on the smb_node pointer.  Alternatively,
 452  * smb_node_release() can be called as soon as the smb_node pointer is no longer
 453  * needed.  In this case, callers are responsible for setting an embedded
 454  * pointer to NULL if it is known that the last reference is being released.
 455  *
 456  * If the passed-in address of the smb_node pointer belongs to a local variable,
 457  * then the caller with the local variable should call smb_node_release()
 458  * directly.
 459  *
 460  * smb_node_release() itself will call smb_node_release() on a node's n_dnode,
 461  * as smb_node_lookup() takes a hold on dnode.
 462  */
 463 void
 464 smb_node_release(smb_node_t *node)
 465 {
 466         SMB_NODE_VALID(node);
 467 
 468         mutex_enter(&node->n_mutex);
 469         ASSERT(node->n_refcnt);
 470         DTRACE_PROBE1(smb_node_release, smb_node_t *, node);
 471         if (--node->n_refcnt == 0) {
 472                 switch (node->n_state) {
 473 
 474                 case SMB_NODE_STATE_AVAILABLE:
 475                         node->n_state = SMB_NODE_STATE_DESTROYING;
 476                         mutex_exit(&node->n_mutex);
 477 
 478                         smb_llist_enter(node->n_hash_bucket, RW_WRITER);
 479                         smb_llist_remove(node->n_hash_bucket, node);
 480                         smb_llist_exit(node->n_hash_bucket);
 481 
 482                         /*
 483                          * Check if the file was deleted
 484                          */
 485                         smb_node_delete_on_close(node);
 486 
 487                         if (node->n_dnode) {
 488                                 ASSERT(node->n_dnode->n_magic ==
 489                                     SMB_NODE_MAGIC);
 490                                 smb_node_release(node->n_dnode);
 491                         }
 492 
 493                         if (node->n_unode) {
 494                                 ASSERT(node->n_unode->n_magic ==
 495                                     SMB_NODE_MAGIC);
 496                                 smb_node_release(node->n_unode);
 497                         }
 498 
 499                         smb_node_free(node);
 500                         return;
 501 
 502                 default:
 503                         SMB_PANIC();
 504                 }
 505         }
 506         smb_node_audit(node);
 507         mutex_exit(&node->n_mutex);
 508 }
 509 
 510 static void
 511 smb_node_delete_on_close(smb_node_t *node)
 512 {
 513         smb_node_t      *d_snode;
 514         int             rc = 0;
 515         uint32_t        flags = 0;
 516 
 517         d_snode = node->n_dnode;
 518         if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
 519                 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
 520                 flags = node->n_delete_on_close_flags;
 521                 ASSERT(node->od_name != NULL);
 522 
 523                 if (smb_node_is_dir(node))
 524                         rc = smb_fsop_rmdir(0, node->delete_on_close_cred,
 525                             d_snode, node->od_name, flags);
 526                 else
 527                         rc = smb_fsop_remove(0, node->delete_on_close_cred,
 528                             d_snode, node->od_name, flags);
 529                 crfree(node->delete_on_close_cred);
 530         }
 531         if (rc != 0)
 532                 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n",
 533                     node->od_name, rc);
 534         DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node);
 535 }
 536 
 537 /*
 538  * smb_node_rename()
 539  *
 540  */
 541 void
 542 smb_node_rename(
 543     smb_node_t  *from_dnode,
 544     smb_node_t  *ret_node,
 545     smb_node_t  *to_dnode,
 546     char        *to_name)
 547 {
 548         SMB_NODE_VALID(from_dnode);
 549         SMB_NODE_VALID(to_dnode);
 550         SMB_NODE_VALID(ret_node);
 551 
 552         smb_node_ref(to_dnode);
 553         mutex_enter(&ret_node->n_mutex);
 554         switch (ret_node->n_state) {
 555         case SMB_NODE_STATE_AVAILABLE:
 556                 ret_node->n_dnode = to_dnode;
 557                 mutex_exit(&ret_node->n_mutex);
 558                 ASSERT(to_dnode->n_dnode != ret_node);
 559                 ASSERT((to_dnode->vp->v_xattrdir) ||
 560                     (to_dnode->vp->v_type == VDIR));
 561                 smb_node_release(from_dnode);
 562                 (void) strcpy(ret_node->od_name, to_name);
 563                 /*
 564                  * XXX Need to update attributes?
 565                  */
 566                 break;
 567         default:
 568                 SMB_PANIC();
 569         }
 570 }
 571 
 572 /*
 573  * Find/create an SMB node for the root of this zone and store it
 574  * in *svrootp.  Also create nodes leading to this directory.
 575  */
 576 int
 577 smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp)
 578 {
 579         zone_t          *zone = curzone;
 580         int             error;
 581 
 582         ASSERT(zone->zone_id == sv->sv_zid);
 583         if (smb_root_node == NULL)
 584                 return (ENOENT);
 585 
 586         /*
 587          * We're getting smb nodes below the zone root here,
 588          * so need to use kcred, not zone_kcred().
 589          */
 590         error = smb_pathname(NULL, zone->zone_rootpath, 0,
 591             smb_root_node, smb_root_node, NULL, svrootp, kcred);
 592 
 593         return (error);
 594 }
 595 
 596 /*
 597  * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir.
 598  * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code.
 599  * We distinguish between readdir failure and non-empty dir by returning
 600  * different values.
 601  */
 602 static uint32_t
 603 smb_rmdir_possible(smb_node_t *n, uint32_t flags)
 604 {
 605         ASSERT(n->vp->v_type == VDIR);
 606         char buf[512]; /* Only large enough to see if the dir is empty. */
 607         int eof, bsize = sizeof (buf), reclen = 0;
 608         char *name;
 609         boolean_t edp = vfs_has_feature(n->vp->v_vfsp, VFSFT_DIRENTFLAGS);
 610 
 611         union {
 612                 char            *u_bufptr;
 613                 struct edirent  *u_edp;
 614                 struct dirent64 *u_dp;
 615         } u;
 616 #define bufptr  u.u_bufptr
 617 #define extdp   u.u_edp
 618 #define dp      u.u_dp
 619 
 620         if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, flags, zone_kcred()))
 621                 return (NT_STATUS_CANNOT_DELETE);
 622         if (bsize == 0)
 623                 return (NT_STATUS_CANNOT_DELETE);
 624         bufptr = buf;
 625         while ((bufptr += reclen) < buf + bsize) {
 626                 if (edp) {
 627                         reclen = extdp->ed_reclen;
 628                         name = extdp->ed_name;
 629                 } else {
 630                         reclen = dp->d_reclen;
 631                         name = dp->d_name;
 632                 }
 633                 if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
 634                         return (NT_STATUS_DIRECTORY_NOT_EMPTY);
 635         }
 636         return (0);
 637 }
 638 
 639 /*
 640  * When DeleteOnClose is set on an smb_node, the common open code will
 641  * reject subsequent open requests for the file. Observation of Windows
 642  * 2000 indicates that subsequent opens should be allowed (assuming
 643  * there would be no sharing violation) until the file is closed using
 644  * the fid on which the DeleteOnClose was requested.
 645  *
 646  * If there are multiple opens with delete-on-close create options,
 647  * whichever the first file handle is closed will trigger the node to be
 648  * marked as delete-on-close. The credentials of that ofile will be used
 649  * as the delete-on-close credentials of the node.
 650  */
 651 uint32_t
 652 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
 653 {
 654         int rc = 0;
 655         uint32_t status;
 656         smb_attr_t attr;
 657 
 658         if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY)
 659                 return (NT_STATUS_CANNOT_DELETE);
 660 
 661         bzero(&attr, sizeof (smb_attr_t));
 662         attr.sa_mask = SMB_AT_DOSATTR;
 663         rc = smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
 664         if ((rc != 0) || (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) {
 665                 return (NT_STATUS_CANNOT_DELETE);
 666         }
 667 
 668         /*
 669          * If the directory is not empty we should fail setting del-on-close
 670          * with STATUS_DIRECTORY_NOT_EMPTY. see MS's
 671          * "File System Behavior Overview" doc section 4.3.2
 672          */
 673         if (smb_node_is_dir(node)) {
 674                 status = smb_rmdir_possible(node, flags);
 675                 if (status != 0) {
 676                         return (status);
 677                 }
 678         }
 679 
 680         mutex_enter(&node->n_mutex);
 681         if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
 682                 mutex_exit(&node->n_mutex);
 683                 return (NT_STATUS_CANNOT_DELETE);
 684         }
 685 
 686         crhold(cr);
 687         node->delete_on_close_cred = cr;
 688         node->n_delete_on_close_flags = flags;
 689         node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
 690         mutex_exit(&node->n_mutex);
 691 
 692         /*
 693          * Tell any change notify calls to close their handles
 694          * and get out of the way.  FILE_ACTION_DELETE_PENDING
 695          * is a special, internal-only action for this purpose.
 696          */
 697         smb_notify_event(node, FILE_ACTION_DELETE_PENDING, NULL);
 698 
 699         return (NT_STATUS_SUCCESS);
 700 }
 701 
 702 void
 703 smb_node_reset_delete_on_close(smb_node_t *node)
 704 {
 705         mutex_enter(&node->n_mutex);
 706         if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
 707                 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
 708                 crfree(node->delete_on_close_cred);
 709                 node->delete_on_close_cred = NULL;
 710                 node->n_delete_on_close_flags = 0;
 711         }
 712         mutex_exit(&node->n_mutex);
 713 }
 714 
 715 /*
 716  * smb_node_open_check
 717  *
 718  * check file sharing rules for current open request
 719  * against all existing opens for a file.
 720  *
 721  * Returns NT_STATUS_SHARING_VIOLATION if there is any
 722  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
 723  */
 724 uint32_t
 725 smb_node_open_check(smb_node_t *node, uint32_t desired_access,
 726     uint32_t share_access)
 727 {
 728         smb_ofile_t *of;
 729         uint32_t status;
 730 
 731         SMB_NODE_VALID(node);
 732 
 733         smb_llist_enter(&node->n_ofile_list, RW_READER);
 734         of = smb_llist_head(&node->n_ofile_list);
 735         while (of) {
 736                 status = smb_ofile_open_check(of, desired_access, share_access);
 737 
 738                 switch (status) {
 739                 case NT_STATUS_INVALID_HANDLE:
 740                 case NT_STATUS_SUCCESS:
 741                         of = smb_llist_next(&node->n_ofile_list, of);
 742                         break;
 743                 default:
 744                         ASSERT(status == NT_STATUS_SHARING_VIOLATION);
 745                         smb_llist_exit(&node->n_ofile_list);
 746                         return (status);
 747                 }
 748         }
 749 
 750         smb_llist_exit(&node->n_ofile_list);
 751         return (NT_STATUS_SUCCESS);
 752 }
 753 
 754 uint32_t
 755 smb_node_rename_check(smb_node_t *node)
 756 {
 757         smb_ofile_t     *of;
 758         uint32_t        status;
 759 
 760         SMB_NODE_VALID(node);
 761 
 762         /*
 763          * Intra-CIFS check
 764          */
 765         smb_llist_enter(&node->n_ofile_list, RW_READER);
 766         of = smb_llist_head(&node->n_ofile_list);
 767         while (of) {
 768                 status = smb_ofile_rename_check(of);
 769 
 770                 switch (status) {
 771                 case NT_STATUS_INVALID_HANDLE:
 772                 case NT_STATUS_SUCCESS:
 773                         of = smb_llist_next(&node->n_ofile_list, of);
 774                         break;
 775                 default:
 776                         ASSERT(status == NT_STATUS_SHARING_VIOLATION);
 777                         smb_llist_exit(&node->n_ofile_list);
 778                         return (status);
 779                 }
 780         }
 781         smb_llist_exit(&node->n_ofile_list);
 782         return (NT_STATUS_SUCCESS);
 783 }
 784 
 785 uint32_t
 786 smb_node_delete_check(smb_node_t *node)
 787 {
 788         smb_ofile_t     *of;
 789         uint32_t        status;
 790 
 791         SMB_NODE_VALID(node);
 792 
 793         if (smb_node_is_dir(node))
 794                 return (NT_STATUS_SUCCESS);
 795 
 796         if (smb_node_is_reparse(node))
 797                 return (NT_STATUS_ACCESS_DENIED);
 798 
 799         /*
 800          * intra-CIFS check
 801          */
 802         smb_llist_enter(&node->n_ofile_list, RW_READER);
 803         of = smb_llist_head(&node->n_ofile_list);
 804         while (of) {
 805                 status = smb_ofile_delete_check(of);
 806 
 807                 switch (status) {
 808                 case NT_STATUS_INVALID_HANDLE:
 809                 case NT_STATUS_SUCCESS:
 810                         of = smb_llist_next(&node->n_ofile_list, of);
 811                         break;
 812                 default:
 813                         ASSERT(status == NT_STATUS_SHARING_VIOLATION);
 814                         smb_llist_exit(&node->n_ofile_list);
 815                         return (status);
 816                 }
 817         }
 818         smb_llist_exit(&node->n_ofile_list);
 819         return (NT_STATUS_SUCCESS);
 820 }
 821 
 822 /*
 823  * smb_node_share_check
 824  *
 825  * Returns: TRUE    - ofiles have non-zero share access
 826  *          B_FALSE - ofile with share access NONE.
 827  */
 828 boolean_t
 829 smb_node_share_check(smb_node_t *node)
 830 {
 831         smb_ofile_t     *of;
 832         boolean_t       status = B_TRUE;
 833 
 834         SMB_NODE_VALID(node);
 835 
 836         smb_llist_enter(&node->n_ofile_list, RW_READER);
 837         of = smb_llist_head(&node->n_ofile_list);
 838         if (of)
 839                 status = smb_ofile_share_check(of);
 840         smb_llist_exit(&node->n_ofile_list);
 841 
 842         return (status);
 843 }
 844 
 845 /*
 846  * SMB Change Notification
 847  */
 848 
 849 void
 850 smb_node_fcn_subscribe(smb_node_t *node, smb_request_t *sr)
 851 {
 852         smb_node_fcn_t          *fcn = &node->n_fcn;
 853 
 854         mutex_enter(&fcn->fcn_mutex);
 855         if (fcn->fcn_count == 0)
 856                 (void) smb_fem_fcn_install(node);
 857         fcn->fcn_count++;
 858         list_insert_tail(&fcn->fcn_watchers, sr);
 859         mutex_exit(&fcn->fcn_mutex);
 860 }
 861 
 862 void
 863 smb_node_fcn_unsubscribe(smb_node_t *node, smb_request_t *sr)
 864 {
 865         smb_node_fcn_t          *fcn = &node->n_fcn;
 866 
 867         mutex_enter(&fcn->fcn_mutex);
 868         list_remove(&fcn->fcn_watchers, sr);
 869         fcn->fcn_count--;
 870         if (fcn->fcn_count == 0)
 871                 smb_fem_fcn_uninstall(node);
 872         mutex_exit(&fcn->fcn_mutex);
 873 }
 874 
 875 void
 876 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
 877 {
 878         SMB_NODE_VALID(node);
 879 
 880         smb_notify_event(node, action, name);
 881 
 882         /*
 883          * These two events come as a pair:
 884          *   FILE_ACTION_RENAMED_OLD_NAME
 885          *   FILE_ACTION_RENAMED_NEW_NAME
 886          * Only do the parent notify for "new".
 887          */
 888         if (action == FILE_ACTION_RENAMED_OLD_NAME)
 889                 return;
 890 
 891         smb_node_notify_parents(node);
 892 }
 893 
 894 /*
 895  * smb_node_notify_parents
 896  *
 897  * Iterate up the directory tree notifying any parent
 898  * directories that are being watched for changes in
 899  * their sub directories.
 900  * Stop at the root node, which has a NULL parent node.
 901  */
 902 void
 903 smb_node_notify_parents(smb_node_t *dnode)
 904 {
 905         smb_node_t *pnode;      /* parent */
 906 
 907         SMB_NODE_VALID(dnode);
 908         pnode = dnode->n_dnode;
 909 
 910         while (pnode != NULL) {
 911                 SMB_NODE_VALID(pnode);
 912                 smb_notify_event(pnode, FILE_ACTION_SUBDIR_CHANGED, NULL);
 913                 /* cd .. */
 914                 dnode = pnode;
 915                 pnode = dnode->n_dnode;
 916         }
 917 }
 918 
 919 /*
 920  * smb_node_start_crit()
 921  *
 922  * Enter critical region for share reservations.
 923  * See comments above smb_fsop_shrlock().
 924  */
 925 void
 926 smb_node_start_crit(smb_node_t *node, krw_t mode)
 927 {
 928         rw_enter(&node->n_lock, mode);
 929         nbl_start_crit(node->vp, mode);
 930 }
 931 
 932 /*
 933  * smb_node_end_crit()
 934  *
 935  * Exit critical region for share reservations.
 936  */
 937 void
 938 smb_node_end_crit(smb_node_t *node)
 939 {
 940         nbl_end_crit(node->vp);
 941         rw_exit(&node->n_lock);
 942 }
 943 
 944 int
 945 smb_node_in_crit(smb_node_t *node)
 946 {
 947         return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock));
 948 }
 949 
 950 void
 951 smb_node_rdlock(smb_node_t *node)
 952 {
 953         rw_enter(&node->n_lock, RW_READER);
 954 }
 955 
 956 void
 957 smb_node_wrlock(smb_node_t *node)
 958 {
 959         rw_enter(&node->n_lock, RW_WRITER);
 960 }
 961 
 962 void
 963 smb_node_unlock(smb_node_t *node)
 964 {
 965         rw_exit(&node->n_lock);
 966 }
 967 
 968 void
 969 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of)
 970 {
 971         SMB_NODE_VALID(node);
 972 
 973         smb_llist_enter(&node->n_ofile_list, RW_WRITER);
 974         smb_llist_insert_tail(&node->n_ofile_list, of);
 975         smb_llist_exit(&node->n_ofile_list);
 976 }
 977 
 978 void
 979 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of)
 980 {
 981         SMB_NODE_VALID(node);
 982 
 983         smb_llist_enter(&node->n_ofile_list, RW_WRITER);
 984         smb_llist_remove(&node->n_ofile_list, of);
 985         smb_llist_exit(&node->n_ofile_list);
 986 }
 987 
 988 /*
 989  * smb_node_inc_open_ofiles
 990  */
 991 void
 992 smb_node_inc_open_ofiles(smb_node_t *node)
 993 {
 994         SMB_NODE_VALID(node);
 995         atomic_inc_32(&node->n_open_count);
 996 }
 997 
 998 /*
 999  * smb_node_dec_open_ofiles
1000  * returns new value
1001  */
1002 uint32_t
1003 smb_node_dec_open_ofiles(smb_node_t *node)
1004 {
1005         SMB_NODE_VALID(node);
1006         return (atomic_dec_32_nv(&node->n_open_count));
1007 }
1008 
1009 /*
1010  * smb_node_inc_opening_count
1011  */
1012 void
1013 smb_node_inc_opening_count(smb_node_t *node)
1014 {
1015         SMB_NODE_VALID(node);
1016         atomic_inc_32(&node->n_opening_count);
1017 }
1018 
1019 /*
1020  * smb_node_dec_opening_count
1021  */
1022 void
1023 smb_node_dec_opening_count(smb_node_t *node)
1024 {
1025         SMB_NODE_VALID(node);
1026         atomic_dec_32(&node->n_opening_count);
1027 }
1028 
1029 /*
1030  * smb_node_getmntpath
1031  */
1032 int
1033 smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen)
1034 {
1035         vnode_t *vp, *root_vp;
1036         vfs_t *vfsp;
1037         int err;
1038 
1039         ASSERT(node);
1040         ASSERT(node->vp);
1041         ASSERT(node->vp->v_vfsp);
1042 
1043         vp = node->vp;
1044         vfsp = vp->v_vfsp;
1045 
1046         if (VFS_ROOT(vfsp, &root_vp))
1047                 return (ENOENT);
1048 
1049         VN_HOLD(vp);
1050 
1051         /* NULL is passed in as we want to start at "/" */
1052         err = vnodetopath(NULL, root_vp, buf, buflen, zone_kcred());
1053 
1054         VN_RELE(vp);
1055         VN_RELE(root_vp);
1056         return (err);
1057 }
1058 
1059 /*
1060  * smb_node_getshrpath
1061  *
1062  * Determine the absolute pathname of 'node' within the share (tree).
1063  * For example if the node represents file "test1.txt" in directory
1064  * "dir1" the pathname would be: \dir1\test1.txt
1065  */
1066 int
1067 smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree,
1068     char *buf, uint32_t buflen)
1069 {
1070         int rc;
1071 
1072         ASSERT(node);
1073         ASSERT(tree);
1074         ASSERT(tree->t_snode);
1075 
1076         rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen);
1077         (void) strsubst(buf, '/', '\\');
1078         return (rc);
1079 }
1080 
1081 /*
1082  * smb_node_getpath
1083  *
1084  * Determine the absolute pathname of 'node' from 'rootvp'.
1085  *
1086  * Using vnodetopath is only reliable for directory nodes (due to
1087  * its reliance on the DNLC for non-directory nodes). Thus, if node
1088  * represents a file, construct the pathname for the parent dnode
1089  * and append filename.
1090  * If node represents a named stream, construct the pathname for the
1091  * associated unnamed stream and append the stream name.
1092  *
1093  * The pathname returned in buf will be '/' separated.
1094  */
1095 int
1096 smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen)
1097 {
1098         int rc;
1099         vnode_t *vp;
1100         smb_node_t *unode, *dnode;
1101         cred_t *kcr = zone_kcred();
1102 
1103         unode = (SMB_IS_STREAM(node)) ? node->n_unode : node;
1104         dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode;
1105 
1106         /* find path to directory node */
1107         vp = dnode->vp;
1108         VN_HOLD(vp);
1109         if (rootvp) {
1110                 VN_HOLD(rootvp);
1111                 rc = vnodetopath(rootvp, vp, buf, buflen, kcr);
1112                 VN_RELE(rootvp);
1113         } else {
1114                 rc = vnodetopath(NULL, vp, buf, buflen, kcr);
1115         }
1116         VN_RELE(vp);
1117 
1118         if (rc != 0)
1119                 return (rc);
1120 
1121         /* append filename if necessary */
1122         if (!smb_node_is_dir(unode)) {
1123                 if (buf[strlen(buf) - 1] != '/')
1124                         (void) strlcat(buf, "/", buflen);
1125                 (void) strlcat(buf, unode->od_name, buflen);
1126         }
1127 
1128         /* append named stream name if necessary */
1129         if (SMB_IS_STREAM(node))
1130                 (void) strlcat(buf, node->od_name, buflen);
1131 
1132         return (rc);
1133 }
1134 
1135 /*
1136  * smb_node_alloc
1137  */
1138 static smb_node_t *
1139 smb_node_alloc(
1140     char        *od_name,
1141     vnode_t     *vp,
1142     smb_llist_t *bucket,
1143     uint32_t    hashkey)
1144 {
1145         smb_node_t      *node;
1146         vnode_t         *root_vp;
1147 
1148         node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
1149 
1150         if (node->n_audit_buf != NULL)
1151                 node->n_audit_buf->anb_index = 0;
1152 
1153         node->flags = 0;
1154         VN_HOLD(vp);
1155         node->vp = vp;
1156         node->n_refcnt = 1;
1157         node->n_hash_bucket = bucket;
1158         node->n_hashkey = hashkey;
1159         node->n_pending_dosattr = 0;
1160         node->n_open_count = 0;
1161         node->n_allocsz = 0;
1162         node->n_dnode = NULL;
1163         node->n_unode = NULL;
1164         node->delete_on_close_cred = NULL;
1165         node->n_delete_on_close_flags = 0;
1166         node->n_oplock.ol_fem = B_FALSE;
1167         node->n_oplock.ol_xthread = NULL;
1168         node->n_oplock.ol_count = 0;
1169         node->n_oplock.ol_break = SMB_OPLOCK_NO_BREAK;
1170 
1171         (void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
1172         if (strcmp(od_name, XATTR_DIR) == 0)
1173                 node->flags |= NODE_XATTR_DIR;
1174 
1175         if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) {
1176                 if (vp == root_vp)
1177                         node->flags |= NODE_FLAGS_VFSROOT;
1178                 VN_RELE(root_vp);
1179         }
1180 
1181         node->n_state = SMB_NODE_STATE_AVAILABLE;
1182         node->n_magic = SMB_NODE_MAGIC;
1183 
1184         return (node);
1185 }
1186 
1187 /*
1188  * smb_node_free
1189  */
1190 static void
1191 smb_node_free(smb_node_t *node)
1192 {
1193         SMB_NODE_VALID(node);
1194 
1195         node->n_magic = 0;
1196         VERIFY(!list_link_active(&node->n_lnd));
1197         VERIFY(node->n_lock_list.ll_count == 0);
1198         VERIFY(node->n_ofile_list.ll_count == 0);
1199         VERIFY(node->n_oplock.ol_count == 0);
1200         VERIFY(node->n_oplock.ol_xthread == NULL);
1201         VERIFY(node->n_oplock.ol_fem == B_FALSE);
1202         VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
1203         VERIFY(!RW_LOCK_HELD(&node->n_lock));
1204         VN_RELE(node->vp);
1205         kmem_cache_free(smb_node_cache, node);
1206 }
1207 
1208 /*
1209  * smb_node_constructor
1210  */
1211 static int
1212 smb_node_constructor(void *buf, void *un, int kmflags)
1213 {
1214         _NOTE(ARGUNUSED(kmflags, un))
1215 
1216         smb_node_t      *node = (smb_node_t *)buf;
1217 
1218         bzero(node, sizeof (smb_node_t));
1219 
1220         smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
1221             offsetof(smb_ofile_t, f_nnd));
1222         smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
1223             offsetof(smb_lock_t, l_lnd));
1224         mutex_init(&node->n_fcn.fcn_mutex, NULL, MUTEX_DEFAULT, NULL);
1225         list_create(&node->n_fcn.fcn_watchers, sizeof (smb_request_t),
1226             offsetof(smb_request_t, sr_ncr.nc_lnd));
1227         cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL);
1228         mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
1229         list_create(&node->n_oplock.ol_grants, sizeof (smb_oplock_grant_t),
1230             offsetof(smb_oplock_grant_t, og_lnd));
1231         rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
1232         mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
1233         smb_node_create_audit_buf(node, kmflags);
1234         return (0);
1235 }
1236 
1237 /*
1238  * smb_node_destructor
1239  */
1240 static void
1241 smb_node_destructor(void *buf, void *un)
1242 {
1243         _NOTE(ARGUNUSED(un))
1244 
1245         smb_node_t      *node = (smb_node_t *)buf;
1246 
1247         smb_node_destroy_audit_buf(node);
1248         mutex_destroy(&node->n_mutex);
1249         rw_destroy(&node->n_lock);
1250         cv_destroy(&node->n_oplock.ol_cv);
1251         mutex_destroy(&node->n_oplock.ol_mutex);
1252         list_destroy(&node->n_fcn.fcn_watchers);
1253         mutex_destroy(&node->n_fcn.fcn_mutex);
1254         smb_llist_destructor(&node->n_lock_list);
1255         smb_llist_destructor(&node->n_ofile_list);
1256         list_destroy(&node->n_oplock.ol_grants);
1257 }
1258 
1259 /*
1260  * smb_node_create_audit_buf
1261  */
1262 static void
1263 smb_node_create_audit_buf(smb_node_t *node, int kmflags)
1264 {
1265         smb_audit_buf_node_t    *abn;
1266 
1267         if (smb_audit_flags & SMB_AUDIT_NODE) {
1268                 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
1269                 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
1270                 node->n_audit_buf = abn;
1271         }
1272 }
1273 
1274 /*
1275  * smb_node_destroy_audit_buf
1276  */
1277 static void
1278 smb_node_destroy_audit_buf(smb_node_t *node)
1279 {
1280         if (node->n_audit_buf != NULL) {
1281                 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t));
1282                 node->n_audit_buf = NULL;
1283         }
1284 }
1285 
1286 /*
1287  * smb_node_audit
1288  *
1289  * This function saves the calling stack in the audit buffer of the node passed
1290  * in.
1291  */
1292 static void
1293 smb_node_audit(smb_node_t *node)
1294 {
1295 #ifdef  _KERNEL
1296         smb_audit_buf_node_t    *abn;
1297         smb_audit_record_node_t *anr;
1298 
1299         if (node->n_audit_buf) {
1300                 abn = node->n_audit_buf;
1301                 anr = abn->anb_records;
1302                 anr += abn->anb_index;
1303                 abn->anb_index++;
1304                 abn->anb_index &= abn->anb_max_index;
1305                 anr->anr_refcnt = node->n_refcnt;
1306                 anr->anr_depth = getpcstack(anr->anr_stack,
1307                     SMB_AUDIT_STACK_DEPTH);
1308         }
1309 #else   /* _KERNEL */
1310         _NOTE(ARGUNUSED(node))
1311 #endif  /* _KERNEL */
1312 }
1313 
1314 static smb_llist_t *
1315 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey)
1316 {
1317         uint32_t        hashkey;
1318 
1319         hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid;
1320         hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8);
1321         *phashkey = hashkey;
1322         return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]);
1323 }
1324 
1325 boolean_t
1326 smb_node_is_file(smb_node_t *node)
1327 {
1328         SMB_NODE_VALID(node);
1329         return (node->vp->v_type == VREG);
1330 }
1331 
1332 boolean_t
1333 smb_node_is_dir(smb_node_t *node)
1334 {
1335         SMB_NODE_VALID(node);
1336         return ((node->vp->v_type == VDIR) ||
1337             (node->flags & NODE_FLAGS_DFSLINK));
1338 }
1339 
1340 boolean_t
1341 smb_node_is_symlink(smb_node_t *node)
1342 {
1343         SMB_NODE_VALID(node);
1344         return ((node->vp->v_type == VLNK) &&
1345             ((node->flags & NODE_FLAGS_REPARSE) == 0));
1346 }
1347 
1348 boolean_t
1349 smb_node_is_dfslink(smb_node_t *node)
1350 {
1351         SMB_NODE_VALID(node);
1352         return ((node->vp->v_type == VLNK) &&
1353             (node->flags & NODE_FLAGS_DFSLINK));
1354 }
1355 
1356 boolean_t
1357 smb_node_is_reparse(smb_node_t *node)
1358 {
1359         SMB_NODE_VALID(node);
1360         return ((node->vp->v_type == VLNK) &&
1361             (node->flags & NODE_FLAGS_REPARSE));
1362 }
1363 
1364 boolean_t
1365 smb_node_is_vfsroot(smb_node_t *node)
1366 {
1367         SMB_NODE_VALID(node);
1368         return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT);
1369 }
1370 
1371 boolean_t
1372 smb_node_is_system(smb_node_t *node)
1373 {
1374         SMB_NODE_VALID(node);
1375         return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM);
1376 }
1377 
1378 /*
1379  * smb_node_file_is_readonly
1380  *
1381  * Checks if the file (which node represents) is marked readonly
1382  * in the filesystem. No account is taken of any pending readonly
1383  * in the node, which must be handled by the callers.
1384  * (See SMB_OFILE_IS_READONLY and SMB_PATHFILE_IS_READONLY)
1385  */
1386 boolean_t
1387 smb_node_file_is_readonly(smb_node_t *node)
1388 {
1389         smb_attr_t attr;
1390 
1391         if (node == NULL)
1392                 return (B_FALSE);       /* pipes */
1393 
1394         if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY)
1395                 return (B_TRUE);
1396 
1397         bzero(&attr, sizeof (smb_attr_t));
1398         attr.sa_mask = SMB_AT_DOSATTR;
1399         (void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
1400         return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0);
1401 }
1402 
1403 /*
1404  * smb_node_setattr
1405  *
1406  * The sr may be NULL, for example when closing an ofile.
1407  * The ofile may be NULL, for example when a client request
1408  * specifies the file by pathname.
1409  *
1410  * Returns: errno
1411  *
1412  * Timestamps
1413  *
1414  * Windows and Unix have different models for timestamp updates.
1415  * [MS-FSA 2.1.5.14 Server Requests Setting of File Information]
1416  *
1417  * An open "handle" in Windows can control whether and when
1418  * any timestamp updates happen for that handle.  For example,
1419  * timestamps set via some handle are no longer updated by I/O
1420  * operations on that handle.  In Unix we don't really have any
1421  * way to avoid the timestamp updates that the file system does.
1422  * Therefore, we need to make some compromises, and simulate the
1423  * more important parts of the Windows file system semantics.
1424  *
1425  * For example, when an SMB client sets file times, set those
1426  * times in the file system (so the change will be visible to
1427  * other clients, at least until they change again) but we also
1428  * make those times "sticky" in our open handle, and reapply
1429  * those times when the handle is closed.  That reapply on close
1430  * simulates the Windows behavior where the timestamp updates
1431  * would be discontinued after they were set.  These "sticky"
1432  * attributes are returned in any query on the handle where
1433  * they are stored.
1434  *
1435  * Other than the above, the file system layer takes care of the
1436  * normal time stamp updates, such as updating the mtime after a
1437  * write, and ctime after an attribute change.
1438  *
1439  * Dos Attributes are stored persistently, but with a twist:
1440  * In Windows, when you set the "read-only" bit on some file,
1441  * existing writable handles to that file continue to have
1442  * write access.  (because access check happens at open)
1443  * If we were to set the read-only bit directly, we would
1444  * cause errors in subsequent writes on any of our open
1445  * (and writable) file handles.  So here too, we have to
1446  * simulate the Windows behavior.  We keep the read-only
1447  * bit "pending" in the smb_node (so it will be visible in
1448  * any new opens of the file) and apply it on close.
1449  *
1450  * File allocation size is also simulated, and not persistent.
1451  * When the file allocation size is set it is first rounded up
1452  * to block size. If the file size is smaller than the allocation
1453  * size the file is truncated by setting the filesize to allocsz.
1454  */
1455 int
1456 smb_node_setattr(smb_request_t *sr, smb_node_t *node,
1457     cred_t *cr, smb_ofile_t *of, smb_attr_t *attr)
1458 {
1459         int rc;
1460         uint_t times_mask;
1461         smb_attr_t tmp_attr;
1462 
1463         SMB_NODE_VALID(node);
1464 
1465         /* set attributes specified in attr */
1466         if (attr->sa_mask == 0)
1467                 return (0);  /* nothing to do (caller bug?) */
1468 
1469         /*
1470          * Allocation size and EOF position interact.
1471          * We don't persistently store the allocation size
1472          * but make it look like we do while there are opens.
1473          * Note: We update the caller's attr in the cases
1474          * where they're setting only one of allocsz|size.
1475          */
1476         switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) {
1477 
1478         case SMB_AT_ALLOCSZ:
1479                 /*
1480                  * Setting the allocation size but not EOF position.
1481                  * Get the current EOF in tmp_attr and (if necessary)
1482                  * truncate to the (rounded up) allocation size.
1483                  * Using kcred here because if we don't have access,
1484                  * we want to fail at setattr below and not here.
1485                  */
1486                 bzero(&tmp_attr, sizeof (smb_attr_t));
1487                 tmp_attr.sa_mask = SMB_AT_SIZE;
1488                 rc = smb_fsop_getattr(NULL, zone_kcred(), node, &tmp_attr);
1489                 if (rc != 0)
1490                         return (rc);
1491                 attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz);
1492                 if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) {
1493                         /* truncate the file to allocsz */
1494                         attr->sa_vattr.va_size = attr->sa_allocsz;
1495                         attr->sa_mask |= SMB_AT_SIZE;
1496                 }
1497                 break;
1498 
1499         case SMB_AT_SIZE:
1500                 /*
1501                  * Setting the EOF position but not allocation size.
1502                  * If the new EOF position would be greater than
1503                  * the allocation size, increase the latter.
1504                  */
1505                 if (node->n_allocsz < attr->sa_vattr.va_size) {
1506                         attr->sa_mask |= SMB_AT_ALLOCSZ;
1507                         attr->sa_allocsz =
1508                             SMB_ALLOCSZ(attr->sa_vattr.va_size);
1509                 }
1510                 break;
1511 
1512         case SMB_AT_ALLOCSZ | SMB_AT_SIZE:
1513                 /*
1514                  * Setting both.  Increase alloc size if needed.
1515                  */
1516                 if (attr->sa_allocsz < attr->sa_vattr.va_size)
1517                         attr->sa_allocsz =
1518                             SMB_ALLOCSZ(attr->sa_vattr.va_size);
1519                 break;
1520 
1521         default:
1522                 break;
1523         }
1524 
1525         /*
1526          * If we have an open file, and we set the size,
1527          * then set the "written" flag so that at close,
1528          * we can force an mtime update.
1529          */
1530         if (of != NULL && (attr->sa_mask & SMB_AT_SIZE) != 0)
1531                 of->f_written = B_TRUE;
1532 
1533         /*
1534          * When operating on an open file, some settable attributes
1535          * become "sticky" in the open file object until close.
1536          * (see above re. timestamps)
1537          */
1538         times_mask = attr->sa_mask & SMB_AT_TIMES;
1539         if (of != NULL && times_mask != 0) {
1540                 smb_attr_t *pa;
1541 
1542                 SMB_OFILE_VALID(of);
1543                 mutex_enter(&of->f_mutex);
1544                 pa = &of->f_pending_attr;
1545 
1546                 pa->sa_mask |= times_mask;
1547 
1548                 if (times_mask & SMB_AT_ATIME)
1549                         pa->sa_vattr.va_atime =
1550                             attr->sa_vattr.va_atime;
1551                 if (times_mask & SMB_AT_MTIME)
1552                         pa->sa_vattr.va_mtime =
1553                             attr->sa_vattr.va_mtime;
1554                 if (times_mask & SMB_AT_CTIME)
1555                         pa->sa_vattr.va_ctime =
1556                             attr->sa_vattr.va_ctime;
1557                 if (times_mask & SMB_AT_CRTIME)
1558                         pa->sa_crtime =
1559                             attr->sa_crtime;
1560 
1561                 mutex_exit(&of->f_mutex);
1562                 /*
1563                  * The f_pending_attr times are reapplied in
1564                  * smb_ofile_close().
1565                  */
1566         }
1567 
1568         /*
1569          * After this point, tmp_attr is what we will actually
1570          * store in the file system _now_, which may differ
1571          * from the callers attr and f_pending_attr w.r.t.
1572          * the DOS readonly flag etc.
1573          */
1574         bcopy(attr, &tmp_attr, sizeof (tmp_attr));
1575         if (attr->sa_mask & (SMB_AT_DOSATTR | SMB_AT_ALLOCSZ)) {
1576                 mutex_enter(&node->n_mutex);
1577                 if ((attr->sa_mask & SMB_AT_DOSATTR) != 0) {
1578                         tmp_attr.sa_dosattr &= smb_vop_dosattr_settable;
1579                         if (((tmp_attr.sa_dosattr &
1580                             FILE_ATTRIBUTE_READONLY) != 0) &&
1581                             (node->n_open_count != 0)) {
1582                                 /* Delay setting readonly */
1583                                 node->n_pending_dosattr =
1584                                     tmp_attr.sa_dosattr;
1585                                 tmp_attr.sa_dosattr &=
1586                                     ~FILE_ATTRIBUTE_READONLY;
1587                         } else {
1588                                 node->n_pending_dosattr = 0;
1589                         }
1590                 }
1591                 /*
1592                  * Simulate n_allocsz persistence only while
1593                  * there are opens.  See smb_node_getattr
1594                  */
1595                 if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0 &&
1596                     node->n_open_count != 0)
1597                         node->n_allocsz = attr->sa_allocsz;
1598                 mutex_exit(&node->n_mutex);
1599         }
1600 
1601         rc = smb_fsop_setattr(sr, cr, node, &tmp_attr);
1602         if (rc != 0)
1603                 return (rc);
1604 
1605         if (node->n_dnode != NULL) {
1606                 smb_node_notify_change(node->n_dnode,
1607                     FILE_ACTION_MODIFIED, node->od_name);
1608         }
1609 
1610         return (0);
1611 }
1612 
1613 /*
1614  * smb_node_getattr
1615  *
1616  * Get attributes from the file system and apply any smb-specific
1617  * overrides for size, dos attributes and timestamps
1618  *
1619  * When node->n_pending_readonly is set on a node, pretend that
1620  * we've already set this node readonly at the filesystem level.
1621  * We can't actually do that until all writable handles are closed
1622  * or those writable handles would suddenly loose their access.
1623  *
1624  * Returns: errno
1625  */
1626 int
1627 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
1628     smb_ofile_t *of, smb_attr_t *attr)
1629 {
1630         int rc;
1631         uint_t want_mask, pend_mask;
1632         boolean_t isdir;
1633 
1634         SMB_NODE_VALID(node);
1635 
1636         /* Deal with some interdependencies */
1637         if (attr->sa_mask & SMB_AT_ALLOCSZ)
1638                 attr->sa_mask |= SMB_AT_SIZE;
1639         if (attr->sa_mask & SMB_AT_DOSATTR)
1640                 attr->sa_mask |= SMB_AT_TYPE;
1641 
1642         rc = smb_fsop_getattr(sr, cr, node, attr);
1643         if (rc != 0)
1644                 return (rc);
1645 
1646         isdir = smb_node_is_dir(node);
1647 
1648         mutex_enter(&node->n_mutex);
1649 
1650         /*
1651          * When there are open handles, and one of them has
1652          * set the DOS readonly flag (in n_pending_dosattr),
1653          * it will not have been stored in the file system.
1654          * In this case use n_pending_dosattr. Note that
1655          * n_pending_dosattr has only the settable bits,
1656          * (setattr masks it with smb_vop_dosattr_settable)
1657          * so we need to keep any non-settable bits we got
1658          * from the file-system above.
1659          */
1660         if (attr->sa_mask & SMB_AT_DOSATTR) {
1661                 if (node->n_pending_dosattr) {
1662                         attr->sa_dosattr &= ~smb_vop_dosattr_settable;
1663                         attr->sa_dosattr |= node->n_pending_dosattr;
1664                 }
1665                 if (attr->sa_dosattr == 0) {
1666                         attr->sa_dosattr = (isdir) ?
1667                             FILE_ATTRIBUTE_DIRECTORY:
1668                             FILE_ATTRIBUTE_NORMAL;
1669                 }
1670         }
1671 
1672         /*
1673          * Also fix-up sa_allocsz, which is not persistent.
1674          * When there are no open files, allocsz is faked.
1675          * While there are open files, we pretend we have a
1676          * persistent allocation size in n_allocsz, and
1677          * keep that up-to-date here, increasing it when
1678          * we see the file size grow past it.
1679          */
1680         if (attr->sa_mask & SMB_AT_ALLOCSZ) {
1681                 if (isdir) {
1682                         attr->sa_allocsz = 0;
1683                 } else if (node->n_open_count == 0) {
1684                         attr->sa_allocsz =
1685                             SMB_ALLOCSZ(attr->sa_vattr.va_size);
1686                 } else {
1687                         if (node->n_allocsz < attr->sa_vattr.va_size)
1688                                 node->n_allocsz =
1689                                     SMB_ALLOCSZ(attr->sa_vattr.va_size);
1690                         attr->sa_allocsz = node->n_allocsz;
1691                 }
1692         }
1693 
1694         mutex_exit(&node->n_mutex);
1695 
1696         if (isdir) {
1697                 attr->sa_vattr.va_size = 0;
1698                 attr->sa_vattr.va_nlink = 1;
1699         }
1700 
1701         /*
1702          * getattr with an ofile gets any "pending" times that
1703          * might have been previously set via this ofile.
1704          * This is what makes these times "sticky".
1705          */
1706         want_mask = attr->sa_mask & SMB_AT_TIMES;
1707         if (of != NULL && want_mask != 0) {
1708                 smb_attr_t *pa;
1709 
1710                 SMB_OFILE_VALID(of);
1711                 mutex_enter(&of->f_mutex);
1712                 pa = &of->f_pending_attr;
1713 
1714                 pend_mask = pa->sa_mask;
1715 
1716                 if (want_mask & pend_mask & SMB_AT_ATIME)
1717                         attr->sa_vattr.va_atime =
1718                             pa->sa_vattr.va_atime;
1719                 if (want_mask & pend_mask & SMB_AT_MTIME)
1720                         attr->sa_vattr.va_mtime =
1721                             pa->sa_vattr.va_mtime;
1722                 if (want_mask & pend_mask & SMB_AT_CTIME)
1723                         attr->sa_vattr.va_ctime =
1724                             pa->sa_vattr.va_ctime;
1725                 if (want_mask & pend_mask & SMB_AT_CRTIME)
1726                         attr->sa_crtime =
1727                             pa->sa_crtime;
1728 
1729                 mutex_exit(&of->f_mutex);
1730         }
1731 
1732 
1733         return (0);
1734 }
1735 
1736 
1737 #ifndef _KERNEL
1738 extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl);
1739 #endif  /* _KERNEL */
1740 
1741 /*
1742  * Check to see if the node represents a reparse point.
1743  * If yes, whether the reparse point contains a DFS link.
1744  */
1745 static void
1746 smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr)
1747 {
1748         nvlist_t *nvl;
1749         nvpair_t *rec;
1750         char *rec_type;
1751 
1752         if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
1753                 return;
1754 
1755         if ((nvl = reparse_init()) == NULL)
1756                 return;
1757 
1758         if (reparse_vnode_parse(node->vp, nvl) != 0) {
1759                 reparse_free(nvl);
1760                 return;
1761         }
1762 
1763         node->flags |= NODE_FLAGS_REPARSE;
1764 
1765         rec = nvlist_next_nvpair(nvl, NULL);
1766         while (rec != NULL) {
1767                 rec_type = nvpair_name(rec);
1768                 if ((rec_type != NULL) &&
1769                     (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) {
1770                         node->flags |= NODE_FLAGS_DFSLINK;
1771                         break;
1772                 }
1773                 rec = nvlist_next_nvpair(nvl, rec);
1774         }
1775 
1776         reparse_free(nvl);
1777 }
1778 
1779 /*
1780  * smb_node_init_system
1781  *
1782  * If the node represents a special system file set NODE_FLAG_SYSTEM.
1783  * System files:
1784  * - any node whose parent dnode has NODE_FLAG_SYSTEM set
1785  * - any node whose associated unnamed stream node (unode) has
1786  *   NODE_FLAG_SYSTEM set
1787  * - .$EXTEND at root of share (quota management)
1788  */
1789 static void
1790 smb_node_init_system(smb_node_t *node)
1791 {
1792         smb_node_t *dnode = node->n_dnode;
1793         smb_node_t *unode = node->n_unode;
1794 
1795         if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) {
1796                 node->flags |= NODE_FLAGS_SYSTEM;
1797                 return;
1798         }
1799 
1800         if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) {
1801                 node->flags |= NODE_FLAGS_SYSTEM;
1802                 return;
1803         }
1804 
1805         if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) &&
1806             (strcasecmp(node->od_name, ".$EXTEND") == 0))) {
1807                 node->flags |= NODE_FLAGS_SYSTEM;
1808         }
1809 }