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