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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * SMB Node State Machine 27 * ---------------------- 28 * 29 * 30 * +----------- Creation/Allocation 31 * | 32 * | T0 33 * | 34 * v 35 * +----------------------------+ T1 36 * | SMB_NODE_STATE_AVAILABLE |--------------------+ 37 * +----------------------------+ | 38 * | ^ | 39 * | | v 40 * | | T2 +-------------------------------+ 41 * | |<---------| SMB_NODE_STATE_OPLOCK_GRANTED | 42 * | | +-------------------------------+ 43 * | T5 | | 44 * | | | T3 45 * | | v 46 * | | T4 +--------------------------------+ 47 * | +----------| SMB_NODE_STATE_OPLOCK_BREAKING | 48 * | +--------------------------------+ 49 * | 50 * v 51 * +-----------------------------+ 52 * | SMB_NODE_STATE_DESTROYING | 53 * +-----------------------------+ 54 * | 55 * | 56 * | T6 57 * | 58 * +----------> Deletion/Free 59 * 60 * Transition T0 61 * 62 * This transition occurs in smb_node_lookup(). If the node looked for is 63 * not found in the has table a new node is created. The reference count is 64 * initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE. 65 * 66 * Transition T1 67 * 68 * This transition occurs smb_oplock_acquire() during an OPEN. 69 * 70 * Transition T2 71 * 72 * This transition occurs in smb_oplock_release(). The events triggering 73 * it are: 74 * 75 * - LockingAndX sent by the client that was granted the oplock. 76 * - Closing of the file. 77 * 78 * Transition T3 79 * 80 * This transition occurs in smb_oplock_break(). The events triggering 81 * it are: 82 * 83 * - Another client wants to open the file. 84 * - A client is trying to delete the file. 85 * - A client is trying to rename the file. 86 * - A client is trying to set/modify the file attributes. 87 * 88 * Transition T4 89 * 90 * This transition occurs in smb_oplock_release or smb_oplock_break(). The 91 * events triggering it are: 92 * 93 * - The client that was granting the oplock releases it (close or 94 * LockingAndx). 95 * - The time alloted to release the oplock expired. 96 * 97 * Transition T5 98 * 99 * This transition occurs in smb_node_release(). If the reference count 100 * drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more 101 * reference count will be given out for that node. 102 * 103 * Transition T6 104 * 105 * This transition occurs in smb_node_release(). The structure is deleted. 106 * 107 * Comments 108 * -------- 109 * 110 * The reason the smb node has 2 states is the following synchronization 111 * rule: 112 * 113 * There's a mutex embedded in the node used to protect its fields and 114 * there's a lock embedded in the bucket of the hash table the node belongs 115 * to. To increment or to decrement the reference count the mutex must be 116 * entered. To insert the node into the bucket and to remove it from the 117 * bucket the lock must be entered in RW_WRITER mode. When both (mutex and 118 * lock) have to be entered, the lock has always to be entered first then 119 * the mutex. This prevents a deadlock between smb_node_lookup() and 120 * smb_node_release() from occurring. However, in smb_node_release() when the 121 * reference count drops to zero and triggers the deletion of the node, the 122 * mutex has to be released before entering the lock of the bucket (to 123 * remove the node). This creates a window during which the node that is 124 * about to be freed could be given out by smb_node_lookup(). To close that 125 * window the node is moved to the state SMB_NODE_STATE_DESTROYING before 126 * releasing the mutex. That way, even if smb_node_lookup() finds it, the 127 * state will indicate that the node should be treated as non existent (of 128 * course the state of the node should be tested/updated under the 129 * protection of the mutex). 130 */ 131 #include <smbsrv/smb_incl.h> 132 #include <smbsrv/smb_fsops.h> 133 #include <smbsrv/smb_kstat.h> 134 #include <sys/pathname.h> 135 #include <sys/sdt.h> 136 #include <sys/nbmlock.h> 137 138 uint32_t smb_is_executable(char *); 139 static void smb_node_delete_on_close(smb_node_t *); 140 static void smb_node_create_audit_buf(smb_node_t *, int); 141 static void smb_node_destroy_audit_buf(smb_node_t *); 142 static void smb_node_audit(smb_node_t *); 143 static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_attr_t *, 144 smb_llist_t *bucket, uint32_t hashkey); 145 static void smb_node_free(smb_node_t *); 146 static int smb_node_constructor(void *, void *, int); 147 static void smb_node_destructor(void *, void *); 148 static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *); 149 150 #define VALIDATE_DIR_NODE(_dir_, _node_) \ 151 ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \ 152 ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \ 153 ASSERT((_dir_)->dir_snode != (_node_)); 154 155 static kmem_cache_t *smb_node_cache = NULL; 156 static boolean_t smb_node_initialized = B_FALSE; 157 static smb_llist_t smb_node_hash_table[SMBND_HASH_MASK+1]; 158 159 /* 160 * smb_node_init 161 * 162 * Initialization of the SMB node layer. 163 * 164 * This function is not multi-thread safe. The caller must make sure only one 165 * thread makes the call. 166 */ 167 int 168 smb_node_init(void) 169 { 170 int i; 171 172 if (smb_node_initialized) 173 return (0); 174 smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE, 175 sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor, 176 NULL, NULL, NULL, 0); 177 178 for (i = 0; i <= SMBND_HASH_MASK; i++) { 179 smb_llist_constructor(&smb_node_hash_table[i], 180 sizeof (smb_node_t), offsetof(smb_node_t, n_lnd)); 181 } 182 smb_node_initialized = B_TRUE; 183 return (0); 184 } 185 186 /* 187 * smb_node_fini 188 * 189 * This function is not multi-thread safe. The caller must make sure only one 190 * thread makes the call. 191 */ 192 void 193 smb_node_fini(void) 194 { 195 int i; 196 197 if (!smb_node_initialized) 198 return; 199 200 #ifdef DEBUG 201 for (i = 0; i <= SMBND_HASH_MASK; i++) { 202 smb_node_t *node; 203 204 /* 205 * The following sequence is just intended for sanity check. 206 * This will have to be modified when the code goes into 207 * production. 208 * 209 * The SMB node hash table should be emtpy at this point. If the 210 * hash table is not empty a panic will be triggered. 211 * 212 * The reason why SMB nodes are still remaining in the hash 213 * table is problably due to a mismatch between calls to 214 * smb_node_lookup() and smb_node_release(). You must track that 215 * down. 216 */ 217 node = smb_llist_head(&smb_node_hash_table[i]); 218 ASSERT(node == NULL); 219 } 220 #endif 221 222 for (i = 0; i <= SMBND_HASH_MASK; i++) { 223 smb_llist_destructor(&smb_node_hash_table[i]); 224 } 225 kmem_cache_destroy(smb_node_cache); 226 smb_node_cache = NULL; 227 smb_node_initialized = B_FALSE; 228 } 229 230 /* 231 * smb_node_lookup() 232 * 233 * NOTE: This routine should only be called by the file system interface layer, 234 * and not by SMB. 235 * 236 * smb_node_lookup() is called upon successful lookup, mkdir, and create 237 * (for both non-streams and streams). In each of these cases, a held vnode is 238 * passed into this routine. If a new smb_node is created it will take its 239 * own hold on the vnode. The caller's hold therefore still belongs to, and 240 * should be released by, the caller. 241 * 242 * A reference is taken on the smb_node whether found in the hash table 243 * or newly created. 244 * 245 * If an smb_node needs to be created, a reference is also taken on the 246 * dir_snode (if passed in). 247 * 248 * See smb_node_release() for details on the release of these references. 249 */ 250 251 /*ARGSUSED*/ 252 smb_node_t * 253 smb_node_lookup( 254 struct smb_request *sr, 255 struct open_param *op, 256 cred_t *cred, 257 vnode_t *vp, 258 char *od_name, 259 smb_node_t *dir_snode, 260 smb_node_t *unnamed_node, 261 smb_attr_t *attr) 262 { 263 smb_llist_t *node_hdr; 264 smb_node_t *node; 265 uint32_t hashkey = 0; 266 fsid_t fsid; 267 int error; 268 krw_t lock_mode; 269 vnode_t *unnamed_vp = NULL; 270 271 /* 272 * smb_vop_getattr() is called here instead of smb_fsop_getattr(), 273 * because the node may not yet exist. We also do not want to call 274 * it with the list lock held. 275 */ 276 277 if (unnamed_node) 278 unnamed_vp = unnamed_node->vp; 279 280 /* 281 * This getattr is performed on behalf of the server 282 * that's why kcred is used not the user's cred 283 */ 284 attr->sa_mask = SMB_AT_ALL; 285 error = smb_vop_getattr(vp, unnamed_vp, attr, 0, kcred); 286 if (error) 287 return (NULL); 288 289 if (sr && sr->tid_tree) { 290 /* 291 * The fsid for a file is that of the tree, even 292 * if the file resides in a different mountpoint 293 * under the share. 294 */ 295 fsid = SMB_TREE_FSID(sr->tid_tree); 296 } else { 297 /* 298 * This should be getting executed only for the 299 * tree root smb_node. 300 */ 301 fsid = vp->v_vfsp->vfs_fsid; 302 } 303 304 node_hdr = smb_node_get_hash(&fsid, attr, &hashkey); 305 lock_mode = RW_READER; 306 307 smb_llist_enter(node_hdr, lock_mode); 308 for (;;) { 309 node = list_head(&node_hdr->ll_list); 310 while (node) { 311 ASSERT(node->n_magic == SMB_NODE_MAGIC); 312 ASSERT(node->n_hash_bucket == node_hdr); 313 if ((node->n_hashkey == hashkey) && (node->vp == vp)) { 314 mutex_enter(&node->n_mutex); 315 DTRACE_PROBE1(smb_node_lookup_hit, 316 smb_node_t *, node); 317 switch (node->n_state) { 318 case SMB_NODE_STATE_OPLOCK_GRANTED: 319 case SMB_NODE_STATE_OPLOCK_BREAKING: 320 case SMB_NODE_STATE_AVAILABLE: 321 /* The node was found. */ 322 node->n_refcnt++; 323 if ((node->dir_snode == NULL) && 324 (dir_snode != NULL) && 325 (strcmp(od_name, "..") != 0) && 326 (strcmp(od_name, ".") != 0)) { 327 VALIDATE_DIR_NODE(dir_snode, 328 node); 329 node->dir_snode = dir_snode; 330 smb_node_ref(dir_snode); 331 } 332 node->attr = *attr; 333 node->n_size = attr->sa_vattr.va_size; 334 335 smb_node_audit(node); 336 mutex_exit(&node->n_mutex); 337 smb_llist_exit(node_hdr); 338 return (node); 339 340 case SMB_NODE_STATE_DESTROYING: 341 /* 342 * Although the node exists it is about 343 * to be destroyed. We act as it hasn't 344 * been found. 345 */ 346 mutex_exit(&node->n_mutex); 347 break; 348 default: 349 /* 350 * Although the node exists it is in an 351 * unknown state. We act as it hasn't 352 * been found. 353 */ 354 ASSERT(0); 355 mutex_exit(&node->n_mutex); 356 break; 357 } 358 } 359 node = smb_llist_next(node_hdr, node); 360 } 361 if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) { 362 lock_mode = RW_WRITER; 363 continue; 364 } 365 break; 366 } 367 node = smb_node_alloc(od_name, vp, attr, node_hdr, hashkey); 368 node->n_orig_uid = crgetuid(sr->user_cr); 369 370 if (op) 371 node->flags |= smb_is_executable(op->fqi.last_comp); 372 373 if (dir_snode) { 374 smb_node_ref(dir_snode); 375 node->dir_snode = dir_snode; 376 ASSERT(dir_snode->dir_snode != node); 377 ASSERT((dir_snode->vp->v_xattrdir) || 378 (dir_snode->vp->v_type == VDIR)); 379 } 380 381 if (unnamed_node) { 382 smb_node_ref(unnamed_node); 383 node->unnamed_stream_node = unnamed_node; 384 } 385 386 DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node); 387 smb_node_audit(node); 388 smb_llist_insert_head(node_hdr, node); 389 smb_llist_exit(node_hdr); 390 return (node); 391 } 392 393 /* 394 * smb_stream_node_lookup() 395 * 396 * Note: stream_name (the name that will be stored in the "od_name" field 397 * of a stream's smb_node) is the same as the on-disk name for the stream 398 * except that it does not have SMB_STREAM_PREFIX prepended. 399 */ 400 401 smb_node_t * 402 smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode, 403 vnode_t *xattrdirvp, vnode_t *vp, char *stream_name, smb_attr_t *ret_attr) 404 { 405 smb_node_t *xattrdir_node; 406 smb_node_t *snode; 407 smb_attr_t tmp_attr; 408 409 xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR, 410 fnode, NULL, &tmp_attr); 411 412 if (xattrdir_node == NULL) 413 return (NULL); 414 415 snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node, 416 fnode, ret_attr); 417 418 (void) smb_node_release(xattrdir_node); 419 return (snode); 420 } 421 422 423 /* 424 * This function should be called whenever a reference is needed on an 425 * smb_node pointer. The copy of an smb_node pointer from one non-local 426 * data structure to another requires a reference to be taken on the smb_node 427 * (unless the usage is localized). Each data structure deallocation routine 428 * will call smb_node_release() on its smb_node pointers. 429 * 430 * In general, an smb_node pointer residing in a structure should never be 431 * stale. A node pointer may be NULL, however, and care should be taken 432 * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid. 433 * Care also needs to be taken with respect to racing deallocations of a 434 * structure. 435 */ 436 void 437 smb_node_ref(smb_node_t *node) 438 { 439 SMB_NODE_VALID(node); 440 441 mutex_enter(&node->n_mutex); 442 switch (node->n_state) { 443 case SMB_NODE_STATE_AVAILABLE: 444 case SMB_NODE_STATE_OPLOCK_GRANTED: 445 case SMB_NODE_STATE_OPLOCK_BREAKING: 446 node->n_refcnt++; 447 ASSERT(node->n_refcnt); 448 DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node); 449 smb_node_audit(node); 450 break; 451 default: 452 SMB_PANIC(); 453 } 454 mutex_exit(&node->n_mutex); 455 } 456 457 /* 458 * smb_node_lookup() takes a hold on an smb_node, whether found in the 459 * hash table or newly created. This hold is expected to be released 460 * in the following manner. 461 * 462 * smb_node_lookup() takes an address of an smb_node pointer. This should 463 * be getting passed down via a lookup (whether path name or component), mkdir, 464 * create. If the original smb_node pointer resides in a data structure, then 465 * the deallocation routine for the data structure is responsible for calling 466 * smb_node_release() on the smb_node pointer. Alternatively, 467 * smb_node_release() can be called as soon as the smb_node pointer is no longer 468 * needed. In this case, callers are responsible for setting an embedded 469 * pointer to NULL if it is known that the last reference is being released. 470 * 471 * If the passed-in address of the smb_node pointer belongs to a local variable, 472 * then the caller with the local variable should call smb_node_release() 473 * directly. 474 * 475 * smb_node_release() itself will call smb_node_release() on a node's dir_snode, 476 * as smb_node_lookup() takes a hold on dir_snode. 477 */ 478 void 479 smb_node_release(smb_node_t *node) 480 { 481 SMB_NODE_VALID(node); 482 483 mutex_enter(&node->n_mutex); 484 ASSERT(node->n_refcnt); 485 DTRACE_PROBE1(smb_node_release, smb_node_t *, node); 486 if (--node->n_refcnt == 0) { 487 switch (node->n_state) { 488 489 case SMB_NODE_STATE_AVAILABLE: 490 node->n_state = SMB_NODE_STATE_DESTROYING; 491 mutex_exit(&node->n_mutex); 492 493 smb_llist_enter(node->n_hash_bucket, RW_WRITER); 494 smb_llist_remove(node->n_hash_bucket, node); 495 smb_llist_exit(node->n_hash_bucket); 496 497 /* 498 * Check if the file was deleted 499 */ 500 smb_node_delete_on_close(node); 501 502 if (node->dir_snode) { 503 ASSERT(node->dir_snode->n_magic == 504 SMB_NODE_MAGIC); 505 smb_node_release(node->dir_snode); 506 } 507 508 if (node->unnamed_stream_node) { 509 ASSERT(node->unnamed_stream_node->n_magic == 510 SMB_NODE_MAGIC); 511 smb_node_release(node->unnamed_stream_node); 512 } 513 514 smb_node_free(node); 515 return; 516 517 default: 518 SMB_PANIC(); 519 } 520 } 521 smb_node_audit(node); 522 mutex_exit(&node->n_mutex); 523 } 524 525 static void 526 smb_node_delete_on_close(smb_node_t *node) 527 { 528 smb_node_t *d_snode; 529 int rc = 0; 530 uint32_t flags = 0; 531 532 d_snode = node->dir_snode; 533 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 534 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 535 flags = node->n_delete_on_close_flags; 536 ASSERT(node->od_name != NULL); 537 538 if (node->attr.sa_vattr.va_type == VDIR) 539 rc = smb_fsop_rmdir(0, node->delete_on_close_cred, 540 d_snode, node->od_name, flags); 541 else 542 rc = smb_fsop_remove(0, node->delete_on_close_cred, 543 d_snode, node->od_name, flags); 544 smb_cred_rele(node->delete_on_close_cred); 545 } 546 if (rc != 0) 547 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n", 548 node->od_name, rc); 549 DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node); 550 } 551 552 /* 553 * smb_node_rename() 554 * 555 */ 556 void 557 smb_node_rename( 558 smb_node_t *from_dnode, 559 smb_node_t *ret_node, 560 smb_node_t *to_dnode, 561 char *to_name) 562 { 563 SMB_NODE_VALID(from_dnode); 564 SMB_NODE_VALID(to_dnode); 565 SMB_NODE_VALID(ret_node); 566 567 smb_node_ref(to_dnode); 568 mutex_enter(&ret_node->n_mutex); 569 switch (ret_node->n_state) { 570 case SMB_NODE_STATE_AVAILABLE: 571 case SMB_NODE_STATE_OPLOCK_GRANTED: 572 case SMB_NODE_STATE_OPLOCK_BREAKING: 573 ret_node->dir_snode = to_dnode; 574 mutex_exit(&ret_node->n_mutex); 575 ASSERT(to_dnode->dir_snode != ret_node); 576 ASSERT((to_dnode->vp->v_xattrdir) || 577 (to_dnode->vp->v_type == VDIR)); 578 smb_node_release(from_dnode); 579 (void) strcpy(ret_node->od_name, to_name); 580 /* 581 * XXX Need to update attributes? 582 */ 583 break; 584 default: 585 SMB_PANIC(); 586 } 587 } 588 589 int 590 smb_node_root_init(vnode_t *vp, smb_server_t *sv, smb_node_t **root) 591 { 592 smb_attr_t va; 593 int error; 594 uint32_t hashkey; 595 smb_llist_t *node_hdr; 596 smb_node_t *node; 597 598 va.sa_mask = SMB_AT_ALL; 599 error = smb_vop_getattr(vp, NULL, &va, 0, kcred); 600 if (error) { 601 VN_RELE(vp); 602 return (error); 603 } 604 605 node_hdr = smb_node_get_hash(&vp->v_vfsp->vfs_fsid, &va, &hashkey); 606 607 node = smb_node_alloc(ROOTVOL, vp, &va, node_hdr, hashkey); 608 609 sv->si_root_smb_node = node; 610 smb_node_audit(node); 611 smb_llist_enter(node_hdr, RW_WRITER); 612 smb_llist_insert_head(node_hdr, node); 613 smb_llist_exit(node_hdr); 614 *root = node; 615 return (0); 616 } 617 618 /* 619 * smb_node_get_size 620 */ 621 u_offset_t 622 smb_node_get_size(smb_node_t *node, smb_attr_t *attr) 623 { 624 u_offset_t size; 625 626 if (attr->sa_vattr.va_type == VDIR) 627 return (0); 628 629 mutex_enter(&node->n_mutex); 630 if (node && (node->flags & NODE_FLAGS_SET_SIZE)) 631 size = node->n_size; 632 else 633 size = attr->sa_vattr.va_size; 634 mutex_exit(&node->n_mutex); 635 return (size); 636 } 637 638 static int 639 timeval_cmp(timestruc_t *a, timestruc_t *b) 640 { 641 if (a->tv_sec < b->tv_sec) 642 return (-1); 643 if (a->tv_sec > b->tv_sec) 644 return (1); 645 /* Seconds are equal compare tv_nsec */ 646 if (a->tv_nsec < b->tv_nsec) 647 return (-1); 648 return (a->tv_nsec > b->tv_nsec); 649 } 650 651 /* 652 * smb_node_set_time 653 * 654 * This function will update the time stored in the node and 655 * set the appropriate flags. If there is nothing to update, 656 * the function will return without any updates. The update 657 * is only in the node level and the attribute in the file system 658 * will be updated when client close the file. 659 */ 660 void 661 smb_node_set_time( 662 smb_node_t *node, 663 timestruc_t *crtime, 664 timestruc_t *mtime, 665 timestruc_t *atime, 666 timestruc_t *ctime, 667 uint_t what) 668 { 669 if (what == 0) 670 return; 671 672 if ((what & SMB_AT_CRTIME && crtime == 0) || 673 (what & SMB_AT_MTIME && mtime == 0) || 674 (what & SMB_AT_ATIME && atime == 0) || 675 (what & SMB_AT_CTIME && ctime == 0)) 676 return; 677 678 mutex_enter(&node->n_mutex); 679 680 if ((what & SMB_AT_CRTIME) && 681 timeval_cmp((timestruc_t *)&node->attr.sa_crtime, 682 crtime) != 0) { 683 node->what |= SMB_AT_CRTIME; 684 node->attr.sa_crtime = *((timestruc_t *)crtime); 685 } 686 687 if ((what & SMB_AT_MTIME) && 688 timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_mtime, 689 mtime) != 0) { 690 node->what |= SMB_AT_MTIME; 691 node->attr.sa_vattr.va_mtime = *((timestruc_t *)mtime); 692 } 693 694 if ((what & SMB_AT_ATIME) && 695 timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_atime, 696 atime) != 0) { 697 node->what |= SMB_AT_ATIME; 698 node->attr.sa_vattr.va_atime = *((timestruc_t *)atime); 699 } 700 701 /* 702 * The ctime handling is trickier. It has three scenarios. 703 * 1. Only ctime need to be set and it is the same as the ctime 704 * stored in the node. (update not necessary) 705 * 2. The ctime is the same as the ctime stored in the node but 706 * is not the only time need to be set. (update required) 707 * 3. The ctime need to be set and is not the same as the ctime 708 * stored in the node. (update required) 709 * Unlike other time setting, the ctime needs to be set even when 710 * it is the same as the ctime in the node if there are other time 711 * needs to be set (#2). This will ensure the ctime not being 712 * updated when other times are being updated in the file system. 713 * 714 * Retained file rules: 715 * 716 * 1. Don't add SMB_AT_CTIME to node->what by default because the 717 * request will be rejected by filesystem 718 * 2. 'what' SMB_AT_CTIME shouldn't be set for retained files, i.e. 719 * any request for changing ctime on these files should have 720 * been already rejected 721 */ 722 node->what |= SMB_AT_CTIME; 723 if (what & SMB_AT_CTIME) { 724 if ((what == SMB_AT_CTIME) && 725 timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_ctime, 726 ctime) == 0) { 727 node->what &= ~SMB_AT_CTIME; 728 } else { 729 gethrestime(&node->attr.sa_vattr.va_ctime); 730 } 731 } else { 732 gethrestime(&node->attr.sa_vattr.va_ctime); 733 } 734 mutex_exit(&node->n_mutex); 735 } 736 737 738 timestruc_t * 739 smb_node_get_crtime(smb_node_t *node) 740 { 741 return ((timestruc_t *)&node->attr.sa_crtime); 742 } 743 744 timestruc_t * 745 smb_node_get_atime(smb_node_t *node) 746 { 747 return ((timestruc_t *)&node->attr.sa_vattr.va_atime); 748 } 749 750 timestruc_t * 751 smb_node_get_ctime(smb_node_t *node) 752 { 753 return ((timestruc_t *)&node->attr.sa_vattr.va_ctime); 754 } 755 756 timestruc_t * 757 smb_node_get_mtime(smb_node_t *node) 758 { 759 return ((timestruc_t *)&node->attr.sa_vattr.va_mtime); 760 } 761 762 /* 763 * smb_node_set_dosattr 764 * 765 * Parse the specified DOS attributes and, if they have been modified, 766 * update the node cache. This call should be followed by a 767 * smb_sync_fsattr() call to write the attribute changes to filesystem. 768 */ 769 void 770 smb_node_set_dosattr(smb_node_t *node, uint32_t dosattr) 771 { 772 uint32_t mode = dosattr & (FILE_ATTRIBUTE_ARCHIVE | 773 FILE_ATTRIBUTE_READONLY | 774 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); 775 776 mutex_enter(&node->n_mutex); 777 if (node->attr.sa_dosattr != mode) { 778 node->attr.sa_dosattr = mode; 779 node->what |= SMB_AT_DOSATTR; 780 } 781 mutex_exit(&node->n_mutex); 782 } 783 784 /* 785 * smb_node_get_dosattr() 786 * 787 * This function is used to provide clients with information as to whether 788 * the readonly bit is set. Hence both the node attribute cache (which 789 * reflects the on-disk attributes) and node->readonly_creator (which 790 * reflects whether a readonly set is pending from a readonly create) are 791 * checked. In the latter case, the readonly attribute should be visible to 792 * all clients even though the readonly creator fid is immune to the readonly 793 * bit until close. 794 */ 795 796 uint32_t 797 smb_node_get_dosattr(smb_node_t *node) 798 { 799 uint32_t dosattr = node->attr.sa_dosattr; 800 801 if (node->readonly_creator) 802 dosattr |= FILE_ATTRIBUTE_READONLY; 803 804 if (!dosattr) 805 dosattr = FILE_ATTRIBUTE_NORMAL; 806 807 return (dosattr); 808 } 809 810 /* 811 * When DeleteOnClose is set on an smb_node, the common open code will 812 * reject subsequent open requests for the file. Observation of Windows 813 * 2000 indicates that subsequent opens should be allowed (assuming 814 * there would be no sharing violation) until the file is closed using 815 * the fid on which the DeleteOnClose was requested. 816 * 817 * If there are multiple opens with delete-on-close create options, 818 * whichever the first file handle is closed will trigger the node to be 819 * marked as delete-on-close. The credentials of that ofile will be used 820 * as the delete-on-close credentials of the node. 821 */ 822 int 823 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags) 824 { 825 int rc = -1; 826 827 mutex_enter(&node->n_mutex); 828 if (!(node->attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) && 829 !(node->flags & NODE_FLAGS_DELETE_ON_CLOSE)) { 830 crhold(cr); 831 node->delete_on_close_cred = cr; 832 node->n_delete_on_close_flags = flags; 833 node->flags |= NODE_FLAGS_DELETE_ON_CLOSE; 834 rc = 0; 835 } 836 mutex_exit(&node->n_mutex); 837 return (rc); 838 } 839 840 void 841 smb_node_reset_delete_on_close(smb_node_t *node) 842 { 843 mutex_enter(&node->n_mutex); 844 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 845 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 846 crfree(node->delete_on_close_cred); 847 node->delete_on_close_cred = NULL; 848 node->n_delete_on_close_flags = 0; 849 } 850 mutex_exit(&node->n_mutex); 851 } 852 853 /* 854 * smb_node_open_check 855 * 856 * check file sharing rules for current open request 857 * against all existing opens for a file. 858 * 859 * Returns NT_STATUS_SHARING_VIOLATION if there is any 860 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 861 */ 862 uint32_t 863 smb_node_open_check( 864 smb_node_t *node, 865 cred_t *cr, 866 uint32_t desired_access, 867 uint32_t share_access) 868 { 869 smb_ofile_t *of; 870 uint32_t status; 871 872 SMB_NODE_VALID(node); 873 874 smb_llist_enter(&node->n_ofile_list, RW_READER); 875 of = smb_llist_head(&node->n_ofile_list); 876 while (of) { 877 status = smb_ofile_open_check(of, cr, desired_access, 878 share_access); 879 880 switch (status) { 881 case NT_STATUS_INVALID_HANDLE: 882 case NT_STATUS_SUCCESS: 883 of = smb_llist_next(&node->n_ofile_list, of); 884 break; 885 default: 886 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 887 smb_llist_exit(&node->n_ofile_list); 888 return (status); 889 } 890 } 891 892 smb_llist_exit(&node->n_ofile_list); 893 return (NT_STATUS_SUCCESS); 894 } 895 896 uint32_t 897 smb_node_rename_check(smb_node_t *node) 898 { 899 smb_ofile_t *of; 900 uint32_t status; 901 902 SMB_NODE_VALID(node); 903 904 /* 905 * Intra-CIFS check 906 */ 907 smb_llist_enter(&node->n_ofile_list, RW_READER); 908 of = smb_llist_head(&node->n_ofile_list); 909 while (of) { 910 status = smb_ofile_rename_check(of); 911 912 switch (status) { 913 case NT_STATUS_INVALID_HANDLE: 914 case NT_STATUS_SUCCESS: 915 of = smb_llist_next(&node->n_ofile_list, of); 916 break; 917 default: 918 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 919 smb_llist_exit(&node->n_ofile_list); 920 return (status); 921 } 922 } 923 smb_llist_exit(&node->n_ofile_list); 924 925 /* 926 * system-wide share check 927 */ 928 if (nbl_share_conflict(node->vp, NBL_RENAME, NULL)) 929 return (NT_STATUS_SHARING_VIOLATION); 930 else 931 return (NT_STATUS_SUCCESS); 932 } 933 934 uint32_t 935 smb_node_delete_check(smb_node_t *node) 936 { 937 smb_ofile_t *of; 938 uint32_t status; 939 940 SMB_NODE_VALID(node); 941 942 if (node->attr.sa_vattr.va_type == VDIR) 943 return (NT_STATUS_SUCCESS); 944 945 /* 946 * intra-CIFS check 947 */ 948 smb_llist_enter(&node->n_ofile_list, RW_READER); 949 of = smb_llist_head(&node->n_ofile_list); 950 while (of) { 951 status = smb_ofile_delete_check(of); 952 953 switch (status) { 954 case NT_STATUS_INVALID_HANDLE: 955 case NT_STATUS_SUCCESS: 956 of = smb_llist_next(&node->n_ofile_list, of); 957 break; 958 default: 959 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 960 smb_llist_exit(&node->n_ofile_list); 961 return (status); 962 } 963 } 964 smb_llist_exit(&node->n_ofile_list); 965 966 /* 967 * system-wide share check 968 */ 969 if (nbl_share_conflict(node->vp, NBL_REMOVE, NULL)) 970 return (NT_STATUS_SHARING_VIOLATION); 971 else 972 return (NT_STATUS_SUCCESS); 973 } 974 975 /* 976 * smb_node_start_crit() 977 * 978 * Enter critical region for share reservations. 979 * See comments above smb_fsop_shrlock(). 980 */ 981 982 void 983 smb_node_start_crit(smb_node_t *node, krw_t mode) 984 { 985 rw_enter(&node->n_lock, mode); 986 nbl_start_crit(node->vp, mode); 987 } 988 989 /* 990 * smb_node_end_crit() 991 * 992 * Exit critical region for share reservations. 993 */ 994 995 void 996 smb_node_end_crit(smb_node_t *node) 997 { 998 nbl_end_crit(node->vp); 999 rw_exit(&node->n_lock); 1000 } 1001 1002 int 1003 smb_node_in_crit(smb_node_t *node) 1004 { 1005 return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock)); 1006 } 1007 1008 void 1009 smb_node_rdlock(smb_node_t *node) 1010 { 1011 rw_enter(&node->n_lock, RW_READER); 1012 } 1013 1014 void 1015 smb_node_wrlock(smb_node_t *node) 1016 { 1017 rw_enter(&node->n_lock, RW_WRITER); 1018 } 1019 1020 void 1021 smb_node_unlock(smb_node_t *node) 1022 { 1023 rw_exit(&node->n_lock); 1024 } 1025 1026 uint32_t 1027 smb_node_get_ofile_count(smb_node_t *node) 1028 { 1029 uint32_t cntr; 1030 1031 SMB_NODE_VALID(node); 1032 1033 smb_llist_enter(&node->n_ofile_list, RW_READER); 1034 cntr = smb_llist_get_count(&node->n_ofile_list); 1035 smb_llist_exit(&node->n_ofile_list); 1036 return (cntr); 1037 } 1038 1039 void 1040 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of) 1041 { 1042 SMB_NODE_VALID(node); 1043 1044 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1045 smb_llist_insert_tail(&node->n_ofile_list, of); 1046 smb_llist_exit(&node->n_ofile_list); 1047 } 1048 1049 void 1050 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of) 1051 { 1052 SMB_NODE_VALID(node); 1053 1054 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1055 smb_llist_remove(&node->n_ofile_list, of); 1056 smb_llist_exit(&node->n_ofile_list); 1057 } 1058 1059 void 1060 smb_node_inc_open_ofiles(smb_node_t *node) 1061 { 1062 SMB_NODE_VALID(node); 1063 1064 mutex_enter(&node->n_mutex); 1065 node->n_open_count++; 1066 mutex_exit(&node->n_mutex); 1067 } 1068 1069 void 1070 smb_node_dec_open_ofiles(smb_node_t *node) 1071 { 1072 SMB_NODE_VALID(node); 1073 1074 mutex_enter(&node->n_mutex); 1075 node->n_open_count--; 1076 mutex_exit(&node->n_mutex); 1077 } 1078 1079 uint32_t 1080 smb_node_get_open_ofiles(smb_node_t *node) 1081 { 1082 uint32_t cnt; 1083 1084 SMB_NODE_VALID(node); 1085 1086 mutex_enter(&node->n_mutex); 1087 cnt = node->n_open_count; 1088 mutex_exit(&node->n_mutex); 1089 return (cnt); 1090 } 1091 1092 /* 1093 * smb_node_alloc 1094 */ 1095 static smb_node_t * 1096 smb_node_alloc( 1097 char *od_name, 1098 vnode_t *vp, 1099 smb_attr_t *attr, 1100 smb_llist_t *bucket, 1101 uint32_t hashkey) 1102 { 1103 smb_node_t *node; 1104 1105 node = kmem_cache_alloc(smb_node_cache, KM_SLEEP); 1106 1107 if (node->n_audit_buf != NULL) 1108 node->n_audit_buf->anb_index = 0; 1109 1110 node->attr = *attr; 1111 node->flags = NODE_FLAGS_ATTR_VALID; 1112 node->n_size = node->attr.sa_vattr.va_size; 1113 VN_HOLD(vp); 1114 node->vp = vp; 1115 node->n_refcnt = 1; 1116 node->n_hash_bucket = bucket; 1117 node->n_hashkey = hashkey; 1118 node->n_orig_uid = 0; 1119 node->readonly_creator = NULL; 1120 node->waiting_event = 0; 1121 node->what = 0; 1122 node->n_open_count = 0; 1123 node->dir_snode = NULL; 1124 node->unnamed_stream_node = NULL; 1125 node->delete_on_close_cred = NULL; 1126 node->n_delete_on_close_flags = 0; 1127 1128 (void) strlcpy(node->od_name, od_name, sizeof (node->od_name)); 1129 if (strcmp(od_name, XATTR_DIR) == 0) 1130 node->flags |= NODE_XATTR_DIR; 1131 1132 node->n_state = SMB_NODE_STATE_AVAILABLE; 1133 node->n_magic = SMB_NODE_MAGIC; 1134 return (node); 1135 } 1136 1137 /* 1138 * smb_node_free 1139 */ 1140 static void 1141 smb_node_free(smb_node_t *node) 1142 { 1143 SMB_NODE_VALID(node); 1144 1145 node->n_magic = 0; 1146 VERIFY(!list_link_active(&node->n_lnd)); 1147 VERIFY(node->n_lock_list.ll_count == 0); 1148 VERIFY(node->n_ofile_list.ll_count == 0); 1149 VERIFY(node->n_oplock.ol_xthread == NULL); 1150 VERIFY(mutex_owner(&node->n_mutex) == NULL); 1151 VERIFY(!RW_LOCK_HELD(&node->n_lock)); 1152 VN_RELE(node->vp); 1153 kmem_cache_free(smb_node_cache, node); 1154 } 1155 1156 /* 1157 * smb_node_constructor 1158 */ 1159 static int 1160 smb_node_constructor(void *buf, void *un, int kmflags) 1161 { 1162 _NOTE(ARGUNUSED(kmflags, un)) 1163 1164 smb_node_t *node = (smb_node_t *)buf; 1165 1166 bzero(node, sizeof (smb_node_t)); 1167 1168 smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t), 1169 offsetof(smb_ofile_t, f_nnd)); 1170 smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t), 1171 offsetof(smb_lock_t, l_lnd)); 1172 cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL); 1173 rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL); 1174 mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL); 1175 smb_node_create_audit_buf(node, kmflags); 1176 return (0); 1177 } 1178 1179 /* 1180 * smb_node_destructor 1181 */ 1182 static void 1183 smb_node_destructor(void *buf, void *un) 1184 { 1185 _NOTE(ARGUNUSED(un)) 1186 1187 smb_node_t *node = (smb_node_t *)buf; 1188 1189 smb_node_destroy_audit_buf(node); 1190 mutex_destroy(&node->n_mutex); 1191 rw_destroy(&node->n_lock); 1192 cv_destroy(&node->n_oplock.ol_cv); 1193 smb_llist_destructor(&node->n_lock_list); 1194 smb_llist_destructor(&node->n_ofile_list); 1195 } 1196 1197 /* 1198 * smb_node_create_audit_buf 1199 */ 1200 static void 1201 smb_node_create_audit_buf(smb_node_t *node, int kmflags) 1202 { 1203 smb_audit_buf_node_t *abn; 1204 1205 if (smb_audit_flags & SMB_AUDIT_NODE) { 1206 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags); 1207 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1; 1208 node->n_audit_buf = abn; 1209 } 1210 } 1211 1212 /* 1213 * smb_node_destroy_audit_buf 1214 */ 1215 static void 1216 smb_node_destroy_audit_buf(smb_node_t *node) 1217 { 1218 if (node->n_audit_buf != NULL) { 1219 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t)); 1220 node->n_audit_buf = NULL; 1221 } 1222 } 1223 1224 /* 1225 * smb_node_audit 1226 * 1227 * This function saves the calling stack in the audit buffer of the node passed 1228 * in. 1229 */ 1230 static void 1231 smb_node_audit(smb_node_t *node) 1232 { 1233 smb_audit_buf_node_t *abn; 1234 smb_audit_record_node_t *anr; 1235 1236 if (node->n_audit_buf) { 1237 abn = node->n_audit_buf; 1238 anr = abn->anb_records; 1239 anr += abn->anb_index; 1240 abn->anb_index++; 1241 abn->anb_index &= abn->anb_max_index; 1242 anr->anr_refcnt = node->n_refcnt; 1243 anr->anr_depth = getpcstack(anr->anr_stack, 1244 SMB_AUDIT_STACK_DEPTH); 1245 } 1246 } 1247 1248 static smb_llist_t * 1249 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey) 1250 { 1251 uint32_t hashkey; 1252 1253 hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid; 1254 hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8); 1255 *phashkey = hashkey; 1256 return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]); 1257 } 1258