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 2010 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 (node != dnode) && 342 (strcmp(od_name, "..") != 0) && 343 (strcmp(od_name, ".") != 0)) { 344 VALIDATE_DIR_NODE(dnode, node); 345 node->n_dnode = dnode; 346 smb_node_ref(dnode); 347 } 348 349 smb_node_audit(node); 350 mutex_exit(&node->n_mutex); 351 smb_llist_exit(node_hdr); 352 return (node); 353 354 case SMB_NODE_STATE_DESTROYING: 355 /* 356 * Although the node exists it is about 357 * to be destroyed. We act as it hasn't 358 * been found. 359 */ 360 mutex_exit(&node->n_mutex); 361 break; 362 default: 363 /* 364 * Although the node exists it is in an 365 * unknown state. We act as it hasn't 366 * been found. 367 */ 368 ASSERT(0); 369 mutex_exit(&node->n_mutex); 370 break; 371 } 372 } 373 node = smb_llist_next(node_hdr, node); 374 } 375 if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) { 376 lock_mode = RW_WRITER; 377 continue; 378 } 379 break; 380 } 381 node = smb_node_alloc(od_name, vp, node_hdr, hashkey); 382 node->n_orig_uid = crgetuid(sr->user_cr); 383 384 if (op) 385 node->flags |= smb_is_executable(op->fqi.fq_last_comp); 386 387 if (dnode) { 388 smb_node_ref(dnode); 389 node->n_dnode = dnode; 390 ASSERT(dnode->n_dnode != node); 391 ASSERT((dnode->vp->v_xattrdir) || 392 (dnode->vp->v_type == VDIR)); 393 } 394 395 if (unode) { 396 smb_node_ref(unode); 397 node->n_unode = unode; 398 } 399 400 DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node); 401 smb_node_audit(node); 402 smb_llist_insert_head(node_hdr, node); 403 smb_llist_exit(node_hdr); 404 return (node); 405 } 406 407 /* 408 * smb_stream_node_lookup() 409 * 410 * Note: stream_name (the name that will be stored in the "od_name" field 411 * of a stream's smb_node) is the same as the on-disk name for the stream 412 * except that it does not have SMB_STREAM_PREFIX prepended. 413 */ 414 415 smb_node_t * 416 smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode, 417 vnode_t *xattrdirvp, vnode_t *vp, char *stream_name) 418 { 419 smb_node_t *xattrdir_node; 420 smb_node_t *snode; 421 422 xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR, 423 fnode, NULL); 424 425 if (xattrdir_node == NULL) 426 return (NULL); 427 428 snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node, 429 fnode); 430 431 (void) smb_node_release(xattrdir_node); 432 return (snode); 433 } 434 435 436 /* 437 * This function should be called whenever a reference is needed on an 438 * smb_node pointer. The copy of an smb_node pointer from one non-local 439 * data structure to another requires a reference to be taken on the smb_node 440 * (unless the usage is localized). Each data structure deallocation routine 441 * will call smb_node_release() on its smb_node pointers. 442 * 443 * In general, an smb_node pointer residing in a structure should never be 444 * stale. A node pointer may be NULL, however, and care should be taken 445 * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid. 446 * Care also needs to be taken with respect to racing deallocations of a 447 * structure. 448 */ 449 void 450 smb_node_ref(smb_node_t *node) 451 { 452 SMB_NODE_VALID(node); 453 454 mutex_enter(&node->n_mutex); 455 switch (node->n_state) { 456 case SMB_NODE_STATE_AVAILABLE: 457 case SMB_NODE_STATE_OPLOCK_GRANTED: 458 case SMB_NODE_STATE_OPLOCK_BREAKING: 459 node->n_refcnt++; 460 ASSERT(node->n_refcnt); 461 DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node); 462 smb_node_audit(node); 463 break; 464 default: 465 SMB_PANIC(); 466 } 467 mutex_exit(&node->n_mutex); 468 } 469 470 /* 471 * smb_node_lookup() takes a hold on an smb_node, whether found in the 472 * hash table or newly created. This hold is expected to be released 473 * in the following manner. 474 * 475 * smb_node_lookup() takes an address of an smb_node pointer. This should 476 * be getting passed down via a lookup (whether path name or component), mkdir, 477 * create. If the original smb_node pointer resides in a data structure, then 478 * the deallocation routine for the data structure is responsible for calling 479 * smb_node_release() on the smb_node pointer. Alternatively, 480 * smb_node_release() can be called as soon as the smb_node pointer is no longer 481 * needed. In this case, callers are responsible for setting an embedded 482 * pointer to NULL if it is known that the last reference is being released. 483 * 484 * If the passed-in address of the smb_node pointer belongs to a local variable, 485 * then the caller with the local variable should call smb_node_release() 486 * directly. 487 * 488 * smb_node_release() itself will call smb_node_release() on a node's n_dnode, 489 * as smb_node_lookup() takes a hold on dnode. 490 */ 491 void 492 smb_node_release(smb_node_t *node) 493 { 494 SMB_NODE_VALID(node); 495 496 mutex_enter(&node->n_mutex); 497 ASSERT(node->n_refcnt); 498 DTRACE_PROBE1(smb_node_release, smb_node_t *, node); 499 if (--node->n_refcnt == 0) { 500 switch (node->n_state) { 501 502 case SMB_NODE_STATE_AVAILABLE: 503 node->n_state = SMB_NODE_STATE_DESTROYING; 504 mutex_exit(&node->n_mutex); 505 506 smb_llist_enter(node->n_hash_bucket, RW_WRITER); 507 smb_llist_remove(node->n_hash_bucket, node); 508 smb_llist_exit(node->n_hash_bucket); 509 510 /* 511 * Check if the file was deleted 512 */ 513 smb_node_delete_on_close(node); 514 515 if (node->n_dnode) { 516 ASSERT(node->n_dnode->n_magic == 517 SMB_NODE_MAGIC); 518 smb_node_release(node->n_dnode); 519 } 520 521 if (node->n_unode) { 522 ASSERT(node->n_unode->n_magic == 523 SMB_NODE_MAGIC); 524 smb_node_release(node->n_unode); 525 } 526 527 smb_node_free(node); 528 return; 529 530 default: 531 SMB_PANIC(); 532 } 533 } 534 smb_node_audit(node); 535 mutex_exit(&node->n_mutex); 536 } 537 538 static void 539 smb_node_delete_on_close(smb_node_t *node) 540 { 541 smb_node_t *d_snode; 542 int rc = 0; 543 uint32_t flags = 0; 544 545 d_snode = node->n_dnode; 546 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 547 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 548 flags = node->n_delete_on_close_flags; 549 ASSERT(node->od_name != NULL); 550 551 if (node->vp->v_type == VDIR) 552 rc = smb_fsop_rmdir(0, node->delete_on_close_cred, 553 d_snode, node->od_name, flags); 554 else 555 rc = smb_fsop_remove(0, node->delete_on_close_cred, 556 d_snode, node->od_name, flags); 557 smb_cred_rele(node->delete_on_close_cred); 558 } 559 if (rc != 0) 560 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n", 561 node->od_name, rc); 562 DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node); 563 } 564 565 /* 566 * smb_node_rename() 567 * 568 */ 569 void 570 smb_node_rename( 571 smb_node_t *from_dnode, 572 smb_node_t *ret_node, 573 smb_node_t *to_dnode, 574 char *to_name) 575 { 576 SMB_NODE_VALID(from_dnode); 577 SMB_NODE_VALID(to_dnode); 578 SMB_NODE_VALID(ret_node); 579 580 smb_node_ref(to_dnode); 581 mutex_enter(&ret_node->n_mutex); 582 switch (ret_node->n_state) { 583 case SMB_NODE_STATE_AVAILABLE: 584 case SMB_NODE_STATE_OPLOCK_GRANTED: 585 case SMB_NODE_STATE_OPLOCK_BREAKING: 586 ret_node->n_dnode = to_dnode; 587 mutex_exit(&ret_node->n_mutex); 588 ASSERT(to_dnode->n_dnode != ret_node); 589 ASSERT((to_dnode->vp->v_xattrdir) || 590 (to_dnode->vp->v_type == VDIR)); 591 smb_node_release(from_dnode); 592 (void) strcpy(ret_node->od_name, to_name); 593 /* 594 * XXX Need to update attributes? 595 */ 596 break; 597 default: 598 SMB_PANIC(); 599 } 600 } 601 602 int 603 smb_node_root_init(vnode_t *vp, smb_server_t *sv, smb_node_t **root) 604 { 605 smb_attr_t attr; 606 int error; 607 uint32_t hashkey; 608 smb_llist_t *node_hdr; 609 smb_node_t *node; 610 611 attr.sa_mask = SMB_AT_ALL; 612 error = smb_vop_getattr(vp, NULL, &attr, 0, kcred); 613 if (error) { 614 VN_RELE(vp); 615 return (error); 616 } 617 618 node_hdr = smb_node_get_hash(&vp->v_vfsp->vfs_fsid, &attr, &hashkey); 619 620 node = smb_node_alloc(ROOTVOL, vp, node_hdr, hashkey); 621 622 sv->si_root_smb_node = node; 623 smb_node_audit(node); 624 smb_llist_enter(node_hdr, RW_WRITER); 625 smb_llist_insert_head(node_hdr, node); 626 smb_llist_exit(node_hdr); 627 *root = node; 628 return (0); 629 } 630 631 /* 632 * When DeleteOnClose is set on an smb_node, the common open code will 633 * reject subsequent open requests for the file. Observation of Windows 634 * 2000 indicates that subsequent opens should be allowed (assuming 635 * there would be no sharing violation) until the file is closed using 636 * the fid on which the DeleteOnClose was requested. 637 * 638 * If there are multiple opens with delete-on-close create options, 639 * whichever the first file handle is closed will trigger the node to be 640 * marked as delete-on-close. The credentials of that ofile will be used 641 * as the delete-on-close credentials of the node. 642 */ 643 int 644 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags) 645 { 646 int rc = 0; 647 smb_attr_t attr; 648 649 if (node->readonly_creator) 650 return (-1); 651 652 bzero(&attr, sizeof (smb_attr_t)); 653 attr.sa_mask = SMB_AT_DOSATTR; 654 rc = smb_fsop_getattr(NULL, kcred, node, &attr); 655 if ((rc != 0) || (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) { 656 return (-1); 657 } 658 659 mutex_enter(&node->n_mutex); 660 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 661 rc = -1; 662 } else { 663 crhold(cr); 664 node->delete_on_close_cred = cr; 665 node->n_delete_on_close_flags = flags; 666 node->flags |= NODE_FLAGS_DELETE_ON_CLOSE; 667 rc = 0; 668 } 669 mutex_exit(&node->n_mutex); 670 return (rc); 671 } 672 673 void 674 smb_node_reset_delete_on_close(smb_node_t *node) 675 { 676 mutex_enter(&node->n_mutex); 677 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 678 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 679 crfree(node->delete_on_close_cred); 680 node->delete_on_close_cred = NULL; 681 node->n_delete_on_close_flags = 0; 682 } 683 mutex_exit(&node->n_mutex); 684 } 685 686 /* 687 * smb_node_open_check 688 * 689 * check file sharing rules for current open request 690 * against all existing opens for a file. 691 * 692 * Returns NT_STATUS_SHARING_VIOLATION if there is any 693 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 694 */ 695 uint32_t 696 smb_node_open_check( 697 smb_node_t *node, 698 cred_t *cr, 699 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, cr, desired_access, 711 share_access); 712 713 switch (status) { 714 case NT_STATUS_INVALID_HANDLE: 715 case NT_STATUS_SUCCESS: 716 of = smb_llist_next(&node->n_ofile_list, of); 717 break; 718 default: 719 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 720 smb_llist_exit(&node->n_ofile_list); 721 return (status); 722 } 723 } 724 725 smb_llist_exit(&node->n_ofile_list); 726 return (NT_STATUS_SUCCESS); 727 } 728 729 uint32_t 730 smb_node_rename_check(smb_node_t *node) 731 { 732 smb_ofile_t *of; 733 uint32_t status; 734 735 SMB_NODE_VALID(node); 736 737 /* 738 * Intra-CIFS check 739 */ 740 smb_llist_enter(&node->n_ofile_list, RW_READER); 741 of = smb_llist_head(&node->n_ofile_list); 742 while (of) { 743 status = smb_ofile_rename_check(of); 744 745 switch (status) { 746 case NT_STATUS_INVALID_HANDLE: 747 case NT_STATUS_SUCCESS: 748 of = smb_llist_next(&node->n_ofile_list, of); 749 break; 750 default: 751 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 752 smb_llist_exit(&node->n_ofile_list); 753 return (status); 754 } 755 } 756 smb_llist_exit(&node->n_ofile_list); 757 758 /* 759 * system-wide share check 760 */ 761 if (nbl_share_conflict(node->vp, NBL_RENAME, NULL)) 762 return (NT_STATUS_SHARING_VIOLATION); 763 else 764 return (NT_STATUS_SUCCESS); 765 } 766 767 uint32_t 768 smb_node_delete_check(smb_node_t *node) 769 { 770 smb_ofile_t *of; 771 uint32_t status; 772 773 SMB_NODE_VALID(node); 774 775 if (node->vp->v_type == VDIR) 776 return (NT_STATUS_SUCCESS); 777 778 /* 779 * intra-CIFS check 780 */ 781 smb_llist_enter(&node->n_ofile_list, RW_READER); 782 of = smb_llist_head(&node->n_ofile_list); 783 while (of) { 784 status = smb_ofile_delete_check(of); 785 786 switch (status) { 787 case NT_STATUS_INVALID_HANDLE: 788 case NT_STATUS_SUCCESS: 789 of = smb_llist_next(&node->n_ofile_list, of); 790 break; 791 default: 792 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 793 smb_llist_exit(&node->n_ofile_list); 794 return (status); 795 } 796 } 797 smb_llist_exit(&node->n_ofile_list); 798 799 /* 800 * system-wide share check 801 */ 802 if (nbl_share_conflict(node->vp, NBL_REMOVE, NULL)) 803 return (NT_STATUS_SHARING_VIOLATION); 804 else 805 return (NT_STATUS_SUCCESS); 806 } 807 808 void 809 smb_node_notify_change(smb_node_t *node) 810 { 811 SMB_NODE_VALID(node); 812 813 if (node->flags & NODE_FLAGS_NOTIFY_CHANGE) { 814 node->flags |= NODE_FLAGS_CHANGED; 815 smb_process_node_notify_change_queue(node); 816 } 817 } 818 819 static void 820 smb_node_notify_parent(smb_node_t *node) 821 { 822 SMB_NODE_VALID(node); 823 824 if (node->n_dnode != NULL) 825 smb_node_notify_change(node->n_dnode); 826 } 827 828 /* 829 * smb_node_start_crit() 830 * 831 * Enter critical region for share reservations. 832 * See comments above smb_fsop_shrlock(). 833 */ 834 835 void 836 smb_node_start_crit(smb_node_t *node, krw_t mode) 837 { 838 rw_enter(&node->n_lock, mode); 839 nbl_start_crit(node->vp, mode); 840 } 841 842 /* 843 * smb_node_end_crit() 844 * 845 * Exit critical region for share reservations. 846 */ 847 848 void 849 smb_node_end_crit(smb_node_t *node) 850 { 851 nbl_end_crit(node->vp); 852 rw_exit(&node->n_lock); 853 } 854 855 int 856 smb_node_in_crit(smb_node_t *node) 857 { 858 return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock)); 859 } 860 861 void 862 smb_node_rdlock(smb_node_t *node) 863 { 864 rw_enter(&node->n_lock, RW_READER); 865 } 866 867 void 868 smb_node_wrlock(smb_node_t *node) 869 { 870 rw_enter(&node->n_lock, RW_WRITER); 871 } 872 873 void 874 smb_node_unlock(smb_node_t *node) 875 { 876 rw_exit(&node->n_lock); 877 } 878 879 uint32_t 880 smb_node_get_ofile_count(smb_node_t *node) 881 { 882 uint32_t cntr; 883 884 SMB_NODE_VALID(node); 885 886 smb_llist_enter(&node->n_ofile_list, RW_READER); 887 cntr = smb_llist_get_count(&node->n_ofile_list); 888 smb_llist_exit(&node->n_ofile_list); 889 return (cntr); 890 } 891 892 void 893 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of) 894 { 895 SMB_NODE_VALID(node); 896 897 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 898 smb_llist_insert_tail(&node->n_ofile_list, of); 899 smb_llist_exit(&node->n_ofile_list); 900 } 901 902 void 903 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of) 904 { 905 SMB_NODE_VALID(node); 906 907 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 908 smb_llist_remove(&node->n_ofile_list, of); 909 smb_llist_exit(&node->n_ofile_list); 910 } 911 912 /* 913 * smb_node_inc_open_ofiles 914 */ 915 void 916 smb_node_inc_open_ofiles(smb_node_t *node) 917 { 918 SMB_NODE_VALID(node); 919 920 mutex_enter(&node->n_mutex); 921 node->n_open_count++; 922 mutex_exit(&node->n_mutex); 923 924 smb_node_init_cached_data(node); 925 } 926 927 /* 928 * smb_node_dec_open_ofiles 929 */ 930 void 931 smb_node_dec_open_ofiles(smb_node_t *node) 932 { 933 SMB_NODE_VALID(node); 934 935 mutex_enter(&node->n_mutex); 936 node->n_open_count--; 937 mutex_exit(&node->n_mutex); 938 939 smb_node_clear_cached_data(node); 940 } 941 942 uint32_t 943 smb_node_get_open_ofiles(smb_node_t *node) 944 { 945 uint32_t cnt; 946 947 SMB_NODE_VALID(node); 948 949 mutex_enter(&node->n_mutex); 950 cnt = node->n_open_count; 951 mutex_exit(&node->n_mutex); 952 return (cnt); 953 } 954 955 /* 956 * smb_node_alloc 957 */ 958 static smb_node_t * 959 smb_node_alloc( 960 char *od_name, 961 vnode_t *vp, 962 smb_llist_t *bucket, 963 uint32_t hashkey) 964 { 965 smb_node_t *node; 966 967 node = kmem_cache_alloc(smb_node_cache, KM_SLEEP); 968 969 if (node->n_audit_buf != NULL) 970 node->n_audit_buf->anb_index = 0; 971 972 node->flags = 0; 973 VN_HOLD(vp); 974 node->vp = vp; 975 node->n_refcnt = 1; 976 node->n_hash_bucket = bucket; 977 node->n_hashkey = hashkey; 978 node->n_orig_uid = 0; 979 node->readonly_creator = NULL; 980 node->waiting_event = 0; 981 node->n_open_count = 0; 982 node->n_dnode = NULL; 983 node->n_unode = NULL; 984 node->delete_on_close_cred = NULL; 985 node->n_delete_on_close_flags = 0; 986 987 (void) strlcpy(node->od_name, od_name, sizeof (node->od_name)); 988 if (strcmp(od_name, XATTR_DIR) == 0) 989 node->flags |= NODE_XATTR_DIR; 990 991 node->n_state = SMB_NODE_STATE_AVAILABLE; 992 node->n_magic = SMB_NODE_MAGIC; 993 return (node); 994 } 995 996 /* 997 * smb_node_free 998 */ 999 static void 1000 smb_node_free(smb_node_t *node) 1001 { 1002 SMB_NODE_VALID(node); 1003 1004 node->n_magic = 0; 1005 VERIFY(!list_link_active(&node->n_lnd)); 1006 VERIFY(node->n_lock_list.ll_count == 0); 1007 VERIFY(node->n_ofile_list.ll_count == 0); 1008 VERIFY(node->n_oplock.ol_xthread == NULL); 1009 VERIFY(mutex_owner(&node->n_mutex) == NULL); 1010 VERIFY(!RW_LOCK_HELD(&node->n_lock)); 1011 VN_RELE(node->vp); 1012 kmem_cache_free(smb_node_cache, node); 1013 } 1014 1015 /* 1016 * smb_node_constructor 1017 */ 1018 static int 1019 smb_node_constructor(void *buf, void *un, int kmflags) 1020 { 1021 _NOTE(ARGUNUSED(kmflags, un)) 1022 1023 smb_node_t *node = (smb_node_t *)buf; 1024 1025 bzero(node, sizeof (smb_node_t)); 1026 1027 smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t), 1028 offsetof(smb_ofile_t, f_nnd)); 1029 smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t), 1030 offsetof(smb_lock_t, l_lnd)); 1031 cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL); 1032 rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL); 1033 mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL); 1034 smb_node_create_audit_buf(node, kmflags); 1035 return (0); 1036 } 1037 1038 /* 1039 * smb_node_destructor 1040 */ 1041 static void 1042 smb_node_destructor(void *buf, void *un) 1043 { 1044 _NOTE(ARGUNUSED(un)) 1045 1046 smb_node_t *node = (smb_node_t *)buf; 1047 1048 smb_node_destroy_audit_buf(node); 1049 mutex_destroy(&node->n_mutex); 1050 rw_destroy(&node->n_lock); 1051 cv_destroy(&node->n_oplock.ol_cv); 1052 smb_llist_destructor(&node->n_lock_list); 1053 smb_llist_destructor(&node->n_ofile_list); 1054 } 1055 1056 /* 1057 * smb_node_create_audit_buf 1058 */ 1059 static void 1060 smb_node_create_audit_buf(smb_node_t *node, int kmflags) 1061 { 1062 smb_audit_buf_node_t *abn; 1063 1064 if (smb_audit_flags & SMB_AUDIT_NODE) { 1065 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags); 1066 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1; 1067 node->n_audit_buf = abn; 1068 } 1069 } 1070 1071 /* 1072 * smb_node_destroy_audit_buf 1073 */ 1074 static void 1075 smb_node_destroy_audit_buf(smb_node_t *node) 1076 { 1077 if (node->n_audit_buf != NULL) { 1078 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t)); 1079 node->n_audit_buf = NULL; 1080 } 1081 } 1082 1083 /* 1084 * smb_node_audit 1085 * 1086 * This function saves the calling stack in the audit buffer of the node passed 1087 * in. 1088 */ 1089 static void 1090 smb_node_audit(smb_node_t *node) 1091 { 1092 smb_audit_buf_node_t *abn; 1093 smb_audit_record_node_t *anr; 1094 1095 if (node->n_audit_buf) { 1096 abn = node->n_audit_buf; 1097 anr = abn->anb_records; 1098 anr += abn->anb_index; 1099 abn->anb_index++; 1100 abn->anb_index &= abn->anb_max_index; 1101 anr->anr_refcnt = node->n_refcnt; 1102 anr->anr_depth = getpcstack(anr->anr_stack, 1103 SMB_AUDIT_STACK_DEPTH); 1104 } 1105 } 1106 1107 static smb_llist_t * 1108 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey) 1109 { 1110 uint32_t hashkey; 1111 1112 hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid; 1113 hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8); 1114 *phashkey = hashkey; 1115 return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]); 1116 } 1117 1118 boolean_t 1119 smb_node_is_dir(smb_node_t *node) 1120 { 1121 SMB_NODE_VALID(node); 1122 return (node->vp->v_type == VDIR); 1123 } 1124 1125 boolean_t 1126 smb_node_is_link(smb_node_t *node) 1127 { 1128 SMB_NODE_VALID(node); 1129 return (node->vp->v_type == VLNK); 1130 } 1131 1132 /* 1133 * smb_node_file_is_readonly 1134 * 1135 * Checks if the file (which node represents) is marked readonly 1136 * in the filesystem. No account is taken of any pending readonly 1137 * in the node, which must be handled by the callers. 1138 * (See SMB_OFILE_IS_READONLY and SMB_PATHFILE_IS_READONLY) 1139 */ 1140 boolean_t 1141 smb_node_file_is_readonly(smb_node_t *node) 1142 { 1143 smb_attr_t attr; 1144 1145 if (node == NULL) 1146 return (B_FALSE); 1147 1148 bzero(&attr, sizeof (smb_attr_t)); 1149 attr.sa_mask = SMB_AT_DOSATTR; 1150 (void) smb_fsop_getattr(NULL, kcred, node, &attr); 1151 return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0); 1152 } 1153 1154 /* 1155 * smb_node_setattr 1156 * 1157 * The sr may be NULL, for example when closing an ofile. 1158 * The ofile may be NULL, for example when a client request 1159 * specifies the file by pathname. 1160 * 1161 * Timestamps 1162 * When attributes are set on an ofile, any pending timestamps 1163 * from a write request on the ofile are implicitly set to "now". 1164 * For compatibility with windows the following timestamps are 1165 * also implicitly set to now: 1166 * - if any attribute is being explicitly set, set ctime to now 1167 * - if file size is being explicitly set, set atime & ctime to now 1168 * 1169 * Any timestamp that is being explicitly set, or has previously 1170 * been explicitly set on the ofile, is excluded from implicit 1171 * (now) setting. 1172 * 1173 * Updates the node's cached timestamp values. 1174 * Updates the ofile's explicit times flag. 1175 * 1176 * File allocation size 1177 * When the file allocation size is set it is first rounded up 1178 * to block size. If the file size is smaller than the allocation 1179 * size the file is truncated by setting the filesize to allocsz. 1180 * If there are open ofiles, the allocsz is cached on the node. 1181 * 1182 * Updates the node's cached allocsz value. 1183 * 1184 * Returns: errno 1185 */ 1186 int 1187 smb_node_setattr(smb_request_t *sr, smb_node_t *node, 1188 cred_t *cr, smb_ofile_t *of, smb_attr_t *attr) 1189 { 1190 int rc; 1191 uint32_t pending_times = 0; 1192 uint32_t explicit_times = 0; 1193 timestruc_t now; 1194 smb_attr_t tmp_attr; 1195 1196 ASSERT(attr); 1197 SMB_NODE_VALID(node); 1198 1199 /* set attributes specified in attr */ 1200 if (attr->sa_mask != 0) { 1201 /* if allocation size is < file size, truncate the file */ 1202 if (attr->sa_mask & SMB_AT_ALLOCSZ) { 1203 attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz); 1204 1205 bzero(&tmp_attr, sizeof (smb_attr_t)); 1206 tmp_attr.sa_mask = SMB_AT_SIZE; 1207 (void) smb_fsop_getattr(NULL, kcred, node, &tmp_attr); 1208 1209 if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) { 1210 attr->sa_vattr.va_size = attr->sa_allocsz; 1211 attr->sa_mask |= SMB_AT_SIZE; 1212 } 1213 } 1214 1215 rc = smb_fsop_setattr(sr, cr, node, attr); 1216 if (rc != 0) 1217 return (rc); 1218 1219 smb_node_set_cached_allocsz(node, attr); 1220 smb_node_set_cached_timestamps(node, attr); 1221 if (of) { 1222 smb_ofile_set_explicit_times(of, 1223 (attr->sa_mask & SMB_AT_TIMES)); 1224 } 1225 } 1226 1227 /* 1228 * Determine which timestamps to implicitly set to "now". 1229 * Don't overwrite timestamps already explicitly set. 1230 */ 1231 bzero(&tmp_attr, sizeof (smb_attr_t)); 1232 gethrestime(&now); 1233 tmp_attr.sa_vattr.va_atime = now; 1234 tmp_attr.sa_vattr.va_mtime = now; 1235 tmp_attr.sa_vattr.va_ctime = now; 1236 1237 /* pending write timestamps */ 1238 if (of) { 1239 if (smb_ofile_write_time_pending(of)) { 1240 pending_times |= 1241 (SMB_AT_MTIME | SMB_AT_CTIME | SMB_AT_ATIME); 1242 } 1243 explicit_times |= (smb_ofile_explicit_times(of)); 1244 } 1245 explicit_times |= (attr->sa_mask & SMB_AT_TIMES); 1246 pending_times &= ~explicit_times; 1247 1248 if (pending_times) { 1249 tmp_attr.sa_mask = pending_times; 1250 (void) smb_fsop_setattr(NULL, kcred, node, &tmp_attr); 1251 } 1252 1253 /* additional timestamps to update in cache */ 1254 if (attr->sa_mask) 1255 tmp_attr.sa_mask |= SMB_AT_CTIME; 1256 if (attr->sa_mask & (SMB_AT_SIZE | SMB_AT_ALLOCSZ)) 1257 tmp_attr.sa_mask |= SMB_AT_MTIME; 1258 tmp_attr.sa_mask &= ~explicit_times; 1259 1260 if (tmp_attr.sa_mask) 1261 smb_node_set_cached_timestamps(node, &tmp_attr); 1262 1263 if (tmp_attr.sa_mask & SMB_AT_MTIME || explicit_times & SMB_AT_MTIME) 1264 smb_node_notify_parent(node); 1265 1266 return (0); 1267 } 1268 1269 /* 1270 * smb_node_getattr 1271 * 1272 * Get attributes from the file system and apply any smb-specific 1273 * overrides for size, dos attributes and timestamps 1274 * 1275 * node->readonly_creator reflects whether a readonly set is pending 1276 * from a readonly create. The readonly attribute should be visible to 1277 * all clients even though the readonly creator fid is immune to the 1278 * readonly bit until close. 1279 * 1280 * Returns: errno 1281 */ 1282 int 1283 smb_node_getattr(smb_request_t *sr, smb_node_t *node, smb_attr_t *attr) 1284 { 1285 int rc; 1286 1287 SMB_NODE_VALID(node); 1288 1289 bzero(attr, sizeof (smb_attr_t)); 1290 attr->sa_mask = SMB_AT_ALL; 1291 rc = smb_fsop_getattr(sr, kcred, node, attr); 1292 if (rc != 0) 1293 return (rc); 1294 1295 mutex_enter(&node->n_mutex); 1296 1297 if (node->vp->v_type == VDIR) { 1298 attr->sa_vattr.va_size = 0; 1299 attr->sa_allocsz = 0; 1300 attr->sa_vattr.va_nlink = 1; 1301 } 1302 1303 if (node->readonly_creator) 1304 attr->sa_dosattr |= FILE_ATTRIBUTE_READONLY; 1305 if (attr->sa_dosattr == 0) 1306 attr->sa_dosattr = FILE_ATTRIBUTE_NORMAL; 1307 1308 1309 mutex_exit(&node->n_mutex); 1310 1311 smb_node_get_cached_allocsz(node, attr); 1312 smb_node_get_cached_timestamps(node, attr); 1313 1314 return (0); 1315 } 1316 1317 /* 1318 * smb_node_init_cached_data 1319 */ 1320 static void 1321 smb_node_init_cached_data(smb_node_t *node) 1322 { 1323 smb_attr_t attr; 1324 1325 bzero(&attr, sizeof (smb_attr_t)); 1326 attr.sa_mask = SMB_AT_ALL; 1327 (void) smb_fsop_getattr(NULL, kcred, node, &attr); 1328 1329 smb_node_init_cached_allocsz(node, &attr); 1330 smb_node_init_cached_timestamps(node, &attr); 1331 } 1332 1333 /* 1334 * smb_node_clear_cached_data 1335 */ 1336 static void 1337 smb_node_clear_cached_data(smb_node_t *node) 1338 { 1339 smb_node_clear_cached_allocsz(node); 1340 smb_node_clear_cached_timestamps(node); 1341 } 1342 1343 /* 1344 * File allocation size (allocsz) caching 1345 * 1346 * When there are open ofiles on the node, the file allocsz is cached. 1347 * The cached value (n_allocsz) is initialized when the first ofile is 1348 * opened and cleared when the last is closed. Allocsz calculated from 1349 * the filesize (rounded up to block size). 1350 * When the allocation size is queried, if the cached allocsz is less 1351 * than the filesize, it is recalculated from the filesize. 1352 */ 1353 1354 /* 1355 * smb_node_init_cached_allocsz 1356 * 1357 * If there are open ofiles, cache the allocsz in the node. 1358 * Calculate the allocsz from the filesizes. 1359 * block size). 1360 */ 1361 static void 1362 smb_node_init_cached_allocsz(smb_node_t *node, smb_attr_t *attr) 1363 { 1364 mutex_enter(&node->n_mutex); 1365 if (node->n_open_count == 1) 1366 node->n_allocsz = SMB_ALLOCSZ(attr->sa_vattr.va_size); 1367 mutex_exit(&node->n_mutex); 1368 } 1369 1370 /* 1371 * smb_node_clear_cached_allocsz 1372 */ 1373 static void 1374 smb_node_clear_cached_allocsz(smb_node_t *node) 1375 { 1376 mutex_enter(&node->n_mutex); 1377 if (node->n_open_count == 0) 1378 node->n_allocsz = 0; 1379 mutex_exit(&node->n_mutex); 1380 } 1381 1382 /* 1383 * smb_node_get_cached_allocsz 1384 * 1385 * If there is no cached allocsz (no open files), calculate 1386 * allocsz from the filesize. 1387 * If the allocsz is cached but is smaller than the filesize 1388 * recalculate the cached allocsz from the filesize. 1389 * 1390 * Return allocs in attr->sa_allocsz. 1391 */ 1392 static void 1393 smb_node_get_cached_allocsz(smb_node_t *node, smb_attr_t *attr) 1394 { 1395 if (node->vp->v_type == VDIR) 1396 return; 1397 1398 mutex_enter(&node->n_mutex); 1399 if (node->n_open_count == 0) { 1400 attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_vattr.va_size); 1401 } else { 1402 if (node->n_allocsz < attr->sa_vattr.va_size) 1403 node->n_allocsz = SMB_ALLOCSZ(attr->sa_vattr.va_size); 1404 attr->sa_allocsz = node->n_allocsz; 1405 } 1406 mutex_exit(&node->n_mutex); 1407 } 1408 1409 /* 1410 * smb_node_set_cached_allocsz 1411 * 1412 * attr->sa_allocsz has already been rounded to block size by 1413 * the caller. 1414 */ 1415 static void 1416 smb_node_set_cached_allocsz(smb_node_t *node, smb_attr_t *attr) 1417 { 1418 mutex_enter(&node->n_mutex); 1419 if (attr->sa_mask & SMB_AT_ALLOCSZ) { 1420 if (node->n_open_count > 0) 1421 node->n_allocsz = attr->sa_allocsz; 1422 } 1423 mutex_exit(&node->n_mutex); 1424 } 1425 1426 1427 /* 1428 * Timestamp caching 1429 * 1430 * Solaris file systems handle timestamps different from NTFS. For 1431 * example when file data is written NTFS doesn't update the timestamps 1432 * until the file is closed, and then only if they haven't been explicity 1433 * set via a set attribute request. In order to provide a more similar 1434 * view of an open file's timestamps, we cache the timestamps in the 1435 * node and manipulate them in a manner more consistent with windows. 1436 * (See handling of explicit times and pending timestamps from a write 1437 * request in smb_node_getattr and smb_node_setattr above.) 1438 * Timestamps remain cached while there are open ofiles for the node. 1439 * This includes open ofiles for named streams. 1440 * n_open_ofiles cannot be used as this doesn't include ofiles opened 1441 * for the node's named streams. Thus n_timestamps contains a count 1442 * of open ofiles (t_open_ofiles), including named streams' ofiles, 1443 * to be used to control timestamp caching. 1444 * 1445 * If a node represents a named stream the associated unnamed streams 1446 * cached timestamps are used instead. 1447 */ 1448 1449 /* 1450 * smb_node_init_cached_timestamps 1451 * 1452 * Increment count of open ofiles which are using the cached timestamps. 1453 * If this is the first open ofile, init the cached timestamps from the 1454 * file system values. 1455 */ 1456 static void 1457 smb_node_init_cached_timestamps(smb_node_t *node, smb_attr_t *attr) 1458 { 1459 smb_node_t *unode; 1460 1461 if ((unode = SMB_IS_STREAM(node)) != NULL) 1462 node = unode; 1463 1464 mutex_enter(&node->n_mutex); 1465 ++(node->n_timestamps.t_open_ofiles); 1466 if (node->n_timestamps.t_open_ofiles == 1) { 1467 node->n_timestamps.t_mtime = attr->sa_vattr.va_mtime; 1468 node->n_timestamps.t_atime = attr->sa_vattr.va_atime; 1469 node->n_timestamps.t_ctime = attr->sa_vattr.va_ctime; 1470 node->n_timestamps.t_crtime = attr->sa_crtime; 1471 node->n_timestamps.t_cached = B_TRUE; 1472 } 1473 mutex_exit(&node->n_mutex); 1474 } 1475 1476 /* 1477 * smb_node_clear_cached_timestamps 1478 * 1479 * Decrement count of open ofiles using the cached timestamps. 1480 * If the decremented count is zero, clear the cached timestamps. 1481 */ 1482 static void 1483 smb_node_clear_cached_timestamps(smb_node_t *node) 1484 { 1485 smb_node_t *unode; 1486 1487 if ((unode = SMB_IS_STREAM(node)) != NULL) 1488 node = unode; 1489 1490 mutex_enter(&node->n_mutex); 1491 ASSERT(node->n_timestamps.t_open_ofiles > 0); 1492 --(node->n_timestamps.t_open_ofiles); 1493 if (node->n_timestamps.t_open_ofiles == 0) 1494 bzero(&node->n_timestamps, sizeof (smb_times_t)); 1495 mutex_exit(&node->n_mutex); 1496 } 1497 1498 /* 1499 * smb_node_get_cached_timestamps 1500 * 1501 * Overwrite timestamps in attr with those cached in node. 1502 */ 1503 static void 1504 smb_node_get_cached_timestamps(smb_node_t *node, smb_attr_t *attr) 1505 { 1506 smb_node_t *unode; 1507 1508 if ((unode = SMB_IS_STREAM(node)) != NULL) 1509 node = unode; 1510 1511 mutex_enter(&node->n_mutex); 1512 if (node->n_timestamps.t_cached) { 1513 attr->sa_vattr.va_mtime = node->n_timestamps.t_mtime; 1514 attr->sa_vattr.va_atime = node->n_timestamps.t_atime; 1515 attr->sa_vattr.va_ctime = node->n_timestamps.t_ctime; 1516 attr->sa_crtime = node->n_timestamps.t_crtime; 1517 } 1518 mutex_exit(&node->n_mutex); 1519 } 1520 1521 /* 1522 * smb_node_set_cached_timestamps 1523 * 1524 * Update the node's cached timestamps with values from attr. 1525 */ 1526 static void 1527 smb_node_set_cached_timestamps(smb_node_t *node, smb_attr_t *attr) 1528 { 1529 smb_node_t *unode; 1530 1531 if ((unode = SMB_IS_STREAM(node)) != NULL) 1532 node = unode; 1533 1534 mutex_enter(&node->n_mutex); 1535 if (node->n_timestamps.t_cached) { 1536 if (attr->sa_mask & SMB_AT_MTIME) 1537 node->n_timestamps.t_mtime = attr->sa_vattr.va_mtime; 1538 if (attr->sa_mask & SMB_AT_ATIME) 1539 node->n_timestamps.t_atime = attr->sa_vattr.va_atime; 1540 if (attr->sa_mask & SMB_AT_CTIME) 1541 node->n_timestamps.t_ctime = attr->sa_vattr.va_ctime; 1542 if (attr->sa_mask & SMB_AT_CRTIME) 1543 node->n_timestamps.t_crtime = attr->sa_crtime; 1544 } 1545 mutex_exit(&node->n_mutex); 1546 } 1547