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