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