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