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