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 531 d_snode = node->dir_snode; 532 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 533 534 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 535 ASSERT(node->od_name != NULL); 536 if (node->attr.sa_vattr.va_type == VDIR) 537 rc = smb_fsop_rmdir(0, node->delete_on_close_cred, 538 d_snode, node->od_name, 1); 539 else 540 rc = smb_fsop_remove(0, node->delete_on_close_cred, 541 d_snode, node->od_name, 1); 542 smb_cred_rele(node->delete_on_close_cred); 543 } 544 if (rc != 0) 545 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n", 546 node->od_name, rc); 547 DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node); 548 } 549 550 /* 551 * smb_node_rename() 552 * 553 */ 554 void 555 smb_node_rename( 556 smb_node_t *from_dnode, 557 smb_node_t *ret_node, 558 smb_node_t *to_dnode, 559 char *to_name) 560 { 561 SMB_NODE_VALID(from_dnode); 562 SMB_NODE_VALID(to_dnode); 563 SMB_NODE_VALID(ret_node); 564 565 smb_node_ref(to_dnode); 566 mutex_enter(&ret_node->n_mutex); 567 switch (ret_node->n_state) { 568 case SMB_NODE_STATE_AVAILABLE: 569 case SMB_NODE_STATE_OPLOCK_GRANTED: 570 case SMB_NODE_STATE_OPLOCK_BREAKING: 571 ret_node->dir_snode = to_dnode; 572 mutex_exit(&ret_node->n_mutex); 573 ASSERT(to_dnode->dir_snode != ret_node); 574 ASSERT((to_dnode->vp->v_xattrdir) || 575 (to_dnode->vp->v_type == VDIR)); 576 smb_node_release(from_dnode); 577 (void) strcpy(ret_node->od_name, to_name); 578 /* 579 * XXX Need to update attributes? 580 */ 581 break; 582 default: 583 SMB_PANIC(); 584 } 585 } 586 587 int 588 smb_node_root_init(vnode_t *vp, smb_server_t *sv, smb_node_t **root) 589 { 590 smb_attr_t va; 591 int error; 592 uint32_t hashkey; 593 smb_llist_t *node_hdr; 594 smb_node_t *node; 595 596 va.sa_mask = SMB_AT_ALL; 597 error = smb_vop_getattr(vp, NULL, &va, 0, kcred); 598 if (error) { 599 VN_RELE(vp); 600 return (error); 601 } 602 603 node_hdr = smb_node_get_hash(&vp->v_vfsp->vfs_fsid, &va, &hashkey); 604 605 node = smb_node_alloc(ROOTVOL, vp, &va, node_hdr, hashkey); 606 607 sv->si_root_smb_node = node; 608 smb_node_audit(node); 609 smb_llist_enter(node_hdr, RW_WRITER); 610 smb_llist_insert_head(node_hdr, node); 611 smb_llist_exit(node_hdr); 612 *root = node; 613 return (0); 614 } 615 616 /* 617 * smb_node_get_size 618 */ 619 u_offset_t 620 smb_node_get_size(smb_node_t *node, smb_attr_t *attr) 621 { 622 u_offset_t size; 623 624 if (attr->sa_vattr.va_type == VDIR) 625 return (0); 626 627 mutex_enter(&node->n_mutex); 628 if (node && (node->flags & NODE_FLAGS_SET_SIZE)) 629 size = node->n_size; 630 else 631 size = attr->sa_vattr.va_size; 632 mutex_exit(&node->n_mutex); 633 return (size); 634 } 635 636 static int 637 timeval_cmp(timestruc_t *a, timestruc_t *b) 638 { 639 if (a->tv_sec < b->tv_sec) 640 return (-1); 641 if (a->tv_sec > b->tv_sec) 642 return (1); 643 /* Seconds are equal compare tv_nsec */ 644 if (a->tv_nsec < b->tv_nsec) 645 return (-1); 646 return (a->tv_nsec > b->tv_nsec); 647 } 648 649 /* 650 * smb_node_set_time 651 * 652 * This function will update the time stored in the node and 653 * set the appropriate flags. If there is nothing to update, 654 * the function will return without any updates. The update 655 * is only in the node level and the attribute in the file system 656 * will be updated when client close the file. 657 */ 658 void 659 smb_node_set_time( 660 smb_node_t *node, 661 timestruc_t *crtime, 662 timestruc_t *mtime, 663 timestruc_t *atime, 664 timestruc_t *ctime, 665 uint_t what) 666 { 667 if (what == 0) 668 return; 669 670 if ((what & SMB_AT_CRTIME && crtime == 0) || 671 (what & SMB_AT_MTIME && mtime == 0) || 672 (what & SMB_AT_ATIME && atime == 0) || 673 (what & SMB_AT_CTIME && ctime == 0)) 674 return; 675 676 mutex_enter(&node->n_mutex); 677 678 if ((what & SMB_AT_CRTIME) && 679 timeval_cmp((timestruc_t *)&node->attr.sa_crtime, 680 crtime) != 0) { 681 node->what |= SMB_AT_CRTIME; 682 node->attr.sa_crtime = *((timestruc_t *)crtime); 683 } 684 685 if ((what & SMB_AT_MTIME) && 686 timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_mtime, 687 mtime) != 0) { 688 node->what |= SMB_AT_MTIME; 689 node->attr.sa_vattr.va_mtime = *((timestruc_t *)mtime); 690 } 691 692 if ((what & SMB_AT_ATIME) && 693 timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_atime, 694 atime) != 0) { 695 node->what |= SMB_AT_ATIME; 696 node->attr.sa_vattr.va_atime = *((timestruc_t *)atime); 697 } 698 699 /* 700 * The ctime handling is trickier. It has three scenarios. 701 * 1. Only ctime need to be set and it is the same as the ctime 702 * stored in the node. (update not necessary) 703 * 2. The ctime is the same as the ctime stored in the node but 704 * is not the only time need to be set. (update required) 705 * 3. The ctime need to be set and is not the same as the ctime 706 * stored in the node. (update required) 707 * Unlike other time setting, the ctime needs to be set even when 708 * it is the same as the ctime in the node if there are other time 709 * needs to be set (#2). This will ensure the ctime not being 710 * updated when other times are being updated in the file system. 711 * 712 * Retained file rules: 713 * 714 * 1. Don't add SMB_AT_CTIME to node->what by default because the 715 * request will be rejected by filesystem 716 * 2. 'what' SMB_AT_CTIME shouldn't be set for retained files, i.e. 717 * any request for changing ctime on these files should have 718 * been already rejected 719 */ 720 node->what |= SMB_AT_CTIME; 721 if (what & SMB_AT_CTIME) { 722 if ((what == SMB_AT_CTIME) && 723 timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_ctime, 724 ctime) == 0) { 725 node->what &= ~SMB_AT_CTIME; 726 } else { 727 gethrestime(&node->attr.sa_vattr.va_ctime); 728 } 729 } else { 730 gethrestime(&node->attr.sa_vattr.va_ctime); 731 } 732 mutex_exit(&node->n_mutex); 733 } 734 735 736 timestruc_t * 737 smb_node_get_crtime(smb_node_t *node) 738 { 739 return ((timestruc_t *)&node->attr.sa_crtime); 740 } 741 742 timestruc_t * 743 smb_node_get_atime(smb_node_t *node) 744 { 745 return ((timestruc_t *)&node->attr.sa_vattr.va_atime); 746 } 747 748 timestruc_t * 749 smb_node_get_ctime(smb_node_t *node) 750 { 751 return ((timestruc_t *)&node->attr.sa_vattr.va_ctime); 752 } 753 754 timestruc_t * 755 smb_node_get_mtime(smb_node_t *node) 756 { 757 return ((timestruc_t *)&node->attr.sa_vattr.va_mtime); 758 } 759 760 /* 761 * smb_node_set_dosattr 762 * 763 * Parse the specified DOS attributes and, if they have been modified, 764 * update the node cache. This call should be followed by a 765 * smb_sync_fsattr() call to write the attribute changes to filesystem. 766 */ 767 void 768 smb_node_set_dosattr(smb_node_t *node, uint32_t dosattr) 769 { 770 uint32_t mode = dosattr & (FILE_ATTRIBUTE_ARCHIVE | 771 FILE_ATTRIBUTE_READONLY | 772 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); 773 774 mutex_enter(&node->n_mutex); 775 if (node->attr.sa_dosattr != mode) { 776 node->attr.sa_dosattr = mode; 777 node->what |= SMB_AT_DOSATTR; 778 } 779 mutex_exit(&node->n_mutex); 780 } 781 782 /* 783 * smb_node_get_dosattr() 784 * 785 * This function is used to provide clients with information as to whether 786 * the readonly bit is set. Hence both the node attribute cache (which 787 * reflects the on-disk attributes) and node->readonly_creator (which 788 * reflects whether a readonly set is pending from a readonly create) are 789 * checked. In the latter case, the readonly attribute should be visible to 790 * all clients even though the readonly creator fid is immune to the readonly 791 * bit until close. 792 */ 793 794 uint32_t 795 smb_node_get_dosattr(smb_node_t *node) 796 { 797 uint32_t dosattr = node->attr.sa_dosattr; 798 799 if (node->readonly_creator) 800 dosattr |= FILE_ATTRIBUTE_READONLY; 801 802 if (!dosattr) 803 dosattr = FILE_ATTRIBUTE_NORMAL; 804 805 return (dosattr); 806 } 807 808 int 809 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr) 810 { 811 int rc = -1; 812 813 mutex_enter(&node->n_mutex); 814 if (!(node->attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) && 815 !(node->flags & NODE_FLAGS_DELETE_ON_CLOSE)) { 816 crhold(cr); 817 node->delete_on_close_cred = cr; 818 node->flags |= NODE_FLAGS_DELETE_ON_CLOSE; 819 rc = 0; 820 } 821 mutex_exit(&node->n_mutex); 822 return (rc); 823 } 824 825 void 826 smb_node_reset_delete_on_close(smb_node_t *node) 827 { 828 mutex_enter(&node->n_mutex); 829 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 830 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 831 crfree(node->delete_on_close_cred); 832 node->delete_on_close_cred = NULL; 833 } 834 mutex_exit(&node->n_mutex); 835 } 836 837 /* 838 * smb_node_open_check 839 * 840 * check file sharing rules for current open request 841 * against all existing opens for a file. 842 * 843 * Returns NT_STATUS_SHARING_VIOLATION if there is any 844 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 845 */ 846 uint32_t 847 smb_node_open_check( 848 smb_node_t *node, 849 cred_t *cr, 850 uint32_t desired_access, 851 uint32_t share_access) 852 { 853 smb_ofile_t *of; 854 uint32_t status; 855 856 SMB_NODE_VALID(node); 857 858 smb_llist_enter(&node->n_ofile_list, RW_READER); 859 of = smb_llist_head(&node->n_ofile_list); 860 while (of) { 861 status = smb_ofile_open_check(of, cr, desired_access, 862 share_access); 863 864 switch (status) { 865 case NT_STATUS_INVALID_HANDLE: 866 case NT_STATUS_SUCCESS: 867 of = smb_llist_next(&node->n_ofile_list, of); 868 break; 869 default: 870 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 871 smb_llist_exit(&node->n_ofile_list); 872 return (status); 873 } 874 } 875 876 smb_llist_exit(&node->n_ofile_list); 877 return (NT_STATUS_SUCCESS); 878 } 879 880 uint32_t 881 smb_node_rename_check(smb_node_t *node) 882 { 883 smb_ofile_t *of; 884 uint32_t status; 885 886 SMB_NODE_VALID(node); 887 888 /* 889 * Intra-CIFS check 890 */ 891 smb_llist_enter(&node->n_ofile_list, RW_READER); 892 of = smb_llist_head(&node->n_ofile_list); 893 while (of) { 894 status = smb_ofile_rename_check(of); 895 896 switch (status) { 897 case NT_STATUS_INVALID_HANDLE: 898 case NT_STATUS_SUCCESS: 899 of = smb_llist_next(&node->n_ofile_list, of); 900 break; 901 default: 902 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 903 smb_llist_exit(&node->n_ofile_list); 904 return (status); 905 } 906 } 907 smb_llist_exit(&node->n_ofile_list); 908 909 /* 910 * system-wide share check 911 */ 912 if (nbl_share_conflict(node->vp, NBL_RENAME, NULL)) 913 return (NT_STATUS_SHARING_VIOLATION); 914 else 915 return (NT_STATUS_SUCCESS); 916 } 917 918 uint32_t 919 smb_node_delete_check(smb_node_t *node) 920 { 921 smb_ofile_t *of; 922 uint32_t status; 923 924 SMB_NODE_VALID(node); 925 926 if (node->attr.sa_vattr.va_type == VDIR) 927 return (NT_STATUS_SUCCESS); 928 929 /* 930 * intra-CIFS check 931 */ 932 smb_llist_enter(&node->n_ofile_list, RW_READER); 933 of = smb_llist_head(&node->n_ofile_list); 934 while (of) { 935 status = smb_ofile_delete_check(of); 936 937 switch (status) { 938 case NT_STATUS_INVALID_HANDLE: 939 case NT_STATUS_SUCCESS: 940 of = smb_llist_next(&node->n_ofile_list, of); 941 break; 942 default: 943 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 944 smb_llist_exit(&node->n_ofile_list); 945 return (status); 946 } 947 } 948 smb_llist_exit(&node->n_ofile_list); 949 950 /* 951 * system-wide share check 952 */ 953 if (nbl_share_conflict(node->vp, NBL_REMOVE, NULL)) 954 return (NT_STATUS_SHARING_VIOLATION); 955 else 956 return (NT_STATUS_SUCCESS); 957 } 958 959 /* 960 * smb_node_start_crit() 961 * 962 * Enter critical region for share reservations. 963 * See comments above smb_fsop_shrlock(). 964 */ 965 966 void 967 smb_node_start_crit(smb_node_t *node, krw_t mode) 968 { 969 rw_enter(&node->n_lock, mode); 970 nbl_start_crit(node->vp, mode); 971 } 972 973 /* 974 * smb_node_end_crit() 975 * 976 * Exit critical region for share reservations. 977 */ 978 979 void 980 smb_node_end_crit(smb_node_t *node) 981 { 982 nbl_end_crit(node->vp); 983 rw_exit(&node->n_lock); 984 } 985 986 int 987 smb_node_in_crit(smb_node_t *node) 988 { 989 return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock)); 990 } 991 992 void 993 smb_node_rdlock(smb_node_t *node) 994 { 995 rw_enter(&node->n_lock, RW_READER); 996 } 997 998 void 999 smb_node_wrlock(smb_node_t *node) 1000 { 1001 rw_enter(&node->n_lock, RW_WRITER); 1002 } 1003 1004 void 1005 smb_node_unlock(smb_node_t *node) 1006 { 1007 rw_exit(&node->n_lock); 1008 } 1009 1010 uint32_t 1011 smb_node_get_ofile_count(smb_node_t *node) 1012 { 1013 uint32_t cntr; 1014 1015 SMB_NODE_VALID(node); 1016 1017 smb_llist_enter(&node->n_ofile_list, RW_READER); 1018 cntr = smb_llist_get_count(&node->n_ofile_list); 1019 smb_llist_exit(&node->n_ofile_list); 1020 return (cntr); 1021 } 1022 1023 void 1024 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of) 1025 { 1026 SMB_NODE_VALID(node); 1027 1028 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1029 smb_llist_insert_tail(&node->n_ofile_list, of); 1030 smb_llist_exit(&node->n_ofile_list); 1031 } 1032 1033 void 1034 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of) 1035 { 1036 SMB_NODE_VALID(node); 1037 1038 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1039 smb_llist_remove(&node->n_ofile_list, of); 1040 smb_llist_exit(&node->n_ofile_list); 1041 } 1042 1043 void 1044 smb_node_inc_open_ofiles(smb_node_t *node) 1045 { 1046 SMB_NODE_VALID(node); 1047 1048 mutex_enter(&node->n_mutex); 1049 node->n_open_count++; 1050 mutex_exit(&node->n_mutex); 1051 } 1052 1053 void 1054 smb_node_dec_open_ofiles(smb_node_t *node) 1055 { 1056 SMB_NODE_VALID(node); 1057 1058 mutex_enter(&node->n_mutex); 1059 node->n_open_count--; 1060 mutex_exit(&node->n_mutex); 1061 } 1062 1063 uint32_t 1064 smb_node_get_open_ofiles(smb_node_t *node) 1065 { 1066 uint32_t cnt; 1067 1068 SMB_NODE_VALID(node); 1069 1070 mutex_enter(&node->n_mutex); 1071 cnt = node->n_open_count; 1072 mutex_exit(&node->n_mutex); 1073 return (cnt); 1074 } 1075 1076 /* 1077 * smb_node_alloc 1078 */ 1079 static smb_node_t * 1080 smb_node_alloc( 1081 char *od_name, 1082 vnode_t *vp, 1083 smb_attr_t *attr, 1084 smb_llist_t *bucket, 1085 uint32_t hashkey) 1086 { 1087 smb_node_t *node; 1088 1089 node = kmem_cache_alloc(smb_node_cache, KM_SLEEP); 1090 1091 if (node->n_audit_buf != NULL) 1092 node->n_audit_buf->anb_index = 0; 1093 1094 node->attr = *attr; 1095 node->flags = NODE_FLAGS_ATTR_VALID; 1096 node->n_size = node->attr.sa_vattr.va_size; 1097 VN_HOLD(vp); 1098 node->vp = vp; 1099 node->n_refcnt = 1; 1100 node->n_hash_bucket = bucket; 1101 node->n_hashkey = hashkey; 1102 node->n_orig_uid = 0; 1103 node->readonly_creator = NULL; 1104 node->waiting_event = 0; 1105 node->what = 0; 1106 node->n_open_count = 0; 1107 node->dir_snode = NULL; 1108 node->unnamed_stream_node = NULL; 1109 node->delete_on_close_cred = NULL; 1110 1111 (void) strlcpy(node->od_name, od_name, sizeof (node->od_name)); 1112 if (strcmp(od_name, XATTR_DIR) == 0) 1113 node->flags |= NODE_XATTR_DIR; 1114 1115 node->n_state = SMB_NODE_STATE_AVAILABLE; 1116 node->n_magic = SMB_NODE_MAGIC; 1117 return (node); 1118 } 1119 1120 /* 1121 * smb_node_free 1122 */ 1123 static void 1124 smb_node_free(smb_node_t *node) 1125 { 1126 SMB_NODE_VALID(node); 1127 1128 node->n_magic = 0; 1129 VERIFY(!list_link_active(&node->n_lnd)); 1130 VERIFY(node->n_lock_list.ll_count == 0); 1131 VERIFY(node->n_ofile_list.ll_count == 0); 1132 VERIFY(node->n_oplock.ol_xthread == NULL); 1133 VERIFY(mutex_owner(&node->n_mutex) == NULL); 1134 VERIFY(!RW_LOCK_HELD(&node->n_lock)); 1135 VN_RELE(node->vp); 1136 kmem_cache_free(smb_node_cache, node); 1137 } 1138 1139 /* 1140 * smb_node_constructor 1141 */ 1142 static int 1143 smb_node_constructor(void *buf, void *un, int kmflags) 1144 { 1145 _NOTE(ARGUNUSED(kmflags, un)) 1146 1147 smb_node_t *node = (smb_node_t *)buf; 1148 1149 bzero(node, sizeof (smb_node_t)); 1150 1151 smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t), 1152 offsetof(smb_ofile_t, f_nnd)); 1153 smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t), 1154 offsetof(smb_lock_t, l_lnd)); 1155 cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL); 1156 rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL); 1157 mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL); 1158 smb_node_create_audit_buf(node, kmflags); 1159 return (0); 1160 } 1161 1162 /* 1163 * smb_node_destructor 1164 */ 1165 static void 1166 smb_node_destructor(void *buf, void *un) 1167 { 1168 _NOTE(ARGUNUSED(un)) 1169 1170 smb_node_t *node = (smb_node_t *)buf; 1171 1172 smb_node_destroy_audit_buf(node); 1173 mutex_destroy(&node->n_mutex); 1174 rw_destroy(&node->n_lock); 1175 cv_destroy(&node->n_oplock.ol_cv); 1176 smb_llist_destructor(&node->n_lock_list); 1177 smb_llist_destructor(&node->n_ofile_list); 1178 } 1179 1180 /* 1181 * smb_node_create_audit_buf 1182 */ 1183 static void 1184 smb_node_create_audit_buf(smb_node_t *node, int kmflags) 1185 { 1186 smb_audit_buf_node_t *abn; 1187 1188 if (smb_audit_flags & SMB_AUDIT_NODE) { 1189 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags); 1190 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1; 1191 node->n_audit_buf = abn; 1192 } 1193 } 1194 1195 /* 1196 * smb_node_destroy_audit_buf 1197 */ 1198 static void 1199 smb_node_destroy_audit_buf(smb_node_t *node) 1200 { 1201 if (node->n_audit_buf != NULL) { 1202 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t)); 1203 node->n_audit_buf = NULL; 1204 } 1205 } 1206 1207 /* 1208 * smb_node_audit 1209 * 1210 * This function saves the calling stack in the audit buffer of the node passed 1211 * in. 1212 */ 1213 static void 1214 smb_node_audit(smb_node_t *node) 1215 { 1216 smb_audit_buf_node_t *abn; 1217 smb_audit_record_node_t *anr; 1218 1219 if (node->n_audit_buf) { 1220 abn = node->n_audit_buf; 1221 anr = abn->anb_records; 1222 anr += abn->anb_index; 1223 abn->anb_index++; 1224 abn->anb_index &= abn->anb_max_index; 1225 anr->anr_refcnt = node->n_refcnt; 1226 anr->anr_depth = getpcstack(anr->anr_stack, 1227 SMB_AUDIT_STACK_DEPTH); 1228 } 1229 } 1230 1231 static smb_llist_t * 1232 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey) 1233 { 1234 uint32_t hashkey; 1235 1236 hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid; 1237 hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8); 1238 *phashkey = hashkey; 1239 return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]); 1240 } 1241