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 700 /* 701 * system-wide share check 702 */ 703 if (nbl_share_conflict(node->vp, NBL_RENAME, NULL)) 704 return (NT_STATUS_SHARING_VIOLATION); 705 else 706 return (NT_STATUS_SUCCESS); 707 } 708 709 uint32_t 710 smb_node_delete_check(smb_node_t *node) 711 { 712 smb_ofile_t *of; 713 uint32_t status; 714 715 SMB_NODE_VALID(node); 716 717 if (smb_node_is_dir(node)) 718 return (NT_STATUS_SUCCESS); 719 720 if (smb_node_is_reparse(node)) 721 return (NT_STATUS_ACCESS_DENIED); 722 723 /* 724 * intra-CIFS check 725 */ 726 smb_llist_enter(&node->n_ofile_list, RW_READER); 727 of = smb_llist_head(&node->n_ofile_list); 728 while (of) { 729 status = smb_ofile_delete_check(of); 730 731 switch (status) { 732 case NT_STATUS_INVALID_HANDLE: 733 case NT_STATUS_SUCCESS: 734 of = smb_llist_next(&node->n_ofile_list, of); 735 break; 736 default: 737 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 738 smb_llist_exit(&node->n_ofile_list); 739 return (status); 740 } 741 } 742 smb_llist_exit(&node->n_ofile_list); 743 744 /* 745 * system-wide share check 746 */ 747 if (nbl_share_conflict(node->vp, NBL_REMOVE, NULL)) 748 return (NT_STATUS_SHARING_VIOLATION); 749 else 750 return (NT_STATUS_SUCCESS); 751 } 752 753 /* 754 * smb_node_share_check 755 * 756 * Returns: TRUE - ofiles have non-zero share access 757 * B_FALSE - ofile with share access NONE. 758 */ 759 boolean_t 760 smb_node_share_check(smb_node_t *node) 761 { 762 smb_ofile_t *of; 763 boolean_t status = B_TRUE; 764 765 SMB_NODE_VALID(node); 766 767 smb_llist_enter(&node->n_ofile_list, RW_READER); 768 of = smb_llist_head(&node->n_ofile_list); 769 if (of) 770 status = smb_ofile_share_check(of); 771 smb_llist_exit(&node->n_ofile_list); 772 773 return (status); 774 } 775 776 /* 777 * SMB Change Notification 778 */ 779 780 void 781 smb_node_fcn_subscribe(smb_node_t *node, smb_request_t *sr) 782 { 783 smb_node_fcn_t *fcn = &node->n_fcn; 784 785 mutex_enter(&fcn->fcn_mutex); 786 if (fcn->fcn_count == 0) 787 smb_fem_fcn_install(node); 788 fcn->fcn_count++; 789 list_insert_tail(&fcn->fcn_watchers, sr); 790 mutex_exit(&fcn->fcn_mutex); 791 } 792 793 void 794 smb_node_fcn_unsubscribe(smb_node_t *node, smb_request_t *sr) 795 { 796 smb_node_fcn_t *fcn = &node->n_fcn; 797 798 mutex_enter(&fcn->fcn_mutex); 799 list_remove(&fcn->fcn_watchers, sr); 800 fcn->fcn_count--; 801 if (fcn->fcn_count == 0) 802 smb_fem_fcn_uninstall(node); 803 mutex_exit(&fcn->fcn_mutex); 804 } 805 806 void 807 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name) 808 { 809 SMB_NODE_VALID(node); 810 811 smb_notify_event(node, action, name); 812 813 /* 814 * These two events come as a pair: 815 * FILE_ACTION_RENAMED_OLD_NAME 816 * FILE_ACTION_RENAMED_NEW_NAME 817 * Only do the parent notify for "new". 818 */ 819 if (action == FILE_ACTION_RENAMED_OLD_NAME) 820 return; 821 822 smb_node_notify_parents(node); 823 } 824 825 /* 826 * smb_node_notify_parents 827 * 828 * Iterate up the directory tree notifying any parent 829 * directories that are being watched for changes in 830 * their sub directories. 831 * Stop at the root node, which has a NULL parent node. 832 */ 833 void 834 smb_node_notify_parents(smb_node_t *dnode) 835 { 836 smb_node_t *pnode; /* parent */ 837 838 SMB_NODE_VALID(dnode); 839 pnode = dnode->n_dnode; 840 841 while (pnode != NULL) { 842 SMB_NODE_VALID(pnode); 843 smb_notify_event(pnode, 0, dnode->od_name); 844 /* cd .. */ 845 dnode = pnode; 846 pnode = dnode->n_dnode; 847 } 848 } 849 850 /* 851 * smb_node_start_crit() 852 * 853 * Enter critical region for share reservations. 854 * See comments above smb_fsop_shrlock(). 855 */ 856 void 857 smb_node_start_crit(smb_node_t *node, krw_t mode) 858 { 859 rw_enter(&node->n_lock, mode); 860 nbl_start_crit(node->vp, mode); 861 } 862 863 /* 864 * smb_node_end_crit() 865 * 866 * Exit critical region for share reservations. 867 */ 868 void 869 smb_node_end_crit(smb_node_t *node) 870 { 871 nbl_end_crit(node->vp); 872 rw_exit(&node->n_lock); 873 } 874 875 int 876 smb_node_in_crit(smb_node_t *node) 877 { 878 return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock)); 879 } 880 881 void 882 smb_node_rdlock(smb_node_t *node) 883 { 884 rw_enter(&node->n_lock, RW_READER); 885 } 886 887 void 888 smb_node_wrlock(smb_node_t *node) 889 { 890 rw_enter(&node->n_lock, RW_WRITER); 891 } 892 893 void 894 smb_node_unlock(smb_node_t *node) 895 { 896 rw_exit(&node->n_lock); 897 } 898 899 void 900 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of) 901 { 902 SMB_NODE_VALID(node); 903 904 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 905 smb_llist_insert_tail(&node->n_ofile_list, of); 906 smb_llist_exit(&node->n_ofile_list); 907 } 908 909 void 910 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of) 911 { 912 SMB_NODE_VALID(node); 913 914 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 915 smb_llist_remove(&node->n_ofile_list, of); 916 smb_llist_exit(&node->n_ofile_list); 917 } 918 919 /* 920 * smb_node_inc_open_ofiles 921 */ 922 void 923 smb_node_inc_open_ofiles(smb_node_t *node) 924 { 925 SMB_NODE_VALID(node); 926 atomic_inc_32(&node->n_open_count); 927 } 928 929 /* 930 * smb_node_dec_open_ofiles 931 * returns new value 932 */ 933 uint32_t 934 smb_node_dec_open_ofiles(smb_node_t *node) 935 { 936 SMB_NODE_VALID(node); 937 return (atomic_dec_32_nv(&node->n_open_count)); 938 } 939 940 /* 941 * smb_node_inc_opening_count 942 */ 943 void 944 smb_node_inc_opening_count(smb_node_t *node) 945 { 946 SMB_NODE_VALID(node); 947 atomic_inc_32(&node->n_opening_count); 948 } 949 950 /* 951 * smb_node_dec_opening_count 952 */ 953 void 954 smb_node_dec_opening_count(smb_node_t *node) 955 { 956 SMB_NODE_VALID(node); 957 atomic_dec_32(&node->n_opening_count); 958 } 959 960 /* 961 * smb_node_getmntpath 962 */ 963 int 964 smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen) 965 { 966 vnode_t *vp, *root_vp; 967 vfs_t *vfsp; 968 int err; 969 970 ASSERT(node); 971 ASSERT(node->vp); 972 ASSERT(node->vp->v_vfsp); 973 974 vp = node->vp; 975 vfsp = vp->v_vfsp; 976 977 if (VFS_ROOT(vfsp, &root_vp)) 978 return (ENOENT); 979 980 VN_HOLD(vp); 981 982 /* NULL is passed in as we want to start at "/" */ 983 err = vnodetopath(NULL, root_vp, buf, buflen, kcred); 984 985 VN_RELE(vp); 986 VN_RELE(root_vp); 987 return (err); 988 } 989 990 /* 991 * smb_node_getshrpath 992 * 993 * Determine the absolute pathname of 'node' within the share (tree). 994 * For example if the node represents file "test1.txt" in directory 995 * "dir1" the pathname would be: \dir1\test1.txt 996 */ 997 int 998 smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree, 999 char *buf, uint32_t buflen) 1000 { 1001 int rc; 1002 1003 ASSERT(node); 1004 ASSERT(tree); 1005 ASSERT(tree->t_snode); 1006 1007 rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen); 1008 (void) strsubst(buf, '/', '\\'); 1009 return (rc); 1010 } 1011 1012 /* 1013 * smb_node_getpath 1014 * 1015 * Determine the absolute pathname of 'node' from 'rootvp'. 1016 * 1017 * Using vnodetopath is only reliable for directory nodes (due to 1018 * its reliance on the DNLC for non-directory nodes). Thus, if node 1019 * represents a file, construct the pathname for the parent dnode 1020 * and append filename. 1021 * If node represents a named stream, construct the pathname for the 1022 * associated unnamed stream and append the stream name. 1023 * 1024 * The pathname returned in buf will be '/' separated. 1025 */ 1026 int 1027 smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen) 1028 { 1029 int rc; 1030 vnode_t *vp; 1031 smb_node_t *unode, *dnode; 1032 1033 unode = (SMB_IS_STREAM(node)) ? node->n_unode : node; 1034 dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode; 1035 1036 /* find path to directory node */ 1037 vp = dnode->vp; 1038 VN_HOLD(vp); 1039 if (rootvp) { 1040 VN_HOLD(rootvp); 1041 rc = vnodetopath(rootvp, vp, buf, buflen, kcred); 1042 VN_RELE(rootvp); 1043 } else { 1044 rc = vnodetopath(NULL, vp, buf, buflen, kcred); 1045 } 1046 VN_RELE(vp); 1047 1048 if (rc != 0) 1049 return (rc); 1050 1051 /* append filename if necessary */ 1052 if (!smb_node_is_dir(unode)) { 1053 if (buf[strlen(buf) - 1] != '/') 1054 (void) strlcat(buf, "/", buflen); 1055 (void) strlcat(buf, unode->od_name, buflen); 1056 } 1057 1058 /* append named stream name if necessary */ 1059 if (SMB_IS_STREAM(node)) 1060 (void) strlcat(buf, node->od_name, buflen); 1061 1062 return (rc); 1063 } 1064 1065 /* 1066 * smb_node_alloc 1067 */ 1068 static smb_node_t * 1069 smb_node_alloc( 1070 char *od_name, 1071 vnode_t *vp, 1072 smb_llist_t *bucket, 1073 uint32_t hashkey) 1074 { 1075 smb_node_t *node; 1076 vnode_t *root_vp; 1077 1078 node = kmem_cache_alloc(smb_node_cache, KM_SLEEP); 1079 1080 if (node->n_audit_buf != NULL) 1081 node->n_audit_buf->anb_index = 0; 1082 1083 node->flags = 0; 1084 VN_HOLD(vp); 1085 node->vp = vp; 1086 node->n_refcnt = 1; 1087 node->n_hash_bucket = bucket; 1088 node->n_hashkey = hashkey; 1089 node->n_pending_dosattr = 0; 1090 node->n_open_count = 0; 1091 node->n_allocsz = 0; 1092 node->n_dnode = NULL; 1093 node->n_unode = NULL; 1094 node->delete_on_close_cred = NULL; 1095 node->n_delete_on_close_flags = 0; 1096 node->n_oplock.ol_fem = B_FALSE; 1097 node->n_oplock.ol_xthread = NULL; 1098 node->n_oplock.ol_count = 0; 1099 node->n_oplock.ol_break = SMB_OPLOCK_NO_BREAK; 1100 1101 (void) strlcpy(node->od_name, od_name, sizeof (node->od_name)); 1102 if (strcmp(od_name, XATTR_DIR) == 0) 1103 node->flags |= NODE_XATTR_DIR; 1104 1105 if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) { 1106 if (vp == root_vp) 1107 node->flags |= NODE_FLAGS_VFSROOT; 1108 VN_RELE(root_vp); 1109 } 1110 1111 node->n_state = SMB_NODE_STATE_AVAILABLE; 1112 node->n_magic = SMB_NODE_MAGIC; 1113 1114 return (node); 1115 } 1116 1117 /* 1118 * smb_node_free 1119 */ 1120 static void 1121 smb_node_free(smb_node_t *node) 1122 { 1123 SMB_NODE_VALID(node); 1124 1125 node->n_magic = 0; 1126 VERIFY(!list_link_active(&node->n_lnd)); 1127 VERIFY(node->n_lock_list.ll_count == 0); 1128 VERIFY(node->n_ofile_list.ll_count == 0); 1129 VERIFY(node->n_oplock.ol_count == 0); 1130 VERIFY(node->n_oplock.ol_xthread == NULL); 1131 VERIFY(node->n_oplock.ol_fem == B_FALSE); 1132 VERIFY(mutex_owner(&node->n_mutex) == NULL); 1133 VERIFY(!RW_LOCK_HELD(&node->n_lock)); 1134 VN_RELE(node->vp); 1135 kmem_cache_free(smb_node_cache, node); 1136 } 1137 1138 /* 1139 * smb_node_constructor 1140 */ 1141 static int 1142 smb_node_constructor(void *buf, void *un, int kmflags) 1143 { 1144 _NOTE(ARGUNUSED(kmflags, un)) 1145 1146 smb_node_t *node = (smb_node_t *)buf; 1147 1148 bzero(node, sizeof (smb_node_t)); 1149 1150 smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t), 1151 offsetof(smb_ofile_t, f_nnd)); 1152 smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t), 1153 offsetof(smb_lock_t, l_lnd)); 1154 mutex_init(&node->n_fcn.fcn_mutex, NULL, MUTEX_DEFAULT, NULL); 1155 list_create(&node->n_fcn.fcn_watchers, sizeof (smb_request_t), 1156 offsetof(smb_request_t, sr_ncr.nc_lnd)); 1157 cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL); 1158 mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL); 1159 list_create(&node->n_oplock.ol_grants, sizeof (smb_oplock_grant_t), 1160 offsetof(smb_oplock_grant_t, og_lnd)); 1161 rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL); 1162 mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL); 1163 smb_node_create_audit_buf(node, kmflags); 1164 return (0); 1165 } 1166 1167 /* 1168 * smb_node_destructor 1169 */ 1170 static void 1171 smb_node_destructor(void *buf, void *un) 1172 { 1173 _NOTE(ARGUNUSED(un)) 1174 1175 smb_node_t *node = (smb_node_t *)buf; 1176 1177 smb_node_destroy_audit_buf(node); 1178 mutex_destroy(&node->n_mutex); 1179 rw_destroy(&node->n_lock); 1180 cv_destroy(&node->n_oplock.ol_cv); 1181 mutex_destroy(&node->n_oplock.ol_mutex); 1182 list_destroy(&node->n_fcn.fcn_watchers); 1183 mutex_destroy(&node->n_fcn.fcn_mutex); 1184 smb_llist_destructor(&node->n_lock_list); 1185 smb_llist_destructor(&node->n_ofile_list); 1186 list_destroy(&node->n_oplock.ol_grants); 1187 } 1188 1189 /* 1190 * smb_node_create_audit_buf 1191 */ 1192 static void 1193 smb_node_create_audit_buf(smb_node_t *node, int kmflags) 1194 { 1195 smb_audit_buf_node_t *abn; 1196 1197 if (smb_audit_flags & SMB_AUDIT_NODE) { 1198 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags); 1199 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1; 1200 node->n_audit_buf = abn; 1201 } 1202 } 1203 1204 /* 1205 * smb_node_destroy_audit_buf 1206 */ 1207 static void 1208 smb_node_destroy_audit_buf(smb_node_t *node) 1209 { 1210 if (node->n_audit_buf != NULL) { 1211 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t)); 1212 node->n_audit_buf = NULL; 1213 } 1214 } 1215 1216 /* 1217 * smb_node_audit 1218 * 1219 * This function saves the calling stack in the audit buffer of the node passed 1220 * in. 1221 */ 1222 static void 1223 smb_node_audit(smb_node_t *node) 1224 { 1225 smb_audit_buf_node_t *abn; 1226 smb_audit_record_node_t *anr; 1227 1228 if (node->n_audit_buf) { 1229 abn = node->n_audit_buf; 1230 anr = abn->anb_records; 1231 anr += abn->anb_index; 1232 abn->anb_index++; 1233 abn->anb_index &= abn->anb_max_index; 1234 anr->anr_refcnt = node->n_refcnt; 1235 anr->anr_depth = getpcstack(anr->anr_stack, 1236 SMB_AUDIT_STACK_DEPTH); 1237 } 1238 } 1239 1240 static smb_llist_t * 1241 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey) 1242 { 1243 uint32_t hashkey; 1244 1245 hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid; 1246 hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8); 1247 *phashkey = hashkey; 1248 return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]); 1249 } 1250 1251 boolean_t 1252 smb_node_is_file(smb_node_t *node) 1253 { 1254 SMB_NODE_VALID(node); 1255 return (node->vp->v_type == VREG); 1256 } 1257 1258 boolean_t 1259 smb_node_is_dir(smb_node_t *node) 1260 { 1261 SMB_NODE_VALID(node); 1262 return ((node->vp->v_type == VDIR) || 1263 (node->flags & NODE_FLAGS_DFSLINK)); 1264 } 1265 1266 boolean_t 1267 smb_node_is_symlink(smb_node_t *node) 1268 { 1269 SMB_NODE_VALID(node); 1270 return ((node->vp->v_type == VLNK) && 1271 ((node->flags & NODE_FLAGS_REPARSE) == 0)); 1272 } 1273 1274 boolean_t 1275 smb_node_is_dfslink(smb_node_t *node) 1276 { 1277 SMB_NODE_VALID(node); 1278 return ((node->vp->v_type == VLNK) && 1279 (node->flags & NODE_FLAGS_DFSLINK)); 1280 } 1281 1282 boolean_t 1283 smb_node_is_reparse(smb_node_t *node) 1284 { 1285 SMB_NODE_VALID(node); 1286 return ((node->vp->v_type == VLNK) && 1287 (node->flags & NODE_FLAGS_REPARSE)); 1288 } 1289 1290 boolean_t 1291 smb_node_is_vfsroot(smb_node_t *node) 1292 { 1293 SMB_NODE_VALID(node); 1294 return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT); 1295 } 1296 1297 boolean_t 1298 smb_node_is_system(smb_node_t *node) 1299 { 1300 SMB_NODE_VALID(node); 1301 return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM); 1302 } 1303 1304 /* 1305 * smb_node_file_is_readonly 1306 * 1307 * Checks if the file (which node represents) is marked readonly 1308 * in the filesystem. No account is taken of any pending readonly 1309 * in the node, which must be handled by the callers. 1310 * (See SMB_OFILE_IS_READONLY and SMB_PATHFILE_IS_READONLY) 1311 */ 1312 boolean_t 1313 smb_node_file_is_readonly(smb_node_t *node) 1314 { 1315 smb_attr_t attr; 1316 1317 if (node == NULL) 1318 return (B_FALSE); /* pipes */ 1319 1320 if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY) 1321 return (B_TRUE); 1322 1323 bzero(&attr, sizeof (smb_attr_t)); 1324 attr.sa_mask = SMB_AT_DOSATTR; 1325 (void) smb_fsop_getattr(NULL, kcred, node, &attr); 1326 return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0); 1327 } 1328 1329 /* 1330 * smb_node_setattr 1331 * 1332 * The sr may be NULL, for example when closing an ofile. 1333 * The ofile may be NULL, for example when a client request 1334 * specifies the file by pathname. 1335 * 1336 * Returns: errno 1337 * 1338 * Timestamps 1339 * 1340 * Windows and Unix have different models for timestamp updates. 1341 * [MS-FSA 2.1.5.14 Server Requests Setting of File Information] 1342 * 1343 * An open "handle" in Windows can control whether and when 1344 * any timestamp updates happen for that handle. For example, 1345 * timestamps set via some handle are no longer updated by I/O 1346 * operations on that handle. In Unix we don't really have any 1347 * way to avoid the timestamp updates that the file system does. 1348 * Therefore, we need to make some compromises, and simulate the 1349 * more important parts of the Windows file system semantics. 1350 * 1351 * For example, when an SMB client sets file times, set those 1352 * times in the file system (so the change will be visible to 1353 * other clients, at least until they change again) but we also 1354 * make those times "sticky" in our open handle, and reapply 1355 * those times when the handle is closed. That reapply on close 1356 * simulates the Windows behavior where the timestamp updates 1357 * would be discontinued after they were set. These "sticky" 1358 * attributes are returned in any query on the handle where 1359 * they are stored. 1360 * 1361 * Other than the above, the file system layer takes care of the 1362 * normal time stamp updates, such as updating the mtime after a 1363 * write, and ctime after an attribute change. 1364 * 1365 * Dos Attributes are stored persistently, but with a twist: 1366 * In Windows, when you set the "read-only" bit on some file, 1367 * existing writable handles to that file continue to have 1368 * write access. (because access check happens at open) 1369 * If we were to set the read-only bit directly, we would 1370 * cause errors in subsequent writes on any of our open 1371 * (and writable) file handles. So here too, we have to 1372 * simulate the Windows behavior. We keep the read-only 1373 * bit "pending" in the smb_node (so it will be visible in 1374 * any new opens of the file) and apply it on close. 1375 * 1376 * File allocation size is also simulated, and not persistent. 1377 * When the file allocation size is set it is first rounded up 1378 * to block size. If the file size is smaller than the allocation 1379 * size the file is truncated by setting the filesize to allocsz. 1380 */ 1381 int 1382 smb_node_setattr(smb_request_t *sr, smb_node_t *node, 1383 cred_t *cr, smb_ofile_t *of, smb_attr_t *attr) 1384 { 1385 int rc; 1386 uint_t times_mask; 1387 smb_attr_t tmp_attr; 1388 1389 SMB_NODE_VALID(node); 1390 1391 /* set attributes specified in attr */ 1392 if (attr->sa_mask == 0) 1393 return (0); /* nothing to do (caller bug?) */ 1394 1395 /* 1396 * Allocation size and EOF position interact. 1397 * We don't persistently store the allocation size 1398 * but make it look like we do while there are opens. 1399 * Note: We update the caller's attr in the cases 1400 * where they're setting only one of allocsz|size. 1401 */ 1402 switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) { 1403 1404 case SMB_AT_ALLOCSZ: 1405 /* 1406 * Setting the allocation size but not EOF position. 1407 * Get the current EOF in tmp_attr and (if necessary) 1408 * truncate to the (rounded up) allocation size. 1409 */ 1410 bzero(&tmp_attr, sizeof (smb_attr_t)); 1411 tmp_attr.sa_mask = SMB_AT_SIZE; 1412 rc = smb_fsop_getattr(NULL, kcred, node, &tmp_attr); 1413 if (rc != 0) 1414 return (rc); 1415 attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz); 1416 if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) { 1417 /* truncate the file to allocsz */ 1418 attr->sa_vattr.va_size = attr->sa_allocsz; 1419 attr->sa_mask |= SMB_AT_SIZE; 1420 } 1421 break; 1422 1423 case SMB_AT_SIZE: 1424 /* 1425 * Setting the EOF position but not allocation size. 1426 * If the new EOF position would be greater than 1427 * the allocation size, increase the latter. 1428 */ 1429 if (node->n_allocsz < attr->sa_vattr.va_size) { 1430 attr->sa_mask |= SMB_AT_ALLOCSZ; 1431 attr->sa_allocsz = 1432 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1433 } 1434 break; 1435 1436 case SMB_AT_ALLOCSZ | SMB_AT_SIZE: 1437 /* 1438 * Setting both. Increase alloc size if needed. 1439 */ 1440 if (attr->sa_allocsz < attr->sa_vattr.va_size) 1441 attr->sa_allocsz = 1442 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1443 break; 1444 1445 default: 1446 break; 1447 } 1448 1449 /* 1450 * If we have an open file, and we set the size, 1451 * then set the "written" flag so that at close, 1452 * we can force an mtime update. 1453 */ 1454 if (of != NULL && (attr->sa_mask & SMB_AT_SIZE) != 0) 1455 of->f_written = B_TRUE; 1456 1457 /* 1458 * When operating on an open file, some settable attributes 1459 * become "sticky" in the open file object until close. 1460 * (see above re. timestamps) 1461 */ 1462 times_mask = attr->sa_mask & SMB_AT_TIMES; 1463 if (of != NULL && times_mask != 0) { 1464 smb_attr_t *pa; 1465 1466 SMB_OFILE_VALID(of); 1467 mutex_enter(&of->f_mutex); 1468 pa = &of->f_pending_attr; 1469 1470 pa->sa_mask |= times_mask; 1471 1472 if (times_mask & SMB_AT_ATIME) 1473 pa->sa_vattr.va_atime = 1474 attr->sa_vattr.va_atime; 1475 if (times_mask & SMB_AT_MTIME) 1476 pa->sa_vattr.va_mtime = 1477 attr->sa_vattr.va_mtime; 1478 if (times_mask & SMB_AT_CTIME) 1479 pa->sa_vattr.va_ctime = 1480 attr->sa_vattr.va_ctime; 1481 if (times_mask & SMB_AT_CRTIME) 1482 pa->sa_crtime = 1483 attr->sa_crtime; 1484 1485 mutex_exit(&of->f_mutex); 1486 /* 1487 * The f_pending_attr times are reapplied in 1488 * smb_ofile_close(). 1489 */ 1490 } 1491 1492 /* 1493 * After this point, tmp_attr is what we will actually 1494 * store in the file system _now_, which may differ 1495 * from the callers attr and f_pending_attr w.r.t. 1496 * the DOS readonly flag etc. 1497 */ 1498 bcopy(attr, &tmp_attr, sizeof (tmp_attr)); 1499 if (attr->sa_mask & (SMB_AT_DOSATTR | SMB_AT_ALLOCSZ)) { 1500 mutex_enter(&node->n_mutex); 1501 if ((attr->sa_mask & SMB_AT_DOSATTR) != 0) { 1502 tmp_attr.sa_dosattr &= smb_vop_dosattr_settable; 1503 if (((tmp_attr.sa_dosattr & 1504 FILE_ATTRIBUTE_READONLY) != 0) && 1505 (node->n_open_count != 0)) { 1506 /* Delay setting readonly */ 1507 node->n_pending_dosattr = 1508 tmp_attr.sa_dosattr; 1509 tmp_attr.sa_dosattr &= 1510 ~FILE_ATTRIBUTE_READONLY; 1511 } else { 1512 node->n_pending_dosattr = 0; 1513 } 1514 } 1515 /* 1516 * Simulate n_allocsz persistence only while 1517 * there are opens. See smb_node_getattr 1518 */ 1519 if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0 && 1520 node->n_open_count != 0) 1521 node->n_allocsz = attr->sa_allocsz; 1522 mutex_exit(&node->n_mutex); 1523 } 1524 1525 rc = smb_fsop_setattr(sr, cr, node, &tmp_attr); 1526 if (rc != 0) 1527 return (rc); 1528 1529 if (node->n_dnode != NULL) { 1530 smb_node_notify_change(node->n_dnode, 1531 FILE_ACTION_MODIFIED, node->od_name); 1532 } 1533 1534 return (0); 1535 } 1536 1537 /* 1538 * smb_node_getattr 1539 * 1540 * Get attributes from the file system and apply any smb-specific 1541 * overrides for size, dos attributes and timestamps 1542 * 1543 * When node->n_pending_readonly is set on a node, pretend that 1544 * we've already set this node readonly at the filesystem level. 1545 * We can't actually do that until all writable handles are closed 1546 * or those writable handles would suddenly loose their access. 1547 * 1548 * Returns: errno 1549 */ 1550 int 1551 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr, 1552 smb_ofile_t *of, smb_attr_t *attr) 1553 { 1554 int rc; 1555 uint_t want_mask, pend_mask; 1556 boolean_t isdir; 1557 1558 SMB_NODE_VALID(node); 1559 1560 /* Deal with some interdependencies */ 1561 if (attr->sa_mask & SMB_AT_ALLOCSZ) 1562 attr->sa_mask |= SMB_AT_SIZE; 1563 if (attr->sa_mask & SMB_AT_DOSATTR) 1564 attr->sa_mask |= SMB_AT_TYPE; 1565 1566 rc = smb_fsop_getattr(sr, cr, node, attr); 1567 if (rc != 0) 1568 return (rc); 1569 1570 isdir = smb_node_is_dir(node); 1571 1572 mutex_enter(&node->n_mutex); 1573 1574 /* 1575 * When there are open handles, and one of them has 1576 * set the DOS readonly flag (in n_pending_dosattr), 1577 * it will not have been stored in the file system. 1578 * In this case use n_pending_dosattr. Note that 1579 * n_pending_dosattr has only the settable bits, 1580 * (setattr masks it with smb_vop_dosattr_settable) 1581 * so we need to keep any non-settable bits we got 1582 * from the file-system above. 1583 */ 1584 if (attr->sa_mask & SMB_AT_DOSATTR) { 1585 if (node->n_pending_dosattr) { 1586 attr->sa_dosattr &= ~smb_vop_dosattr_settable; 1587 attr->sa_dosattr |= node->n_pending_dosattr; 1588 } 1589 if (attr->sa_dosattr == 0) { 1590 attr->sa_dosattr = (isdir) ? 1591 FILE_ATTRIBUTE_DIRECTORY: 1592 FILE_ATTRIBUTE_NORMAL; 1593 } 1594 } 1595 1596 /* 1597 * Also fix-up sa_allocsz, which is not persistent. 1598 * When there are no open files, allocsz is faked. 1599 * While there are open files, we pretend we have a 1600 * persistent allocation size in n_allocsz, and 1601 * keep that up-to-date here, increasing it when 1602 * we see the file size grow past it. 1603 */ 1604 if (attr->sa_mask & SMB_AT_ALLOCSZ) { 1605 if (isdir) { 1606 attr->sa_allocsz = 0; 1607 } else if (node->n_open_count == 0) { 1608 attr->sa_allocsz = 1609 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1610 } else { 1611 if (node->n_allocsz < attr->sa_vattr.va_size) 1612 node->n_allocsz = 1613 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1614 attr->sa_allocsz = node->n_allocsz; 1615 } 1616 } 1617 1618 mutex_exit(&node->n_mutex); 1619 1620 if (isdir) { 1621 attr->sa_vattr.va_size = 0; 1622 attr->sa_vattr.va_nlink = 1; 1623 } 1624 1625 /* 1626 * getattr with an ofile gets any "pending" times that 1627 * might have been previously set via this ofile. 1628 * This is what makes these times "sticky". 1629 */ 1630 want_mask = attr->sa_mask & SMB_AT_TIMES; 1631 if (of != NULL && want_mask != 0) { 1632 smb_attr_t *pa; 1633 1634 SMB_OFILE_VALID(of); 1635 mutex_enter(&of->f_mutex); 1636 pa = &of->f_pending_attr; 1637 1638 pend_mask = pa->sa_mask; 1639 1640 if (want_mask & pend_mask & SMB_AT_ATIME) 1641 attr->sa_vattr.va_atime = 1642 pa->sa_vattr.va_atime; 1643 if (want_mask & pend_mask & SMB_AT_MTIME) 1644 attr->sa_vattr.va_mtime = 1645 pa->sa_vattr.va_mtime; 1646 if (want_mask & pend_mask & SMB_AT_CTIME) 1647 attr->sa_vattr.va_ctime = 1648 pa->sa_vattr.va_ctime; 1649 if (want_mask & pend_mask & SMB_AT_CRTIME) 1650 attr->sa_crtime = 1651 pa->sa_crtime; 1652 1653 mutex_exit(&of->f_mutex); 1654 } 1655 1656 1657 return (0); 1658 } 1659 1660 1661 /* 1662 * Check to see if the node represents a reparse point. 1663 * If yes, whether the reparse point contains a DFS link. 1664 */ 1665 static void 1666 smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr) 1667 { 1668 nvlist_t *nvl; 1669 nvpair_t *rec; 1670 char *rec_type; 1671 1672 if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) 1673 return; 1674 1675 if ((nvl = reparse_init()) == NULL) 1676 return; 1677 1678 if (reparse_vnode_parse(node->vp, nvl) != 0) { 1679 reparse_free(nvl); 1680 return; 1681 } 1682 1683 node->flags |= NODE_FLAGS_REPARSE; 1684 1685 rec = nvlist_next_nvpair(nvl, NULL); 1686 while (rec != NULL) { 1687 rec_type = nvpair_name(rec); 1688 if ((rec_type != NULL) && 1689 (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) { 1690 node->flags |= NODE_FLAGS_DFSLINK; 1691 break; 1692 } 1693 rec = nvlist_next_nvpair(nvl, rec); 1694 } 1695 1696 reparse_free(nvl); 1697 } 1698 1699 /* 1700 * smb_node_init_system 1701 * 1702 * If the node represents a special system file set NODE_FLAG_SYSTEM. 1703 * System files: 1704 * - any node whose parent dnode has NODE_FLAG_SYSTEM set 1705 * - any node whose associated unnamed stream node (unode) has 1706 * NODE_FLAG_SYSTEM set 1707 * - .$EXTEND at root of share (quota management) 1708 */ 1709 static void 1710 smb_node_init_system(smb_node_t *node) 1711 { 1712 smb_node_t *dnode = node->n_dnode; 1713 smb_node_t *unode = node->n_unode; 1714 1715 if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) { 1716 node->flags |= NODE_FLAGS_SYSTEM; 1717 return; 1718 } 1719 1720 if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) { 1721 node->flags |= NODE_FLAGS_SYSTEM; 1722 return; 1723 } 1724 1725 if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) && 1726 (strcasecmp(node->od_name, ".$EXTEND") == 0))) { 1727 node->flags |= NODE_FLAGS_SYSTEM; 1728 } 1729 } 1730