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