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