1 /* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: smbfs_vnops.c,v 1.128.36.1 2005/05/27 02:35:28 lindak Exp $ 33 */ 34 35 /* 36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 37 */ 38 39 #include <sys/systm.h> 40 #include <sys/cred.h> 41 #include <sys/vnode.h> 42 #include <sys/vfs.h> 43 #include <sys/filio.h> 44 #include <sys/uio.h> 45 #include <sys/dirent.h> 46 #include <sys/errno.h> 47 #include <sys/sunddi.h> 48 #include <sys/sysmacros.h> 49 #include <sys/kmem.h> 50 #include <sys/cmn_err.h> 51 #include <sys/vfs_opreg.h> 52 #include <sys/policy.h> 53 54 #include <sys/param.h> 55 #include <sys/vm.h> 56 #include <vm/seg_vn.h> 57 #include <vm/pvn.h> 58 #include <vm/as.h> 59 #include <vm/hat.h> 60 #include <vm/page.h> 61 #include <vm/seg.h> 62 #include <vm/seg_map.h> 63 #include <vm/seg_kmem.h> 64 #include <vm/seg_kpm.h> 65 66 #include <netsmb/smb_osdep.h> 67 #include <netsmb/smb.h> 68 #include <netsmb/smb_conn.h> 69 #include <netsmb/smb_subr.h> 70 71 #include <smbfs/smbfs.h> 72 #include <smbfs/smbfs_node.h> 73 #include <smbfs/smbfs_subr.h> 74 75 #include <sys/fs/smbfs_ioctl.h> 76 #include <fs/fs_subr.h> 77 78 /* 79 * We assign directory offsets like the NFS client, where the 80 * offset increments by _one_ after each directory entry. 81 * Further, the entries "." and ".." are always at offsets 82 * zero and one (respectively) and the "real" entries from 83 * the server appear at offsets starting with two. This 84 * macro is used to initialize the n_dirofs field after 85 * setting n_dirseq with a _findopen call. 86 */ 87 #define FIRST_DIROFS 2 88 89 /* 90 * These characters are illegal in NTFS file names. 91 * ref: http://support.microsoft.com/kb/147438 92 * 93 * Careful! The check in the XATTR case skips the 94 * first character to allow colon in XATTR names. 95 */ 96 static const char illegal_chars[] = { 97 ':', /* colon - keep this first! */ 98 '\\', /* back slash */ 99 '/', /* slash */ 100 '*', /* asterisk */ 101 '?', /* question mark */ 102 '"', /* double quote */ 103 '<', /* less than sign */ 104 '>', /* greater than sign */ 105 '|', /* vertical bar */ 106 0 107 }; 108 109 /* 110 * Turning this on causes nodes to be created in the cache 111 * during directory listings, normally avoiding a second 112 * OtW attribute fetch just after a readdir. 113 */ 114 int smbfs_fastlookup = 1; 115 116 /* local static function defines */ 117 118 static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **, 119 cred_t *); 120 static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, 121 int cache_ok, caller_context_t *); 122 static int smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, 123 cred_t *cr, caller_context_t *); 124 static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *); 125 static int smbfs_accessx(void *, int, cred_t *); 126 static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, 127 caller_context_t *); 128 static void smbfs_rele_fid(smbnode_t *, struct smb_cred *); 129 130 /* 131 * These are the vnode ops routines which implement the vnode interface to 132 * the networked file system. These routines just take their parameters, 133 * make them look networkish by putting the right info into interface structs, 134 * and then calling the appropriate remote routine(s) to do the work. 135 * 136 * Note on directory name lookup cacheing: If we detect a stale fhandle, 137 * we purge the directory cache relative to that vnode. This way, the 138 * user won't get burned by the cache repeatedly. See <smbfs/smbnode.h> for 139 * more details on smbnode locking. 140 */ 141 142 static int smbfs_open(vnode_t **, int, cred_t *, caller_context_t *); 143 static int smbfs_close(vnode_t *, int, int, offset_t, cred_t *, 144 caller_context_t *); 145 static int smbfs_read(vnode_t *, struct uio *, int, cred_t *, 146 caller_context_t *); 147 static int smbfs_write(vnode_t *, struct uio *, int, cred_t *, 148 caller_context_t *); 149 static int smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *, 150 caller_context_t *); 151 static int smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *, 152 caller_context_t *); 153 static int smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *, 154 caller_context_t *); 155 static int smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *); 156 static int smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *); 157 static void smbfs_inactive(vnode_t *, cred_t *, caller_context_t *); 158 static int smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *, 159 int, vnode_t *, cred_t *, caller_context_t *, 160 int *, pathname_t *); 161 static int smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl, 162 int, vnode_t **, cred_t *, int, caller_context_t *, 163 vsecattr_t *); 164 static int smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *, 165 int); 166 static int smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *, 167 caller_context_t *, int); 168 static int smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **, 169 cred_t *, caller_context_t *, int, vsecattr_t *); 170 static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *, 171 caller_context_t *, int); 172 static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *, 173 caller_context_t *, int); 174 static int smbfs_rwlock(vnode_t *, int, caller_context_t *); 175 static void smbfs_rwunlock(vnode_t *, int, caller_context_t *); 176 static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *); 177 static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t, 178 struct flk_callback *, cred_t *, caller_context_t *); 179 static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t, 180 cred_t *, caller_context_t *); 181 static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *, 182 caller_context_t *); 183 static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *, 184 caller_context_t *); 185 static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *, 186 caller_context_t *); 187 static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *, 188 caller_context_t *); 189 190 static int uio_page_mapin(uio_t *uiop, page_t *pp); 191 192 static void uio_page_mapout(uio_t *uiop, page_t *pp); 193 194 static int smbfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, 195 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr, 196 caller_context_t *ct); 197 198 static int smbfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, 199 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr, 200 caller_context_t *ct); 201 202 static int smbfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, 203 size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr, 204 caller_context_t *ct); 205 206 static int smbfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, 207 cred_t *cr, caller_context_t *ct); 208 209 static int smbfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, 210 int flags, cred_t *cr); 211 212 static int smbfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp, 213 page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr, 214 enum seg_rw rw, cred_t *cr, caller_context_t *ct); 215 216 static int smbfs_getapage(vnode_t *vp, u_offset_t off, size_t len, 217 uint_t *protp, page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr, 218 enum seg_rw rw, cred_t *cr); 219 220 static int writenp(smbnode_t *np, caddr_t base, int tcount, struct uio *uiop, int pgcreated); 221 222 /* Dummy function to use until correct function is ported in */ 223 int noop_vnodeop() { 224 return (0); 225 } 226 227 struct vnodeops *smbfs_vnodeops = NULL; 228 229 /* 230 * Most unimplemented ops will return ENOSYS because of fs_nosys(). 231 * The only ops where that won't work are ACCESS (due to open(2) 232 * failures) and ... (anything else left?) 233 */ 234 const fs_operation_def_t smbfs_vnodeops_template[] = { 235 { VOPNAME_OPEN, { .vop_open = smbfs_open } }, 236 { VOPNAME_CLOSE, { .vop_close = smbfs_close } }, 237 { VOPNAME_READ, { .vop_read = smbfs_read } }, 238 { VOPNAME_WRITE, { .vop_write = smbfs_write } }, 239 { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } }, 240 { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } }, 241 { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } }, 242 { VOPNAME_ACCESS, { .vop_access = smbfs_access } }, 243 { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } }, 244 { VOPNAME_CREATE, { .vop_create = smbfs_create } }, 245 { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } }, 246 { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */ 247 { VOPNAME_RENAME, { .vop_rename = smbfs_rename } }, 248 { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } }, 249 { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } }, 250 { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } }, 251 { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */ 252 { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */ 253 { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } }, 254 { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } }, 255 { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */ 256 { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } }, 257 { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } }, 258 { VOPNAME_SEEK, { .vop_seek = smbfs_seek } }, 259 { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } }, 260 { VOPNAME_SPACE, { .vop_space = smbfs_space } }, 261 { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */ 262 { VOPNAME_GETPAGE, { .vop_getpage = smbfs_getpage } }, /* smbfs_getpage, */ 263 { VOPNAME_PUTPAGE, { .vop_putpage = smbfs_putpage } }, /* smbfs_putpage, */ 264 { VOPNAME_MAP, { .vop_map = smbfs_map } }, /* smbfs_map, */ 265 { VOPNAME_ADDMAP, { .vop_addmap = smbfs_addmap } }, /* smbfs_addmap, */ 266 { VOPNAME_DELMAP, { .vop_delmap = smbfs_delmap } }, /* smbfs_delmap, */ 267 { VOPNAME_DISPOSE, { .vop_dispose = fs_dispose}}, 268 { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */ 269 { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } }, 270 { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */ 271 { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } }, 272 { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } }, 273 { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } }, 274 { NULL, NULL } 275 }; 276 277 /* 278 * XXX 279 * When new and relevant functionality is enabled, we should be 280 * calling vfs_set_feature() to inform callers that pieces of 281 * functionality are available, per PSARC 2007/227. 282 */ 283 /* ARGSUSED */ 284 static int 285 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) 286 { 287 smbnode_t *np; 288 vnode_t *vp; 289 smbfattr_t fa; 290 u_int32_t rights, rightsrcvd; 291 u_int16_t fid, oldfid; 292 int oldgenid; 293 struct smb_cred scred; 294 smbmntinfo_t *smi; 295 smb_share_t *ssp; 296 cred_t *oldcr; 297 int tmperror; 298 int error = 0; 299 300 vp = *vpp; 301 np = VTOSMB(vp); 302 smi = VTOSMI(vp); 303 ssp = smi->smi_share; 304 305 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 306 return (EIO); 307 308 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 309 return (EIO); 310 311 if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */ 312 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type); 313 return (EACCES); 314 } 315 316 /* 317 * Get exclusive access to n_fid and related stuff. 318 * No returns after this until out. 319 */ 320 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 321 return (EINTR); 322 smb_credinit(&scred, cr); 323 324 /* 325 * Keep track of the vnode type at first open. 326 * It may change later, and we need close to do 327 * cleanup for the type we opened. Also deny 328 * open of new types until old type is closed. 329 * XXX: Per-open instance nodes whould help. 330 */ 331 if (np->n_ovtype == VNON) { 332 ASSERT(np->n_dirrefs == 0); 333 ASSERT(np->n_fidrefs == 0); 334 } else if (np->n_ovtype != vp->v_type) { 335 SMBVDEBUG("open n_ovtype=%d v_type=%d\n", 336 np->n_ovtype, vp->v_type); 337 error = EACCES; 338 goto out; 339 } 340 341 /* 342 * Directory open. See smbfs_readvdir() 343 */ 344 if (vp->v_type == VDIR) { 345 if (np->n_dirseq == NULL) { 346 /* first open */ 347 error = smbfs_smb_findopen(np, "*", 1, 348 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, 349 &scred, &np->n_dirseq); 350 if (error != 0) 351 goto out; 352 } 353 np->n_dirofs = FIRST_DIROFS; 354 np->n_dirrefs++; 355 goto have_fid; 356 } 357 358 /* 359 * If caller specified O_TRUNC/FTRUNC, then be sure to set 360 * FWRITE (to drive successful setattr(size=0) after open) 361 */ 362 if (flag & FTRUNC) 363 flag |= FWRITE; 364 365 /* 366 * If we already have it open, and the FID is still valid, 367 * check whether the rights are sufficient for FID reuse. 368 */ 369 if (np->n_fidrefs > 0 && 370 np->n_vcgenid == ssp->ss_vcgenid) { 371 int upgrade = 0; 372 373 if ((flag & FWRITE) && 374 !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA)) 375 upgrade = 1; 376 if ((flag & FREAD) && 377 !(np->n_rights & SA_RIGHT_FILE_READ_DATA)) 378 upgrade = 1; 379 if (!upgrade) { 380 /* 381 * the existing open is good enough 382 */ 383 np->n_fidrefs++; 384 goto have_fid; 385 } 386 } 387 rights = np->n_fidrefs ? np->n_rights : 0; 388 389 /* 390 * we always ask for READ_CONTROL so we can always get the 391 * owner/group IDs to satisfy a stat. Ditto attributes. 392 */ 393 rights |= (STD_RIGHT_READ_CONTROL_ACCESS | 394 SA_RIGHT_FILE_READ_ATTRIBUTES); 395 if ((flag & FREAD)) 396 rights |= SA_RIGHT_FILE_READ_DATA; 397 if ((flag & FWRITE)) 398 rights |= SA_RIGHT_FILE_WRITE_DATA | 399 SA_RIGHT_FILE_APPEND_DATA | 400 SA_RIGHT_FILE_WRITE_ATTRIBUTES; 401 402 bzero(&fa, sizeof (fa)); 403 error = smbfs_smb_open(np, 404 NULL, 0, 0, /* name nmlen xattr */ 405 rights, &scred, 406 &fid, &rightsrcvd, &fa); 407 if (error) 408 goto out; 409 smbfs_attrcache_fa(vp, &fa); 410 411 /* 412 * We have a new FID and access rights. 413 */ 414 oldfid = np->n_fid; 415 oldgenid = np->n_vcgenid; 416 np->n_fid = fid; 417 np->n_vcgenid = ssp->ss_vcgenid; 418 np->n_rights = rightsrcvd; 419 np->n_fidrefs++; 420 if (np->n_fidrefs > 1 && 421 oldgenid == ssp->ss_vcgenid) { 422 /* 423 * We already had it open (presumably because 424 * it was open with insufficient rights.) 425 * Close old wire-open. 426 */ 427 tmperror = smbfs_smb_close(ssp, 428 oldfid, NULL, &scred); 429 if (tmperror) 430 SMBVDEBUG("error %d closing %s\n", 431 tmperror, np->n_rpath); 432 } 433 434 /* 435 * This thread did the open. 436 * Save our credentials too. 437 */ 438 mutex_enter(&np->r_statelock); 439 oldcr = np->r_cred; 440 np->r_cred = cr; 441 crhold(cr); 442 if (oldcr) 443 crfree(oldcr); 444 mutex_exit(&np->r_statelock); 445 446 have_fid: 447 /* 448 * Keep track of the vnode type at first open. 449 * (see comments above) 450 */ 451 if (np->n_ovtype == VNON) 452 np->n_ovtype = vp->v_type; 453 454 out: 455 smb_credrele(&scred); 456 smbfs_rw_exit(&np->r_lkserlock); 457 return (error); 458 } 459 460 /*ARGSUSED*/ 461 static int 462 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr, 463 caller_context_t *ct) 464 { 465 smbnode_t *np; 466 smbmntinfo_t *smi; 467 struct smb_cred scred; 468 469 np = VTOSMB(vp); 470 smi = VTOSMI(vp); 471 472 /* 473 * Don't "bail out" for VFS_UNMOUNTED here, 474 * as we want to do cleanup, etc. 475 */ 476 477 /* 478 * zone_enter(2) prevents processes from changing zones with SMBFS files 479 * open; if we happen to get here from the wrong zone we can't do 480 * anything over the wire. 481 */ 482 if (smi->smi_zone_ref.zref_zone != curproc->p_zone) { 483 /* 484 * We could attempt to clean up locks, except we're sure 485 * that the current process didn't acquire any locks on 486 * the file: any attempt to lock a file belong to another zone 487 * will fail, and one can't lock an SMBFS file and then change 488 * zones, as that fails too. 489 * 490 * Returning an error here is the sane thing to do. A 491 * subsequent call to VN_RELE() which translates to a 492 * smbfs_inactive() will clean up state: if the zone of the 493 * vnode's origin is still alive and kicking, an async worker 494 * thread will handle the request (from the correct zone), and 495 * everything (minus the final smbfs_getattr_otw() call) should 496 * be OK. If the zone is going away smbfs_async_inactive() will 497 * throw away cached pages inline. 498 */ 499 return (EIO); 500 } 501 502 /* 503 * If we are using local locking for this filesystem, then 504 * release all of the SYSV style record locks. Otherwise, 505 * we are doing network locking and we need to release all 506 * of the network locks. All of the locks held by this 507 * process on this file are released no matter what the 508 * incoming reference count is. 509 */ 510 if (smi->smi_flags & SMI_LLOCK) { 511 pid_t pid = ddi_get_pid(); 512 cleanlocks(vp, pid, 0); 513 cleanshares(vp, pid); 514 } 515 516 /* 517 * This (passed in) count is the ref. count from the 518 * user's file_t before the closef call (fio.c). 519 * We only care when the reference goes away. 520 */ 521 if (count > 1) 522 return (0); 523 524 /* 525 * Decrement the reference count for the FID 526 * and possibly do the OtW close. 527 * 528 * Exclusive lock for modifying n_fid stuff. 529 * Don't want this one ever interruptible. 530 */ 531 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 532 smb_credinit(&scred, cr); 533 534 /* 535 * If FID ref. count is 1 and count of mmaped pages isn't 0, 536 * we won't call smbfs_rele_fid(), because it will result in the otW close. 537 * The count of mapped pages isn't 0, which means the mapped pages 538 * possibly will be accessed after close(), we should keep the FID valid, 539 * i.e., dont do the otW close. 540 * Dont worry that FID will be leaked, because when the 541 * vnode's count becomes 0, smbfs_inactive() will 542 * help us release FID and eventually do the otW close. 543 */ 544 if (np->n_fidrefs > 1) { 545 smbfs_rele_fid(np, &scred); 546 } else if (np->r_mapcnt == 0) { 547 /* 548 * Before otW close, make sure dirty pages written back. 549 */ 550 if ((flag & FWRITE) && vn_has_cached_data(vp)) { 551 /* smbfs_putapage() will acquire shared lock, so release 552 * exclusive lock temporally. 553 */ 554 smbfs_rw_exit(&np->r_lkserlock); 555 556 (void) smbfs_putpage(vp, (offset_t) 0, 0, B_INVAL | B_ASYNC, cr, ct); 557 558 /* acquire exclusive lock again. */ 559 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 560 } 561 smbfs_rele_fid(np, &scred); 562 } 563 564 smb_credrele(&scred); 565 smbfs_rw_exit(&np->r_lkserlock); 566 567 return (0); 568 } 569 570 /* 571 * Helper for smbfs_close. Decrement the reference count 572 * for an SMB-level file or directory ID, and when the last 573 * reference for the fid goes away, do the OtW close. 574 * Also called in smbfs_inactive (defensive cleanup). 575 */ 576 static void 577 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred) 578 { 579 smb_share_t *ssp; 580 cred_t *oldcr; 581 struct smbfs_fctx *fctx; 582 int error; 583 uint16_t ofid; 584 585 ssp = np->n_mount->smi_share; 586 error = 0; 587 588 /* Make sure we serialize for n_dirseq use. */ 589 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER)); 590 591 /* 592 * Note that vp->v_type may change if a remote node 593 * is deleted and recreated as a different type, and 594 * our getattr may change v_type accordingly. 595 * Now use n_ovtype to keep track of the v_type 596 * we had during open (see comments above). 597 */ 598 switch (np->n_ovtype) { 599 case VDIR: 600 ASSERT(np->n_dirrefs > 0); 601 if (--np->n_dirrefs) 602 return; 603 if ((fctx = np->n_dirseq) != NULL) { 604 np->n_dirseq = NULL; 605 np->n_dirofs = 0; 606 error = smbfs_smb_findclose(fctx, scred); 607 } 608 break; 609 610 case VREG: 611 ASSERT(np->n_fidrefs > 0); 612 if (--np->n_fidrefs) 613 return; 614 if ((ofid = np->n_fid) != SMB_FID_UNUSED) { 615 np->n_fid = SMB_FID_UNUSED; 616 /* After reconnect, n_fid is invalid */ 617 if (np->n_vcgenid == ssp->ss_vcgenid) { 618 error = smbfs_smb_close( 619 ssp, ofid, NULL, scred); 620 } 621 } 622 break; 623 624 default: 625 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype); 626 break; 627 } 628 if (error) { 629 SMBVDEBUG("error %d closing %s\n", 630 error, np->n_rpath); 631 } 632 633 /* Allow next open to use any v_type. */ 634 np->n_ovtype = VNON; 635 636 /* 637 * Other "last close" stuff. 638 */ 639 mutex_enter(&np->r_statelock); 640 if (np->n_flag & NATTRCHANGED) 641 smbfs_attrcache_rm_locked(np); 642 oldcr = np->r_cred; 643 np->r_cred = NULL; 644 mutex_exit(&np->r_statelock); 645 if (oldcr != NULL) 646 crfree(oldcr); 647 } 648 649 /* ARGSUSED */ 650 static int 651 smbfs_read(vnode_t * vp, struct uio * uiop, int ioflag, cred_t * cr, 652 caller_context_t * ct) 653 { 654 struct smb_cred scred; 655 struct vattr va; 656 smbnode_t *np; 657 smbmntinfo_t *smi; 658 smb_share_t *ssp; 659 offset_t endoff; 660 ssize_t past_eof; 661 int error; 662 663 caddr_t base; 664 u_offset_t blk; 665 u_offset_t boff; 666 size_t blen; 667 uint_t flags; 668 669 np = VTOSMB(vp); 670 smi = VTOSMI(vp); 671 ssp = smi->smi_share; 672 673 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 674 return (EIO); 675 676 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 677 return (EIO); 678 679 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER)); 680 681 if (vp->v_type != VREG) 682 return (EISDIR); 683 684 if (uiop->uio_resid == 0) 685 return (0); 686 687 /* 688 * Like NFS3, just check for 63-bit overflow. Our SMB layer takes 689 * care to return EFBIG when it has to fallback to a 32-bit call. 690 */ 691 endoff = uiop->uio_loffset + uiop->uio_resid; 692 if (uiop->uio_loffset < 0 || endoff < 0) 693 return (EINVAL); 694 695 /* get vnode attributes from server */ 696 va.va_mask = AT_SIZE | AT_MTIME; 697 if (error = smbfsgetattr(vp, &va, cr)) 698 return (error); 699 700 /* Update mtime with mtime from server here? */ 701 702 /* if offset is beyond EOF, read nothing */ 703 if (uiop->uio_loffset >= va.va_size) 704 return (0); 705 706 /* 707 * Limit the read to the remaining file size. Do this by temporarily 708 * reducing uio_resid by the amount the lies beyoned the EOF. 709 */ 710 if (endoff > va.va_size) { 711 past_eof = (ssize_t) (endoff - va.va_size); 712 uiop->uio_resid -= past_eof; 713 } else 714 past_eof = 0; 715 716 /* Bypass the VM if vnode is non-cacheable. */ 717 if ((vp->v_flag & VNOCACHE) || 718 ((np->r_flags & RDIRECTIO) && 719 np->r_mapcnt == 0 && 720 !(vn_has_cached_data(vp)))) { 721 722 /* Shared lock for n_fid use in smb_rwuio */ 723 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 724 return (EINTR); 725 smb_credinit(&scred, cr); 726 727 /* After reconnect, n_fid is invalid */ 728 if (np->n_vcgenid != ssp->ss_vcgenid) 729 error = ESTALE; 730 else 731 error = smb_rwuio(ssp, np->n_fid, UIO_READ, 732 uiop, &scred, smb_timo_read); 733 734 smb_credrele(&scred); 735 smbfs_rw_exit(&np->r_lkserlock); 736 737 } else { 738 739 /* Do I/O through segmap. */ 740 do { 741 blk = uiop->uio_loffset & MAXBMASK; 742 boff = uiop->uio_loffset & MAXBOFFSET; 743 blen = MIN(MAXBSIZE - boff, uiop->uio_resid); 744 745 if (vpm_enable) { 746 747 error = vpm_data_copy(vp, blk + boff, blen, uiop, 1, NULL, 0, S_READ); 748 749 } else { 750 751 base = segmap_getmapflt(segkmap, vp, blk + boff, blen, 1, S_READ); 752 753 error = uiomove(base + boff, blen, UIO_READ, uiop); 754 } 755 756 if (!error) { 757 mutex_enter(&np->r_statelock); 758 if ((blen + boff == MAXBSIZE) || (uiop->uio_loffset == np->r_size)) { 759 flags = SM_DONTNEED; 760 } else { 761 flags = 0; 762 } 763 mutex_exit(&np->r_statelock); 764 } else { 765 flags = 0; 766 } 767 if (vpm_enable) { 768 (void) vpm_sync_pages(vp, blk + boff, blen, flags); 769 } else { 770 (void) segmap_release(segkmap, base, flags); 771 } 772 } while (!error && uiop->uio_resid > 0); 773 } 774 775 /* undo adjustment of resid */ 776 uiop->uio_resid += past_eof; 777 778 return (error); 779 } 780 781 /* ARGSUSED */ 782 static int 783 smbfs_write(vnode_t * vp, struct uio * uiop, int ioflag, cred_t * cr, 784 caller_context_t * ct) 785 { 786 struct smb_cred scred; 787 struct vattr va; 788 smbnode_t *np; 789 smbmntinfo_t *smi; 790 smb_share_t *ssp; 791 offset_t endoff, limit; 792 ssize_t past_limit; 793 int error, timo; 794 795 caddr_t base; 796 u_offset_t blk; 797 u_offset_t boff; 798 size_t blen; 799 uint_t flags; 800 801 u_offset_t last_off; 802 size_t last_resid; 803 804 np = VTOSMB(vp); 805 smi = VTOSMI(vp); 806 ssp = smi->smi_share; 807 808 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 809 return (EIO); 810 811 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 812 return (EIO); 813 814 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER)); 815 816 if (vp->v_type != VREG) 817 return (EISDIR); 818 819 if (uiop->uio_resid == 0) 820 return (0); 821 822 /* 823 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC) 824 */ 825 if (ioflag & (FAPPEND | FSYNC)) { 826 if (np->n_flag & NMODIFIED) { 827 smbfs_attrcache_remove(np); 828 /* XXX: smbfs_vinvalbuf? */ 829 } 830 } 831 if (ioflag & FAPPEND) { 832 /* 833 * File size can be changed by another client 834 */ 835 va.va_mask = AT_SIZE; 836 if (error = smbfsgetattr(vp, &va, cr)) 837 return (error); 838 uiop->uio_loffset = va.va_size; 839 } 840 /* 841 * Like NFS3, just check for 63-bit overflow. 842 */ 843 endoff = uiop->uio_loffset + uiop->uio_resid; 844 if (uiop->uio_loffset < 0 || endoff < 0) 845 return (EINVAL); 846 847 /* 848 * Check to make sure that the process will not exceed its limit on 849 * file size. It is okay to write up to the limit, but not beyond. 850 * Thus, the write which reaches the limit will be short and the next 851 * write will return an error. 852 * 853 * So if we're starting at or beyond the limit, EFBIG. Otherwise, 854 * temporarily reduce resid to the amount the falls after the limit. 855 */ 856 limit = uiop->uio_llimit; 857 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) 858 limit = MAXOFFSET_T; 859 if (uiop->uio_loffset >= limit) 860 return (EFBIG); 861 if (endoff > limit) { 862 past_limit = (ssize_t) (endoff - limit); 863 uiop->uio_resid -= past_limit; 864 } else 865 past_limit = 0; 866 867 /* Bypass the VM if vnode is non-cacheable. */ 868 if ((vp->v_flag & VNOCACHE) || 869 ((np->r_flags & RDIRECTIO) && 870 np->r_mapcnt == 0 && 871 !(vn_has_cached_data(vp)))) { 872 873 /* Timeout: longer for append. */ 874 timo = smb_timo_write; 875 if (endoff > np->r_size) 876 timo = smb_timo_append; 877 878 /* Shared lock for n_fid use in smb_rwuio */ 879 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 880 return (EINTR); 881 smb_credinit(&scred, cr); 882 883 /* After reconnect, n_fid is invalid */ 884 if (np->n_vcgenid != ssp->ss_vcgenid) 885 error = ESTALE; 886 else 887 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE, 888 uiop, &scred, timo); 889 890 if (error == 0) { 891 mutex_enter(&np->r_statelock); 892 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 893 if (uiop->uio_loffset > (offset_t) np->r_size) 894 np->r_size = (len_t) uiop->uio_loffset; 895 mutex_exit(&np->r_statelock); 896 if (ioflag & (FSYNC | FDSYNC)) { 897 /* Don't error the I/O if this fails. */ 898 (void) smbfs_smb_flush(np, &scred); 899 } 900 } 901 smb_credrele(&scred); 902 smbfs_rw_exit(&np->r_lkserlock); 903 904 } else { 905 906 /* Do I/O through segmap. */ 907 size_t bsize = vp->v_vfsp->vfs_bsize; 908 909 do { 910 blk = uiop->uio_loffset & MAXBMASK; 911 boff = uiop->uio_loffset & MAXBOFFSET; 912 blen = MIN(MAXBSIZE - boff, uiop->uio_resid); 913 914 last_off = uiop->uio_loffset; 915 last_resid = uiop->uio_resid; 916 917 uio_prefaultpages((ssize_t) blen, uiop); 918 919 if (vpm_enable) { 920 921 error = writenp(np, NULL, blen, uiop, 0); 922 923 } else { 924 925 if (segmap_kpm) { 926 u_offset_t poff = uiop->uio_loffset & PAGEOFFSET; 927 size_t plen = MIN(PAGESIZE - poff, uiop->uio_resid); 928 929 int pagecreate; 930 931 mutex_enter(&np->r_statelock); 932 pagecreate = (poff == 0) && 933 ((plen == PAGESIZE) || 934 (uiop->uio_loffset + plen >= np->r_size)); 935 mutex_exit(&np->r_statelock); 936 937 base = segmap_getmapflt(segkmap, vp, blk + boff, plen, !pagecreate, S_WRITE); 938 error = writenp(np, base + poff, blen, uiop, pagecreate); 939 940 } else { 941 base = segmap_getmapflt(segkmap, vp, blk + boff, blen, 0, S_READ); 942 error = writenp(np, base + boff, blen, uiop, 0); 943 } 944 } 945 946 if (!error) { 947 if (uiop->uio_loffset % bsize == 0) { 948 flags = SM_WRITE | SM_DONTNEED; 949 } else { 950 flags = 0; 951 } 952 953 if (ioflag & (FSYNC | FDSYNC)) { 954 flags &= ~SM_ASYNC; 955 flags |= SM_WRITE; 956 } 957 if (vpm_enable) { 958 error = vpm_sync_pages(vp, blk, blen, flags); 959 } else { 960 error = segmap_release(segkmap, base, flags); 961 } 962 } else { 963 if (vpm_enable) { 964 (void) vpm_sync_pages(vp, blk, blen, 0); 965 } else { 966 (void) segmap_release(segkmap, base, 0); 967 } 968 } 969 } while (!error && uiop->uio_resid > 0); 970 } 971 972 /* undo adjustment of resid */ 973 if (error) { 974 uiop->uio_resid = last_resid + past_limit; 975 uiop->uio_loffset = last_off; 976 } else { 977 uiop->uio_resid += past_limit; 978 } 979 980 return (error); 981 } 982 983 /* correspond to writerp() in nfs_client.c */ 984 static int 985 writenp(smbnode_t * np, caddr_t base, int tcount, struct uio * uiop, int pgcreated) 986 { 987 int pagecreate; 988 int n; 989 int saved_n; 990 caddr_t saved_base; 991 u_offset_t offset; 992 int error; 993 int sm_error; 994 995 vnode_t *vp = SMBTOV(np); 996 997 ASSERT(tcount <= MAXBSIZE && tcount <= uiop->uio_resid); 998 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER)); 999 if (!vpm_enable) { 1000 ASSERT(((uintptr_t) base & MAXBOFFSET) + tcount <= MAXBSIZE); 1001 } 1002 /* 1003 * Move bytes in at most PAGESIZE chunks. We must avoid spanning 1004 * pages in uiomove() because page faults may cause the cache to be 1005 * invalidated out from under us. The r_size is not updated until 1006 * after the uiomove. If we push the last page of a file before 1007 * r_size is correct, we will lose the data written past the current 1008 * (and invalid) r_size. 1009 */ 1010 do { 1011 offset = uiop->uio_loffset; 1012 pagecreate = 0; 1013 1014 /* 1015 * n is the number of bytes required to satisfy the request 1016 * or the number of bytes to fill out the page. 1017 */ 1018 n = (int) MIN((PAGESIZE - (offset & PAGEOFFSET)), tcount); 1019 1020 /* 1021 * Check to see if we can skip reading in the page and just 1022 * allocate the memory. We can do this if we are going to 1023 * rewrite the entire mapping or if we are going to write to 1024 * or beyond the current end of file from the beginning of 1025 * the mapping. 1026 * 1027 * The read of r_size is now protected by r_statelock. 1028 */ 1029 mutex_enter(&np->r_statelock); 1030 /* 1031 * When pgcreated is nonzero the caller has already done a 1032 * segmap_getmapflt with forcefault 0 and S_WRITE. With 1033 * segkpm this means we already have at least one page 1034 * created and mapped at base. 1035 */ 1036 pagecreate = pgcreated || 1037 ((offset & PAGEOFFSET) == 0 && 1038 (n == PAGESIZE || ((offset + n) >= np->r_size))); 1039 1040 mutex_exit(&np->r_statelock); 1041 1042 if (!vpm_enable && pagecreate) { 1043 /* 1044 * The last argument tells segmap_pagecreate() to 1045 * always lock the page, as opposed to sometimes 1046 * returning with the page locked. This way we avoid 1047 * a fault on the ensuing uiomove(), but also more 1048 * importantly (to fix bug 1094402) we can call 1049 * segmap_fault() to unlock the page in all cases. An 1050 * alternative would be to modify segmap_pagecreate() 1051 * to tell us when it is locking a page, but that's a 1052 * fairly major interface change. 1053 */ 1054 if (pgcreated == 0) 1055 (void) segmap_pagecreate(segkmap, base, 1056 (uint_t) n, 1); 1057 saved_base = base; 1058 saved_n = n; 1059 } 1060 /* 1061 * The number of bytes of data in the last page can not be 1062 * accurately be determined while page is being uiomove'd to 1063 * and the size of the file being updated. Thus, inform 1064 * threads which need to know accurately how much data is in 1065 * the last page of the file. They will not do the i/o 1066 * immediately, but will arrange for the i/o to happen later 1067 * when this modify operation will have finished. 1068 */ 1069 ASSERT(!(np->r_flags & RMODINPROGRESS)); 1070 mutex_enter(&np->r_statelock); 1071 np->r_flags |= RMODINPROGRESS; 1072 np->r_modaddr = (offset & MAXBMASK); 1073 mutex_exit(&np->r_statelock); 1074 1075 if (vpm_enable) { 1076 /* 1077 * Copy data. If new pages are created, part of the 1078 * page that is not written will be initizliazed with 1079 * zeros. 1080 */ 1081 error = vpm_data_copy(vp, offset, n, uiop, 1082 !pagecreate, NULL, 0, S_WRITE); 1083 } else { 1084 error = uiomove(base, n, UIO_WRITE, uiop); 1085 } 1086 1087 /* 1088 * r_size is the maximum number of bytes known to be in the 1089 * file. Make sure it is at least as high as the first 1090 * unwritten byte pointed to by uio_loffset. 1091 */ 1092 mutex_enter(&np->r_statelock); 1093 if (np->r_size < uiop->uio_loffset) 1094 np->r_size = uiop->uio_loffset; 1095 np->r_flags &= ~RMODINPROGRESS; 1096 np->r_flags |= RDIRTY; 1097 mutex_exit(&np->r_statelock); 1098 1099 /* n = # of bytes written */ 1100 n = (int) (uiop->uio_loffset - offset); 1101 1102 if (!vpm_enable) { 1103 base += n; 1104 } 1105 tcount -= n; 1106 /* 1107 * If we created pages w/o initializing them completely, we 1108 * need to zero the part that wasn't set up. This happens on 1109 * a most EOF write cases and if we had some sort of error 1110 * during the uiomove. 1111 */ 1112 if (!vpm_enable && pagecreate) { 1113 if ((uiop->uio_loffset & PAGEOFFSET) || n == 0) 1114 (void) kzero(base, PAGESIZE - n); 1115 1116 if (pgcreated) { 1117 /* 1118 * Caller is responsible for this page, it 1119 * was not created in this loop. 1120 */ 1121 pgcreated = 0; 1122 } else { 1123 /* 1124 * For bug 1094402: segmap_pagecreate locks 1125 * page. Unlock it. This also unlocks the 1126 * pages allocated by page_create_va() in 1127 * segmap_pagecreate(). 1128 */ 1129 sm_error = segmap_fault(kas.a_hat, segkmap, 1130 saved_base, saved_n, 1131 F_SOFTUNLOCK, S_WRITE); 1132 if (error == 0) 1133 error = sm_error; 1134 } 1135 } 1136 } while (tcount > 0 && error == 0); 1137 1138 return (error); 1139 } 1140 1141 /* ARGSUSED */ 1142 static int 1143 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, 1144 cred_t *cr, int *rvalp, caller_context_t *ct) 1145 { 1146 int error; 1147 smbmntinfo_t *smi; 1148 1149 smi = VTOSMI(vp); 1150 1151 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1152 return (EIO); 1153 1154 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 1155 return (EIO); 1156 1157 switch (cmd) { 1158 /* First three from ZFS. XXX - need these? */ 1159 1160 case _FIOFFS: 1161 error = smbfs_fsync(vp, 0, cr, ct); 1162 break; 1163 1164 /* 1165 * The following two ioctls are used by bfu. 1166 * Silently ignore to avoid bfu errors. 1167 */ 1168 case _FIOGDIO: 1169 case _FIOSDIO: 1170 error = 0; 1171 break; 1172 1173 #ifdef NOT_YET /* XXX - from the NFS code. */ 1174 case _FIODIRECTIO: 1175 error = smbfs_directio(vp, (int)arg, cr); 1176 #endif 1177 1178 /* 1179 * Allow get/set with "raw" security descriptor (SD) data. 1180 * Useful for testing, diagnosing idmap problems, etc. 1181 */ 1182 case SMBFSIO_GETSD: 1183 error = smbfs_acl_iocget(vp, arg, flag, cr); 1184 break; 1185 1186 case SMBFSIO_SETSD: 1187 error = smbfs_acl_iocset(vp, arg, flag, cr); 1188 break; 1189 1190 default: 1191 error = ENOTTY; 1192 break; 1193 } 1194 1195 return (error); 1196 } 1197 1198 1199 /* 1200 * Return either cached or remote attributes. If get remote attr 1201 * use them to check and invalidate caches, then cache the new attributes. 1202 * 1203 * XXX 1204 * This op should eventually support PSARC 2007/315, Extensible Attribute 1205 * Interfaces, for richer metadata. 1206 */ 1207 /* ARGSUSED */ 1208 static int 1209 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 1210 caller_context_t *ct) 1211 { 1212 smbnode_t *np; 1213 smbmntinfo_t *smi; 1214 1215 smi = VTOSMI(vp); 1216 1217 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1218 return (EIO); 1219 1220 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 1221 return (EIO); 1222 1223 /* 1224 * If it has been specified that the return value will 1225 * just be used as a hint, and we are only being asked 1226 * for size, fsid or rdevid, then return the client's 1227 * notion of these values without checking to make sure 1228 * that the attribute cache is up to date. 1229 * The whole point is to avoid an over the wire GETATTR 1230 * call. 1231 */ 1232 np = VTOSMB(vp); 1233 if (flags & ATTR_HINT) { 1234 if (vap->va_mask == 1235 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) { 1236 mutex_enter(&np->r_statelock); 1237 if (vap->va_mask | AT_SIZE) 1238 vap->va_size = np->r_size; 1239 if (vap->va_mask | AT_FSID) 1240 vap->va_fsid = vp->v_vfsp->vfs_dev; 1241 if (vap->va_mask | AT_RDEV) 1242 vap->va_rdev = vp->v_rdev; 1243 mutex_exit(&np->r_statelock); 1244 return (0); 1245 } 1246 } 1247 1248 return (smbfsgetattr(vp, vap, cr)); 1249 } 1250 1251 /* smbfsgetattr() in smbfs_client.c */ 1252 1253 /* 1254 * XXX 1255 * This op should eventually support PSARC 2007/315, Extensible Attribute 1256 * Interfaces, for richer metadata. 1257 */ 1258 /*ARGSUSED4*/ 1259 static int 1260 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 1261 caller_context_t *ct) 1262 { 1263 vfs_t *vfsp; 1264 smbmntinfo_t *smi; 1265 int error; 1266 uint_t mask; 1267 struct vattr oldva; 1268 1269 vfsp = vp->v_vfsp; 1270 smi = VFTOSMI(vfsp); 1271 1272 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1273 return (EIO); 1274 1275 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1276 return (EIO); 1277 1278 mask = vap->va_mask; 1279 if (mask & AT_NOSET) 1280 return (EINVAL); 1281 1282 if (vfsp->vfs_flag & VFS_RDONLY) 1283 return (EROFS); 1284 1285 /* 1286 * This is a _local_ access check so that only the owner of 1287 * this mount can set attributes. With ACLs enabled, the 1288 * file owner can be different from the mount owner, and we 1289 * need to check the _mount_ owner here. See _access_rwx 1290 */ 1291 bzero(&oldva, sizeof (oldva)); 1292 oldva.va_mask = AT_TYPE | AT_MODE; 1293 error = smbfsgetattr(vp, &oldva, cr); 1294 if (error) 1295 return (error); 1296 oldva.va_mask |= AT_UID | AT_GID; 1297 oldva.va_uid = smi->smi_uid; 1298 oldva.va_gid = smi->smi_gid; 1299 1300 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 1301 smbfs_accessx, vp); 1302 if (error) 1303 return (error); 1304 1305 if (mask & (AT_UID | AT_GID)) { 1306 if (smi->smi_flags & SMI_ACL) 1307 error = smbfs_acl_setids(vp, vap, cr); 1308 else 1309 error = ENOSYS; 1310 if (error != 0) { 1311 SMBVDEBUG("error %d seting UID/GID on %s", 1312 error, VTOSMB(vp)->n_rpath); 1313 /* 1314 * It might be more correct to return the 1315 * error here, but that causes complaints 1316 * when root extracts a cpio archive, etc. 1317 * So ignore this error, and go ahead with 1318 * the rest of the setattr work. 1319 */ 1320 } 1321 } 1322 1323 return (smbfssetattr(vp, vap, flags, cr)); 1324 } 1325 1326 /* 1327 * Mostly from Darwin smbfs_setattr() 1328 * but then modified a lot. 1329 */ 1330 /* ARGSUSED */ 1331 static int 1332 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) 1333 { 1334 int error = 0; 1335 smbnode_t *np = VTOSMB(vp); 1336 uint_t mask = vap->va_mask; 1337 struct timespec *mtime, *atime; 1338 struct smb_cred scred; 1339 int cerror, modified = 0; 1340 unsigned short fid; 1341 int have_fid = 0; 1342 uint32_t rights = 0; 1343 1344 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone); 1345 1346 /* 1347 * There are no settable attributes on the XATTR dir, 1348 * so just silently ignore these. On XATTR files, 1349 * you can set the size but nothing else. 1350 */ 1351 if (vp->v_flag & V_XATTRDIR) 1352 return (0); 1353 if (np->n_flag & N_XATTR) { 1354 if (mask & AT_TIMES) 1355 SMBVDEBUG("ignore set time on xattr\n"); 1356 mask &= AT_SIZE; 1357 } 1358 1359 /* 1360 * If our caller is trying to set multiple attributes, they 1361 * can make no assumption about what order they are done in. 1362 * Here we try to do them in order of decreasing likelihood 1363 * of failure, just to minimize the chance we'll wind up 1364 * with a partially complete request. 1365 */ 1366 1367 /* Shared lock for (possible) n_fid use. */ 1368 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1369 return (EINTR); 1370 smb_credinit(&scred, cr); 1371 1372 /* 1373 * Will we need an open handle for this setattr? 1374 * If so, what rights will we need? 1375 */ 1376 if (mask & (AT_ATIME | AT_MTIME)) { 1377 rights |= 1378 SA_RIGHT_FILE_WRITE_ATTRIBUTES; 1379 } 1380 if (mask & AT_SIZE) { 1381 rights |= 1382 SA_RIGHT_FILE_WRITE_DATA | 1383 SA_RIGHT_FILE_APPEND_DATA; 1384 } 1385 1386 /* 1387 * Only SIZE really requires a handle, but it's 1388 * simpler and more reliable to set via a handle. 1389 * Some servers like NT4 won't set times by path. 1390 * Also, we're usually setting everything anyway. 1391 */ 1392 if (mask & (AT_SIZE | AT_ATIME | AT_MTIME)) { 1393 error = smbfs_smb_tmpopen(np, rights, &scred, &fid); 1394 if (error) { 1395 SMBVDEBUG("error %d opening %s\n", 1396 error, np->n_rpath); 1397 goto out; 1398 } 1399 have_fid = 1; 1400 } 1401 1402 /* 1403 * If the server supports the UNIX extensions, right here is where 1404 * we'd support changes to uid, gid, mode, and possibly va_flags. 1405 * For now we claim to have made any such changes. 1406 */ 1407 1408 if (mask & AT_SIZE) { 1409 /* 1410 * If the new file size is less than what the client sees as 1411 * the file size, then just change the size and invalidate 1412 * the pages. 1413 * I am commenting this code at present because the function 1414 * smbfs_putapage() is not yet implemented. 1415 */ 1416 1417 /* 1418 * Set the file size to vap->va_size. 1419 */ 1420 ASSERT(have_fid); 1421 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred); 1422 if (error) { 1423 SMBVDEBUG("setsize error %d file %s\n", 1424 error, np->n_rpath); 1425 } else { 1426 /* 1427 * Darwin had code here to zero-extend. 1428 * Tests indicate the server will zero-fill, 1429 * so looks like we don't need to do this. 1430 * Good thing, as this could take forever. 1431 * 1432 * XXX: Reportedly, writing one byte of zero 1433 * at the end offset avoids problems here. 1434 */ 1435 mutex_enter(&np->r_statelock); 1436 np->r_size = vap->va_size; 1437 mutex_exit(&np->r_statelock); 1438 modified = 1; 1439 } 1440 } 1441 1442 /* 1443 * XXX: When Solaris has create_time, set that too. 1444 * Note: create_time is different from ctime. 1445 */ 1446 mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0); 1447 atime = ((mask & AT_ATIME) ? &vap->va_atime : 0); 1448 1449 if (mtime || atime) { 1450 /* 1451 * Always use the handle-based set attr call now. 1452 * Not trying to set DOS attributes here so pass zero. 1453 */ 1454 ASSERT(have_fid); 1455 error = smbfs_smb_setfattr(np, fid, 1456 0, mtime, atime, &scred); 1457 if (error) { 1458 SMBVDEBUG("set times error %d file %s\n", 1459 error, np->n_rpath); 1460 } else { 1461 modified = 1; 1462 } 1463 } 1464 1465 out: 1466 if (modified) { 1467 /* 1468 * Invalidate attribute cache in case the server 1469 * doesn't set exactly the attributes we asked. 1470 */ 1471 smbfs_attrcache_remove(np); 1472 } 1473 1474 if (have_fid) { 1475 cerror = smbfs_smb_tmpclose(np, fid, &scred); 1476 if (cerror) 1477 SMBVDEBUG("error %d closing %s\n", 1478 cerror, np->n_rpath); 1479 } 1480 1481 smb_credrele(&scred); 1482 smbfs_rw_exit(&np->r_lkserlock); 1483 1484 return (error); 1485 } 1486 1487 /* 1488 * smbfs_access_rwx() 1489 * Common function for smbfs_access, etc. 1490 * 1491 * The security model implemented by the FS is unusual 1492 * due to the current "single user mounts" restriction: 1493 * All access under a given mount point uses the CIFS 1494 * credentials established by the owner of the mount. 1495 * 1496 * Most access checking is handled by the CIFS server, 1497 * but we need sufficient Unix access checks here to 1498 * prevent other local Unix users from having access 1499 * to objects under this mount that the uid/gid/mode 1500 * settings in the mount would not allow. 1501 * 1502 * With this model, there is a case where we need the 1503 * ability to do an access check before we have the 1504 * vnode for an object. This function takes advantage 1505 * of the fact that the uid/gid/mode is per mount, and 1506 * avoids the need for a vnode. 1507 * 1508 * We still (sort of) need a vnode when we call 1509 * secpolicy_vnode_access, but that only uses 1510 * the vtype field, so we can use a pair of fake 1511 * vnodes that have only v_type filled in. 1512 * 1513 * XXX: Later, add a new secpolicy_vtype_access() 1514 * that takes the vtype instead of a vnode, and 1515 * get rid of the tmpl_vxxx fake vnodes below. 1516 */ 1517 static int 1518 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr) 1519 { 1520 /* See the secpolicy call below. */ 1521 static const vnode_t tmpl_vdir = { .v_type = VDIR }; 1522 static const vnode_t tmpl_vreg = { .v_type = VREG }; 1523 vattr_t va; 1524 vnode_t *tvp; 1525 struct smbmntinfo *smi = VFTOSMI(vfsp); 1526 int shift = 0; 1527 1528 /* 1529 * Build our (fabricated) vnode attributes. 1530 * XXX: Could make these templates in the 1531 * per-mount struct and use them here. 1532 */ 1533 bzero(&va, sizeof (va)); 1534 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 1535 va.va_type = vtype; 1536 va.va_mode = (vtype == VDIR) ? 1537 smi->smi_dmode : smi->smi_fmode; 1538 va.va_uid = smi->smi_uid; 1539 va.va_gid = smi->smi_gid; 1540 1541 /* 1542 * Disallow write attempts on read-only file systems, 1543 * unless the file is a device or fifo node. Note: 1544 * Inline vn_is_readonly and IS_DEVVP here because 1545 * we may not have a vnode ptr. Original expr. was: 1546 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp)) 1547 */ 1548 if ((mode & VWRITE) && 1549 (vfsp->vfs_flag & VFS_RDONLY) && 1550 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO)) 1551 return (EROFS); 1552 1553 /* 1554 * Disallow attempts to access mandatory lock files. 1555 * Similarly, expand MANDLOCK here. 1556 * XXX: not sure we need this. 1557 */ 1558 if ((mode & (VWRITE | VREAD | VEXEC)) && 1559 va.va_type == VREG && MANDMODE(va.va_mode)) 1560 return (EACCES); 1561 1562 /* 1563 * Access check is based on only 1564 * one of owner, group, public. 1565 * If not owner, then check group. 1566 * If not a member of the group, 1567 * then check public access. 1568 */ 1569 if (crgetuid(cr) != va.va_uid) { 1570 shift += 3; 1571 if (!groupmember(va.va_gid, cr)) 1572 shift += 3; 1573 } 1574 1575 /* 1576 * We need a vnode for secpolicy_vnode_access, 1577 * but the only thing it looks at is v_type, 1578 * so pass one of the templates above. 1579 */ 1580 tvp = (va.va_type == VDIR) ? 1581 (vnode_t *)&tmpl_vdir : 1582 (vnode_t *)&tmpl_vreg; 1583 1584 return (secpolicy_vnode_access2(cr, tvp, va.va_uid, 1585 va.va_mode << shift, mode)); 1586 } 1587 1588 /* 1589 * See smbfs_setattr 1590 */ 1591 static int 1592 smbfs_accessx(void *arg, int mode, cred_t *cr) 1593 { 1594 vnode_t *vp = arg; 1595 /* 1596 * Note: The caller has checked the current zone, 1597 * the SMI_DEAD and VFS_UNMOUNTED flags, etc. 1598 */ 1599 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr)); 1600 } 1601 1602 /* 1603 * XXX 1604 * This op should support PSARC 2007/403, Modified Access Checks for CIFS 1605 */ 1606 /* ARGSUSED */ 1607 static int 1608 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct) 1609 { 1610 vfs_t *vfsp; 1611 smbmntinfo_t *smi; 1612 1613 vfsp = vp->v_vfsp; 1614 smi = VFTOSMI(vfsp); 1615 1616 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1617 return (EIO); 1618 1619 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1620 return (EIO); 1621 1622 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr)); 1623 } 1624 1625 1626 /* 1627 * Flush local dirty pages to stable storage on the server. 1628 * 1629 * If FNODSYNC is specified, then there is nothing to do because 1630 * metadata changes are not cached on the client before being 1631 * sent to the server. 1632 */ 1633 /* ARGSUSED */ 1634 static int 1635 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) 1636 { 1637 int error = 0; 1638 smbmntinfo_t *smi; 1639 smbnode_t *np; 1640 struct smb_cred scred; 1641 1642 np = VTOSMB(vp); 1643 smi = VTOSMI(vp); 1644 1645 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1646 return (EIO); 1647 1648 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 1649 return (EIO); 1650 1651 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp)) 1652 return (0); 1653 1654 if ((syncflag & (FSYNC|FDSYNC)) == 0) 1655 return (0); 1656 1657 /* Shared lock for n_fid use in _flush */ 1658 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1659 return (EINTR); 1660 smb_credinit(&scred, cr); 1661 1662 error = smbfs_smb_flush(np, &scred); 1663 1664 smb_credrele(&scred); 1665 smbfs_rw_exit(&np->r_lkserlock); 1666 1667 return (error); 1668 } 1669 1670 /* 1671 * Last reference to vnode went away. 1672 */ 1673 /* ARGSUSED */ 1674 static void 1675 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 1676 { 1677 smbnode_t *np; 1678 struct smb_cred scred; 1679 1680 /* 1681 * Don't "bail out" for VFS_UNMOUNTED here, 1682 * as we want to do cleanup, etc. 1683 * See also pcfs_inactive 1684 */ 1685 1686 np = VTOSMB(vp); 1687 1688 /* 1689 * If this is coming from the wrong zone, we let someone in the right 1690 * zone take care of it asynchronously. We can get here due to 1691 * VN_RELE() being called from pageout() or fsflush(). This call may 1692 * potentially turn into an expensive no-op if, for instance, v_count 1693 * gets incremented in the meantime, but it's still correct. 1694 */ 1695 1696 /* 1697 * Defend against the possibility that higher-level callers 1698 * might not correctly balance open and close calls. If we 1699 * get here with open references remaining, it means there 1700 * was a missing VOP_CLOSE somewhere. If that happens, do 1701 * the close here so we don't "leak" FIDs on the server. 1702 * 1703 * Exclusive lock for modifying n_fid stuff. 1704 * Don't want this one ever interruptible. 1705 */ 1706 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 1707 smb_credinit(&scred, cr); 1708 1709 switch (np->n_ovtype) { 1710 case VNON: 1711 /* not open (OK) */ 1712 break; 1713 1714 case VDIR: 1715 if (np->n_dirrefs == 0) 1716 break; 1717 SMBVDEBUG("open dir: refs %d path %s\n", 1718 np->n_dirrefs, np->n_rpath); 1719 /* Force last close. */ 1720 np->n_dirrefs = 1; 1721 smbfs_rele_fid(np, &scred); 1722 break; 1723 1724 case VREG: 1725 if (np->n_fidrefs == 0) 1726 break; 1727 SMBVDEBUG("open file: refs %d id 0x%x path %s\n", 1728 np->n_fidrefs, np->n_fid, np->n_rpath); 1729 /* 1730 * Before otW close, make sure dirty pages written back. 1731 */ 1732 if (vn_has_cached_data(vp)) { 1733 /* smbfs_putapage() will acquire shared lock, so release 1734 * exclusive lock temporally. 1735 */ 1736 smbfs_rw_exit(&np->r_lkserlock); 1737 1738 (void) smbfs_putpage(vp, (offset_t) 0, 0, B_INVAL | B_ASYNC, cr, ct); 1739 1740 /* acquire exclusive lock again. */ 1741 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 1742 } 1743 /* Force last close. */ 1744 np->n_fidrefs = 1; 1745 smbfs_rele_fid(np, &scred); 1746 break; 1747 1748 default: 1749 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype); 1750 np->n_ovtype = VNON; 1751 break; 1752 } 1753 1754 smb_credrele(&scred); 1755 smbfs_rw_exit(&np->r_lkserlock); 1756 1757 smbfs_addfree(np); 1758 } 1759 1760 /* 1761 * Remote file system operations having to do with directory manipulation. 1762 */ 1763 /* ARGSUSED */ 1764 static int 1765 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, 1766 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, 1767 int *direntflags, pathname_t *realpnp) 1768 { 1769 vfs_t *vfs; 1770 smbmntinfo_t *smi; 1771 smbnode_t *dnp; 1772 int error; 1773 1774 vfs = dvp->v_vfsp; 1775 smi = VFTOSMI(vfs); 1776 1777 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1778 return (EPERM); 1779 1780 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED) 1781 return (EIO); 1782 1783 dnp = VTOSMB(dvp); 1784 1785 /* 1786 * Are we looking up extended attributes? If so, "dvp" is 1787 * the file or directory for which we want attributes, and 1788 * we need a lookup of the (faked up) attribute directory 1789 * before we lookup the rest of the path. 1790 */ 1791 if (flags & LOOKUP_XATTR) { 1792 /* 1793 * Require the xattr mount option. 1794 */ 1795 if ((vfs->vfs_flag & VFS_XATTR) == 0) 1796 return (EINVAL); 1797 1798 error = smbfs_get_xattrdir(dvp, vpp, cr, flags); 1799 return (error); 1800 } 1801 1802 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp))) 1803 return (EINTR); 1804 1805 error = smbfslookup(dvp, nm, vpp, cr, 1, ct); 1806 1807 smbfs_rw_exit(&dnp->r_rwlock); 1808 1809 return (error); 1810 } 1811 1812 /* ARGSUSED */ 1813 static int 1814 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, 1815 int cache_ok, caller_context_t *ct) 1816 { 1817 int error; 1818 int supplen; /* supported length */ 1819 vnode_t *vp; 1820 smbnode_t *np; 1821 smbnode_t *dnp; 1822 smbmntinfo_t *smi; 1823 /* struct smb_vc *vcp; */ 1824 const char *ill; 1825 const char *name = (const char *)nm; 1826 int nmlen = strlen(nm); 1827 int rplen; 1828 struct smb_cred scred; 1829 struct smbfattr fa; 1830 1831 smi = VTOSMI(dvp); 1832 dnp = VTOSMB(dvp); 1833 1834 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone); 1835 1836 #ifdef NOT_YET 1837 vcp = SSTOVC(smi->smi_share); 1838 1839 /* XXX: Should compute this once and store it in smbmntinfo_t */ 1840 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12; 1841 #else 1842 supplen = 255; 1843 #endif 1844 1845 /* 1846 * RWlock must be held, either reader or writer. 1847 * XXX: Can we check without looking directly 1848 * inside the struct smbfs_rwlock_t? 1849 */ 1850 ASSERT(dnp->r_rwlock.count != 0); 1851 1852 /* 1853 * If lookup is for "", just return dvp. 1854 * No need to perform any access checks. 1855 */ 1856 if (nmlen == 0) { 1857 VN_HOLD(dvp); 1858 *vpp = dvp; 1859 return (0); 1860 } 1861 1862 /* 1863 * Can't do lookups in non-directories. 1864 */ 1865 if (dvp->v_type != VDIR) 1866 return (ENOTDIR); 1867 1868 /* 1869 * Need search permission in the directory. 1870 */ 1871 error = smbfs_access(dvp, VEXEC, 0, cr, ct); 1872 if (error) 1873 return (error); 1874 1875 /* 1876 * If lookup is for ".", just return dvp. 1877 * Access check was done above. 1878 */ 1879 if (nmlen == 1 && name[0] == '.') { 1880 VN_HOLD(dvp); 1881 *vpp = dvp; 1882 return (0); 1883 } 1884 1885 /* 1886 * Now some sanity checks on the name. 1887 * First check the length. 1888 */ 1889 if (nmlen > supplen) 1890 return (ENAMETOOLONG); 1891 1892 /* 1893 * Avoid surprises with characters that are 1894 * illegal in Windows file names. 1895 * Todo: CATIA mappings XXX 1896 */ 1897 ill = illegal_chars; 1898 if (dnp->n_flag & N_XATTR) 1899 ill++; /* allow colon */ 1900 if (strpbrk(nm, ill)) 1901 return (EINVAL); 1902 1903 /* 1904 * Special handling for lookup of ".." 1905 * 1906 * We keep full pathnames (as seen on the server) 1907 * so we can just trim off the last component to 1908 * get the full pathname of the parent. Note: 1909 * We don't actually copy and modify, but just 1910 * compute the trimmed length and pass that with 1911 * the current dir path (not null terminated). 1912 * 1913 * We don't go over-the-wire to get attributes 1914 * for ".." because we know it's a directory, 1915 * and we can just leave the rest "stale" 1916 * until someone does a getattr. 1917 */ 1918 if (nmlen == 2 && name[0] == '.' && name[1] == '.') { 1919 if (dvp->v_flag & VROOT) { 1920 /* 1921 * Already at the root. This can happen 1922 * with directory listings at the root, 1923 * which lookup "." and ".." to get the 1924 * inode numbers. Let ".." be the same 1925 * as "." in the FS root. 1926 */ 1927 VN_HOLD(dvp); 1928 *vpp = dvp; 1929 return (0); 1930 } 1931 1932 /* 1933 * Special case for XATTR directory 1934 */ 1935 if (dvp->v_flag & V_XATTRDIR) { 1936 error = smbfs_xa_parent(dvp, vpp); 1937 return (error); 1938 } 1939 1940 /* 1941 * Find the parent path length. 1942 */ 1943 rplen = dnp->n_rplen; 1944 ASSERT(rplen > 0); 1945 while (--rplen >= 0) { 1946 if (dnp->n_rpath[rplen] == '\\') 1947 break; 1948 } 1949 if (rplen <= 0) { 1950 /* Found our way to the root. */ 1951 vp = SMBTOV(smi->smi_root); 1952 VN_HOLD(vp); 1953 *vpp = vp; 1954 return (0); 1955 } 1956 np = smbfs_node_findcreate(smi, 1957 dnp->n_rpath, rplen, NULL, 0, 0, 1958 &smbfs_fattr0); /* force create */ 1959 ASSERT(np != NULL); 1960 vp = SMBTOV(np); 1961 vp->v_type = VDIR; 1962 1963 /* Success! */ 1964 *vpp = vp; 1965 return (0); 1966 } 1967 1968 /* 1969 * Normal lookup of a name under this directory. 1970 * Note we handled "", ".", ".." above. 1971 */ 1972 if (cache_ok) { 1973 /* 1974 * The caller indicated that it's OK to use a 1975 * cached result for this lookup, so try to 1976 * reclaim a node from the smbfs node cache. 1977 */ 1978 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr); 1979 if (error) 1980 return (error); 1981 if (vp != NULL) { 1982 /* hold taken in lookup_cache */ 1983 *vpp = vp; 1984 return (0); 1985 } 1986 } 1987 1988 /* 1989 * OK, go over-the-wire to get the attributes, 1990 * then create the node. 1991 */ 1992 smb_credinit(&scred, cr); 1993 /* Note: this can allocate a new "name" */ 1994 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred); 1995 smb_credrele(&scred); 1996 if (error == ENOTDIR) { 1997 /* 1998 * Lookup failed because this directory was 1999 * removed or renamed by another client. 2000 * Remove any cached attributes under it. 2001 */ 2002 smbfs_attrcache_remove(dnp); 2003 smbfs_attrcache_prune(dnp); 2004 } 2005 if (error) 2006 goto out; 2007 2008 error = smbfs_nget(dvp, name, nmlen, &fa, &vp); 2009 if (error) 2010 goto out; 2011 2012 /* Success! */ 2013 *vpp = vp; 2014 2015 out: 2016 /* smbfs_smb_lookup may have allocated name. */ 2017 if (name != nm) 2018 smbfs_name_free(name, nmlen); 2019 2020 return (error); 2021 } 2022 2023 /* 2024 * smbfslookup_cache 2025 * 2026 * Try to reclaim a node from the smbfs node cache. 2027 * Some statistics for DEBUG. 2028 * 2029 * This mechanism lets us avoid many of the five (or more) 2030 * OtW lookup calls per file seen with "ls -l" if we search 2031 * the smbfs node cache for recently inactive(ated) nodes. 2032 */ 2033 #ifdef DEBUG 2034 int smbfs_lookup_cache_calls = 0; 2035 int smbfs_lookup_cache_error = 0; 2036 int smbfs_lookup_cache_miss = 0; 2037 int smbfs_lookup_cache_stale = 0; 2038 int smbfs_lookup_cache_hits = 0; 2039 #endif /* DEBUG */ 2040 2041 /* ARGSUSED */ 2042 static int 2043 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen, 2044 vnode_t **vpp, cred_t *cr) 2045 { 2046 struct vattr va; 2047 smbnode_t *dnp; 2048 smbnode_t *np; 2049 vnode_t *vp; 2050 int error; 2051 char sep; 2052 2053 dnp = VTOSMB(dvp); 2054 *vpp = NULL; 2055 2056 #ifdef DEBUG 2057 smbfs_lookup_cache_calls++; 2058 #endif 2059 2060 /* 2061 * First make sure we can get attributes for the 2062 * directory. Cached attributes are OK here. 2063 * If we removed or renamed the directory, this 2064 * will return ENOENT. If someone else removed 2065 * this directory or file, we'll find out when we 2066 * try to open or get attributes. 2067 */ 2068 va.va_mask = AT_TYPE | AT_MODE; 2069 error = smbfsgetattr(dvp, &va, cr); 2070 if (error) { 2071 #ifdef DEBUG 2072 smbfs_lookup_cache_error++; 2073 #endif 2074 return (error); 2075 } 2076 2077 /* 2078 * Passing NULL smbfattr here so we will 2079 * just look, not create. 2080 */ 2081 sep = SMBFS_DNP_SEP(dnp); 2082 np = smbfs_node_findcreate(dnp->n_mount, 2083 dnp->n_rpath, dnp->n_rplen, 2084 nm, nmlen, sep, NULL); 2085 if (np == NULL) { 2086 #ifdef DEBUG 2087 smbfs_lookup_cache_miss++; 2088 #endif 2089 return (0); 2090 } 2091 2092 /* 2093 * Found it. Attributes still valid? 2094 */ 2095 vp = SMBTOV(np); 2096 if (np->r_attrtime <= gethrtime()) { 2097 /* stale */ 2098 #ifdef DEBUG 2099 smbfs_lookup_cache_stale++; 2100 #endif 2101 VN_RELE(vp); 2102 return (0); 2103 } 2104 2105 /* 2106 * Success! 2107 * Caller gets hold from smbfs_node_findcreate 2108 */ 2109 #ifdef DEBUG 2110 smbfs_lookup_cache_hits++; 2111 #endif 2112 *vpp = vp; 2113 return (0); 2114 } 2115 2116 /* 2117 * XXX 2118 * vsecattr_t is new to build 77, and we need to eventually support 2119 * it in order to create an ACL when an object is created. 2120 * 2121 * This op should support the new FIGNORECASE flag for case-insensitive 2122 * lookups, per PSARC 2007/244. 2123 */ 2124 /* ARGSUSED */ 2125 static int 2126 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, 2127 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct, 2128 vsecattr_t *vsecp) 2129 { 2130 int error; 2131 int cerror; 2132 vfs_t *vfsp; 2133 vnode_t *vp; 2134 #ifdef NOT_YET 2135 smbnode_t *np; 2136 #endif 2137 smbnode_t *dnp; 2138 smbmntinfo_t *smi; 2139 struct vattr vattr; 2140 struct smbfattr fattr; 2141 struct smb_cred scred; 2142 const char *name = (const char *)nm; 2143 int nmlen = strlen(nm); 2144 uint32_t disp; 2145 uint16_t fid; 2146 int xattr; 2147 2148 vfsp = dvp->v_vfsp; 2149 smi = VFTOSMI(vfsp); 2150 dnp = VTOSMB(dvp); 2151 vp = NULL; 2152 2153 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2154 return (EPERM); 2155 2156 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 2157 return (EIO); 2158 2159 /* 2160 * Note: this may break mknod(2) calls to create a directory, 2161 * but that's obscure use. Some other filesystems do this. 2162 * XXX: Later, redirect VDIR type here to _mkdir. 2163 */ 2164 if (va->va_type != VREG) 2165 return (EINVAL); 2166 2167 /* 2168 * If the pathname is "", just use dvp, no checks. 2169 * Do this outside of the rwlock (like zfs). 2170 */ 2171 if (nmlen == 0) { 2172 VN_HOLD(dvp); 2173 *vpp = dvp; 2174 return (0); 2175 } 2176 2177 /* Don't allow "." or ".." through here. */ 2178 if ((nmlen == 1 && name[0] == '.') || 2179 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 2180 return (EISDIR); 2181 2182 /* 2183 * We make a copy of the attributes because the caller does not 2184 * expect us to change what va points to. 2185 */ 2186 vattr = *va; 2187 2188 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2189 return (EINTR); 2190 smb_credinit(&scred, cr); 2191 2192 /* 2193 * XXX: Do we need r_lkserlock too? 2194 * No use of any shared fid or fctx... 2195 */ 2196 2197 /* 2198 * NFS needs to go over the wire, just to be sure whether the 2199 * file exists or not. Using a cached result is dangerous in 2200 * this case when making a decision regarding existence. 2201 * 2202 * The SMB protocol does NOT really need to go OTW here 2203 * thanks to the expressive NTCREATE disposition values. 2204 * Unfortunately, to do Unix access checks correctly, 2205 * we need to know if the object already exists. 2206 * When the object does not exist, we need VWRITE on 2207 * the directory. Note: smbfslookup() checks VEXEC. 2208 */ 2209 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2210 if (error == 0) { 2211 /* 2212 * The file already exists. Error? 2213 * NB: have a hold from smbfslookup 2214 */ 2215 if (exclusive == EXCL) { 2216 error = EEXIST; 2217 VN_RELE(vp); 2218 goto out; 2219 } 2220 /* 2221 * Verify requested access. 2222 */ 2223 error = smbfs_access(vp, mode, 0, cr, ct); 2224 if (error) { 2225 VN_RELE(vp); 2226 goto out; 2227 } 2228 2229 /* 2230 * Truncate (if requested). 2231 */ 2232 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) { 2233 vattr.va_mask = AT_SIZE; 2234 error = smbfssetattr(vp, &vattr, 0, cr); 2235 if (error) { 2236 VN_RELE(vp); 2237 goto out; 2238 } 2239 } 2240 /* Success! */ 2241 #ifdef NOT_YET 2242 vnevent_create(vp, ct); 2243 #endif 2244 *vpp = vp; 2245 goto out; 2246 } 2247 2248 /* 2249 * The file did not exist. Need VWRITE in the directory. 2250 */ 2251 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 2252 if (error) 2253 goto out; 2254 2255 /* 2256 * Now things get tricky. We also need to check the 2257 * requested open mode against the file we may create. 2258 * See comments at smbfs_access_rwx 2259 */ 2260 error = smbfs_access_rwx(vfsp, VREG, mode, cr); 2261 if (error) 2262 goto out; 2263 2264 /* 2265 * Now the code derived from Darwin, 2266 * but with greater use of NT_CREATE 2267 * disposition options. Much changed. 2268 * 2269 * Create (or open) a new child node. 2270 * Note we handled "." and ".." above. 2271 */ 2272 2273 if (exclusive == EXCL) 2274 disp = NTCREATEX_DISP_CREATE; 2275 else { 2276 /* Truncate regular files if requested. */ 2277 if ((va->va_type == VREG) && 2278 (va->va_mask & AT_SIZE) && 2279 (va->va_size == 0)) 2280 disp = NTCREATEX_DISP_OVERWRITE_IF; 2281 else 2282 disp = NTCREATEX_DISP_OPEN_IF; 2283 } 2284 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0; 2285 error = smbfs_smb_create(dnp, 2286 name, nmlen, xattr, 2287 disp, &scred, &fid); 2288 if (error) 2289 goto out; 2290 2291 /* 2292 * XXX: Missing some code here to deal with 2293 * the case where we opened an existing file, 2294 * it's size is larger than 32-bits, and we're 2295 * setting the size from a process that's not 2296 * aware of large file offsets. i.e. 2297 * from the NFS3 code: 2298 */ 2299 #if NOT_YET /* XXX */ 2300 if ((vattr.va_mask & AT_SIZE) && 2301 vp->v_type == VREG) { 2302 np = VTOSMB(vp); 2303 /* 2304 * Check here for large file handled 2305 * by LF-unaware process (as 2306 * ufs_create() does) 2307 */ 2308 if (!(lfaware & FOFFMAX)) { 2309 mutex_enter(&np->r_statelock); 2310 if (np->r_size > MAXOFF32_T) 2311 error = EOVERFLOW; 2312 mutex_exit(&np->r_statelock); 2313 } 2314 if (!error) { 2315 vattr.va_mask = AT_SIZE; 2316 error = smbfssetattr(vp, 2317 &vattr, 0, cr); 2318 } 2319 } 2320 #endif /* XXX */ 2321 /* 2322 * Should use the fid to get/set the size 2323 * while we have it opened here. See above. 2324 */ 2325 2326 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred); 2327 if (cerror) 2328 SMBVDEBUG("error %d closing %s\\%s\n", 2329 cerror, dnp->n_rpath, name); 2330 2331 /* 2332 * In the open case, the name may differ a little 2333 * from what we passed to create (case, etc.) 2334 * so call lookup to get the (opened) name. 2335 * 2336 * XXX: Could avoid this extra lookup if the 2337 * "createact" result from NT_CREATE says we 2338 * created the object. 2339 */ 2340 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 2341 if (error) 2342 goto out; 2343 2344 /* update attr and directory cache */ 2345 smbfs_attr_touchdir(dnp); 2346 2347 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 2348 if (error) 2349 goto out; 2350 2351 /* XXX invalidate pages if we truncated? */ 2352 2353 /* Success! */ 2354 *vpp = vp; 2355 error = 0; 2356 2357 out: 2358 smb_credrele(&scred); 2359 smbfs_rw_exit(&dnp->r_rwlock); 2360 if (name != nm) 2361 smbfs_name_free(name, nmlen); 2362 return (error); 2363 } 2364 2365 /* 2366 * XXX 2367 * This op should support the new FIGNORECASE flag for case-insensitive 2368 * lookups, per PSARC 2007/244. 2369 */ 2370 /* ARGSUSED */ 2371 static int 2372 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct, 2373 int flags) 2374 { 2375 int error; 2376 vnode_t *vp; 2377 smbnode_t *np; 2378 smbnode_t *dnp; 2379 struct smb_cred scred; 2380 /* enum smbfsstat status; */ 2381 smbmntinfo_t *smi; 2382 2383 smi = VTOSMI(dvp); 2384 2385 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2386 return (EPERM); 2387 2388 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2389 return (EIO); 2390 2391 dnp = VTOSMB(dvp); 2392 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2393 return (EINTR); 2394 smb_credinit(&scred, cr); 2395 2396 /* 2397 * Verify access to the dirctory. 2398 */ 2399 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct); 2400 if (error) 2401 goto out; 2402 2403 /* 2404 * NOTE: the darwin code gets the "vp" passed in so it looks 2405 * like the "vp" has probably been "lookup"ed by the VFS layer. 2406 * It looks like we will need to lookup the vp to check the 2407 * caches and check if the object being deleted is a directory. 2408 */ 2409 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2410 if (error) 2411 goto out; 2412 2413 /* Never allow link/unlink directories on CIFS. */ 2414 if (vp->v_type == VDIR) { 2415 VN_RELE(vp); 2416 error = EPERM; 2417 goto out; 2418 } 2419 2420 /* 2421 * Now we have the real reference count on the vnode 2422 * Do we have the file open? 2423 */ 2424 np = VTOSMB(vp); 2425 mutex_enter(&np->r_statelock); 2426 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) { 2427 /* 2428 * NFS does a rename on remove here. 2429 * Probably not applicable for SMB. 2430 * Like Darwin, just return EBUSY. 2431 * 2432 * XXX: Todo - Use Trans2rename, and 2433 * if that fails, ask the server to 2434 * set the delete-on-close flag. 2435 */ 2436 mutex_exit(&np->r_statelock); 2437 error = EBUSY; 2438 } else { 2439 smbfs_attrcache_rm_locked(np); 2440 mutex_exit(&np->r_statelock); 2441 2442 error = smbfs_smb_delete(np, &scred, NULL, 0, 0); 2443 2444 /* 2445 * If the file should no longer exist, discard 2446 * any cached attributes under this node. 2447 */ 2448 switch (error) { 2449 case 0: 2450 case ENOENT: 2451 case ENOTDIR: 2452 smbfs_attrcache_prune(np); 2453 break; 2454 } 2455 } 2456 2457 VN_RELE(vp); 2458 2459 out: 2460 smb_credrele(&scred); 2461 smbfs_rw_exit(&dnp->r_rwlock); 2462 2463 return (error); 2464 } 2465 2466 2467 /* 2468 * XXX 2469 * This op should support the new FIGNORECASE flag for case-insensitive 2470 * lookups, per PSARC 2007/244. 2471 */ 2472 /* ARGSUSED */ 2473 static int 2474 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, 2475 caller_context_t *ct, int flags) 2476 { 2477 /* vnode_t *realvp; */ 2478 2479 if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone || 2480 curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone) 2481 return (EPERM); 2482 2483 if (VTOSMI(odvp)->smi_flags & SMI_DEAD || 2484 VTOSMI(ndvp)->smi_flags & SMI_DEAD || 2485 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED || 2486 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2487 return (EIO); 2488 2489 return (smbfsrename(odvp, onm, ndvp, nnm, cr, ct)); 2490 } 2491 2492 /* 2493 * smbfsrename does the real work of renaming in SMBFS 2494 */ 2495 /* ARGSUSED */ 2496 static int 2497 smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, 2498 caller_context_t *ct) 2499 { 2500 int error; 2501 int nvp_locked = 0; 2502 vnode_t *nvp = NULL; 2503 vnode_t *ovp = NULL; 2504 smbnode_t *onp; 2505 smbnode_t *nnp; 2506 smbnode_t *odnp; 2507 smbnode_t *ndnp; 2508 struct smb_cred scred; 2509 /* enum smbfsstat status; */ 2510 2511 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone); 2512 2513 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 || 2514 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0) 2515 return (EINVAL); 2516 2517 /* 2518 * Check that everything is on the same filesystem. 2519 * vn_rename checks the fsid's, but in case we don't 2520 * fill those in correctly, check here too. 2521 */ 2522 if (odvp->v_vfsp != ndvp->v_vfsp) 2523 return (EXDEV); 2524 2525 odnp = VTOSMB(odvp); 2526 ndnp = VTOSMB(ndvp); 2527 2528 /* 2529 * Avoid deadlock here on old vs new directory nodes 2530 * by always taking the locks in order of address. 2531 * The order is arbitrary, but must be consistent. 2532 */ 2533 if (odnp < ndnp) { 2534 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2535 SMBINTR(odvp))) 2536 return (EINTR); 2537 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2538 SMBINTR(ndvp))) { 2539 smbfs_rw_exit(&odnp->r_rwlock); 2540 return (EINTR); 2541 } 2542 } else { 2543 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2544 SMBINTR(ndvp))) 2545 return (EINTR); 2546 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2547 SMBINTR(odvp))) { 2548 smbfs_rw_exit(&ndnp->r_rwlock); 2549 return (EINTR); 2550 } 2551 } 2552 smb_credinit(&scred, cr); 2553 /* 2554 * No returns after this point (goto out) 2555 */ 2556 2557 /* 2558 * Need write access on source and target. 2559 * Server takes care of most checks. 2560 */ 2561 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct); 2562 if (error) 2563 goto out; 2564 if (odvp != ndvp) { 2565 error = smbfs_access(ndvp, VWRITE, 0, cr, ct); 2566 if (error) 2567 goto out; 2568 } 2569 2570 /* 2571 * Lookup the source name. Must already exist. 2572 */ 2573 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct); 2574 if (error) 2575 goto out; 2576 2577 /* 2578 * Lookup the target file. If it exists, it needs to be 2579 * checked to see whether it is a mount point and whether 2580 * it is active (open). 2581 */ 2582 error = smbfslookup(ndvp, nnm, &nvp, cr, 0, ct); 2583 if (!error) { 2584 /* 2585 * Target (nvp) already exists. Check that it 2586 * has the same type as the source. The server 2587 * will check this also, (and more reliably) but 2588 * this lets us return the correct error codes. 2589 */ 2590 if (ovp->v_type == VDIR) { 2591 if (nvp->v_type != VDIR) { 2592 error = ENOTDIR; 2593 goto out; 2594 } 2595 } else { 2596 if (nvp->v_type == VDIR) { 2597 error = EISDIR; 2598 goto out; 2599 } 2600 } 2601 2602 /* 2603 * POSIX dictates that when the source and target 2604 * entries refer to the same file object, rename 2605 * must do nothing and exit without error. 2606 */ 2607 if (ovp == nvp) { 2608 error = 0; 2609 goto out; 2610 } 2611 2612 /* 2613 * Also must ensure the target is not a mount point, 2614 * and keep mount/umount away until we're done. 2615 */ 2616 if (vn_vfsrlock(nvp)) { 2617 error = EBUSY; 2618 goto out; 2619 } 2620 nvp_locked = 1; 2621 if (vn_mountedvfs(nvp) != NULL) { 2622 error = EBUSY; 2623 goto out; 2624 } 2625 2626 /* 2627 * CIFS gives a SHARING_VIOLATION error when 2628 * trying to rename onto an exising object, 2629 * so try to remove the target first. 2630 * (Only for files, not directories.) 2631 */ 2632 if (nvp->v_type == VDIR) { 2633 error = EEXIST; 2634 goto out; 2635 } 2636 2637 /* 2638 * Nodes that are "not active" here have v_count=2 2639 * because vn_renameat (our caller) did a lookup on 2640 * both the source and target before this call. 2641 * Otherwise this similar to smbfs_remove. 2642 */ 2643 nnp = VTOSMB(nvp); 2644 mutex_enter(&nnp->r_statelock); 2645 if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) { 2646 /* 2647 * The target file exists, is not the same as 2648 * the source file, and is active. Other FS 2649 * implementations unlink the target here. 2650 * For SMB, we don't assume we can remove an 2651 * open file. Return an error instead. 2652 */ 2653 mutex_exit(&nnp->r_statelock); 2654 error = EBUSY; 2655 goto out; 2656 } 2657 2658 /* 2659 * Target file is not active. Try to remove it. 2660 */ 2661 smbfs_attrcache_rm_locked(nnp); 2662 mutex_exit(&nnp->r_statelock); 2663 2664 error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0); 2665 2666 /* 2667 * Similar to smbfs_remove 2668 */ 2669 switch (error) { 2670 case 0: 2671 case ENOENT: 2672 case ENOTDIR: 2673 smbfs_attrcache_prune(nnp); 2674 break; 2675 } 2676 2677 if (error) 2678 goto out; 2679 /* 2680 * OK, removed the target file. Continue as if 2681 * lookup target had failed (nvp == NULL). 2682 */ 2683 vn_vfsunlock(nvp); 2684 nvp_locked = 0; 2685 VN_RELE(nvp); 2686 nvp = NULL; 2687 } /* nvp */ 2688 2689 onp = VTOSMB(ovp); 2690 smbfs_attrcache_remove(onp); 2691 2692 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred); 2693 2694 /* 2695 * If the old name should no longer exist, 2696 * discard any cached attributes under it. 2697 */ 2698 if (error == 0) 2699 smbfs_attrcache_prune(onp); 2700 2701 out: 2702 if (nvp) { 2703 if (nvp_locked) 2704 vn_vfsunlock(nvp); 2705 VN_RELE(nvp); 2706 } 2707 if (ovp) 2708 VN_RELE(ovp); 2709 2710 smb_credrele(&scred); 2711 smbfs_rw_exit(&odnp->r_rwlock); 2712 smbfs_rw_exit(&ndnp->r_rwlock); 2713 2714 return (error); 2715 } 2716 2717 /* 2718 * XXX 2719 * vsecattr_t is new to build 77, and we need to eventually support 2720 * it in order to create an ACL when an object is created. 2721 * 2722 * This op should support the new FIGNORECASE flag for case-insensitive 2723 * lookups, per PSARC 2007/244. 2724 */ 2725 /* ARGSUSED */ 2726 static int 2727 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, 2728 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp) 2729 { 2730 vnode_t *vp; 2731 struct smbnode *dnp = VTOSMB(dvp); 2732 struct smbmntinfo *smi = VTOSMI(dvp); 2733 struct smb_cred scred; 2734 struct smbfattr fattr; 2735 const char *name = (const char *) nm; 2736 int nmlen = strlen(name); 2737 int error, hiderr; 2738 2739 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2740 return (EPERM); 2741 2742 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2743 return (EIO); 2744 2745 if ((nmlen == 1 && name[0] == '.') || 2746 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 2747 return (EEXIST); 2748 2749 /* Only plain files are allowed in V_XATTRDIR. */ 2750 if (dvp->v_flag & V_XATTRDIR) 2751 return (EINVAL); 2752 2753 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2754 return (EINTR); 2755 smb_credinit(&scred, cr); 2756 2757 /* 2758 * XXX: Do we need r_lkserlock too? 2759 * No use of any shared fid or fctx... 2760 */ 2761 2762 /* 2763 * Require write access in the containing directory. 2764 */ 2765 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 2766 if (error) 2767 goto out; 2768 2769 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred); 2770 if (error) 2771 goto out; 2772 2773 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 2774 if (error) 2775 goto out; 2776 2777 smbfs_attr_touchdir(dnp); 2778 2779 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 2780 if (error) 2781 goto out; 2782 2783 if (name[0] == '.') 2784 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred))) 2785 SMBVDEBUG("hide failure %d\n", hiderr); 2786 2787 /* Success! */ 2788 *vpp = vp; 2789 error = 0; 2790 out: 2791 smb_credrele(&scred); 2792 smbfs_rw_exit(&dnp->r_rwlock); 2793 2794 if (name != nm) 2795 smbfs_name_free(name, nmlen); 2796 2797 return (error); 2798 } 2799 2800 /* 2801 * XXX 2802 * This op should support the new FIGNORECASE flag for case-insensitive 2803 * lookups, per PSARC 2007/244. 2804 */ 2805 /* ARGSUSED */ 2806 static int 2807 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr, 2808 caller_context_t *ct, int flags) 2809 { 2810 vnode_t *vp = NULL; 2811 int vp_locked = 0; 2812 struct smbmntinfo *smi = VTOSMI(dvp); 2813 struct smbnode *dnp = VTOSMB(dvp); 2814 struct smbnode *np; 2815 struct smb_cred scred; 2816 int error; 2817 2818 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2819 return (EPERM); 2820 2821 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2822 return (EIO); 2823 2824 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2825 return (EINTR); 2826 smb_credinit(&scred, cr); 2827 2828 /* 2829 * Require w/x access in the containing directory. 2830 * Server handles all other access checks. 2831 */ 2832 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct); 2833 if (error) 2834 goto out; 2835 2836 /* 2837 * First lookup the entry to be removed. 2838 */ 2839 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2840 if (error) 2841 goto out; 2842 np = VTOSMB(vp); 2843 2844 /* 2845 * Disallow rmdir of "." or current dir, or the FS root. 2846 * Also make sure it's a directory, not a mount point, 2847 * and lock to keep mount/umount away until we're done. 2848 */ 2849 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) { 2850 error = EINVAL; 2851 goto out; 2852 } 2853 if (vp->v_type != VDIR) { 2854 error = ENOTDIR; 2855 goto out; 2856 } 2857 if (vn_vfsrlock(vp)) { 2858 error = EBUSY; 2859 goto out; 2860 } 2861 vp_locked = 1; 2862 if (vn_mountedvfs(vp) != NULL) { 2863 error = EBUSY; 2864 goto out; 2865 } 2866 2867 smbfs_attrcache_remove(np); 2868 error = smbfs_smb_rmdir(np, &scred); 2869 2870 /* 2871 * Similar to smbfs_remove 2872 */ 2873 switch (error) { 2874 case 0: 2875 case ENOENT: 2876 case ENOTDIR: 2877 smbfs_attrcache_prune(np); 2878 break; 2879 } 2880 2881 if (error) 2882 goto out; 2883 2884 mutex_enter(&np->r_statelock); 2885 dnp->n_flag |= NMODIFIED; 2886 mutex_exit(&np->r_statelock); 2887 smbfs_attr_touchdir(dnp); 2888 smbfs_rmhash(np); 2889 2890 out: 2891 if (vp) { 2892 if (vp_locked) 2893 vn_vfsunlock(vp); 2894 VN_RELE(vp); 2895 } 2896 smb_credrele(&scred); 2897 smbfs_rw_exit(&dnp->r_rwlock); 2898 2899 return (error); 2900 } 2901 2902 2903 /* ARGSUSED */ 2904 static int 2905 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp, 2906 caller_context_t *ct, int flags) 2907 { 2908 struct smbnode *np = VTOSMB(vp); 2909 int error = 0; 2910 smbmntinfo_t *smi; 2911 2912 smi = VTOSMI(vp); 2913 2914 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2915 return (EIO); 2916 2917 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2918 return (EIO); 2919 2920 /* 2921 * Require read access in the directory. 2922 */ 2923 error = smbfs_access(vp, VREAD, 0, cr, ct); 2924 if (error) 2925 return (error); 2926 2927 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER)); 2928 2929 /* 2930 * XXX: Todo readdir cache here 2931 * Note: NFS code is just below this. 2932 * 2933 * I am serializing the entire readdir opreation 2934 * now since we have not yet implemented readdir 2935 * cache. This fix needs to be revisited once 2936 * we implement readdir cache. 2937 */ 2938 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 2939 return (EINTR); 2940 2941 error = smbfs_readvdir(vp, uiop, cr, eofp, ct); 2942 2943 smbfs_rw_exit(&np->r_lkserlock); 2944 2945 return (error); 2946 } 2947 2948 /* ARGSUSED */ 2949 static int 2950 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, 2951 caller_context_t *ct) 2952 { 2953 /* 2954 * Note: "limit" tells the SMB-level FindFirst/FindNext 2955 * functions how many directory entries to request in 2956 * each OtW call. It needs to be large enough so that 2957 * we don't make lots of tiny OtW requests, but there's 2958 * no point making it larger than the maximum number of 2959 * OtW entries that would fit in a maximum sized trans2 2960 * response (64k / 48). Beyond that, it's just tuning. 2961 * WinNT used 512, Win2k used 1366. We use 1000. 2962 */ 2963 static const int limit = 1000; 2964 /* Largest possible dirent size. */ 2965 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN); 2966 struct smb_cred scred; 2967 vnode_t *newvp; 2968 struct smbnode *np = VTOSMB(vp); 2969 struct smbfs_fctx *ctx; 2970 struct dirent64 *dp; 2971 ssize_t save_resid; 2972 offset_t save_offset; /* 64 bits */ 2973 int offset; /* yes, 32 bits */ 2974 int nmlen, error; 2975 ushort_t reclen; 2976 2977 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone); 2978 2979 /* Make sure we serialize for n_dirseq use. */ 2980 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER)); 2981 2982 /* 2983 * Make sure smbfs_open filled in n_dirseq 2984 */ 2985 if (np->n_dirseq == NULL) 2986 return (EBADF); 2987 2988 /* Check for overflow of (32-bit) directory offset. */ 2989 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX || 2990 (uio->uio_loffset + uio->uio_resid) > INT32_MAX) 2991 return (EINVAL); 2992 2993 /* Require space for at least one dirent. */ 2994 if (uio->uio_resid < dbufsiz) 2995 return (EINVAL); 2996 2997 SMBVDEBUG("dirname='%s'\n", np->n_rpath); 2998 smb_credinit(&scred, cr); 2999 dp = kmem_alloc(dbufsiz, KM_SLEEP); 3000 3001 save_resid = uio->uio_resid; 3002 save_offset = uio->uio_loffset; 3003 offset = uio->uio_offset; 3004 SMBVDEBUG("in: offset=%d, resid=%d\n", 3005 (int)uio->uio_offset, (int)uio->uio_resid); 3006 error = 0; 3007 3008 /* 3009 * Generate the "." and ".." entries here so we can 3010 * (1) make sure they appear (but only once), and 3011 * (2) deal with getting their I numbers which the 3012 * findnext below does only for normal names. 3013 */ 3014 while (offset < FIRST_DIROFS) { 3015 /* 3016 * Tricky bit filling in the first two: 3017 * offset 0 is ".", offset 1 is ".." 3018 * so strlen of these is offset+1. 3019 */ 3020 reclen = DIRENT64_RECLEN(offset + 1); 3021 if (uio->uio_resid < reclen) 3022 goto out; 3023 bzero(dp, reclen); 3024 dp->d_reclen = reclen; 3025 dp->d_name[0] = '.'; 3026 dp->d_name[1] = '.'; 3027 dp->d_name[offset + 1] = '\0'; 3028 /* 3029 * Want the real I-numbers for the "." and ".." 3030 * entries. For these two names, we know that 3031 * smbfslookup can get the nodes efficiently. 3032 */ 3033 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct); 3034 if (error) { 3035 dp->d_ino = np->n_ino + offset; /* fiction */ 3036 } else { 3037 dp->d_ino = VTOSMB(newvp)->n_ino; 3038 VN_RELE(newvp); 3039 } 3040 /* 3041 * Note: d_off is the offset that a user-level program 3042 * should seek to for reading the NEXT directory entry. 3043 * See libc: readdir, telldir, seekdir 3044 */ 3045 dp->d_off = offset + 1; 3046 error = uiomove(dp, reclen, UIO_READ, uio); 3047 if (error) 3048 goto out; 3049 /* 3050 * Note: uiomove updates uio->uio_offset, 3051 * but we want it to be our "cookie" value, 3052 * which just counts dirents ignoring size. 3053 */ 3054 uio->uio_offset = ++offset; 3055 } 3056 3057 /* 3058 * If there was a backward seek, we have to reopen. 3059 */ 3060 if (offset < np->n_dirofs) { 3061 SMBVDEBUG("Reopening search %d:%d\n", 3062 offset, np->n_dirofs); 3063 error = smbfs_smb_findopen(np, "*", 1, 3064 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, 3065 &scred, &ctx); 3066 if (error) { 3067 SMBVDEBUG("can not open search, error = %d", error); 3068 goto out; 3069 } 3070 /* free the old one */ 3071 (void) smbfs_smb_findclose(np->n_dirseq, &scred); 3072 /* save the new one */ 3073 np->n_dirseq = ctx; 3074 np->n_dirofs = FIRST_DIROFS; 3075 } else { 3076 ctx = np->n_dirseq; 3077 } 3078 3079 /* 3080 * Skip entries before the requested offset. 3081 */ 3082 while (np->n_dirofs < offset) { 3083 error = smbfs_smb_findnext(ctx, limit, &scred); 3084 if (error != 0) 3085 goto out; 3086 np->n_dirofs++; 3087 } 3088 3089 /* 3090 * While there's room in the caller's buffer: 3091 * get a directory entry from SMB, 3092 * convert to a dirent, copyout. 3093 * We stop when there is no longer room for a 3094 * maximum sized dirent because we must decide 3095 * before we know anything about the next entry. 3096 */ 3097 while (uio->uio_resid >= dbufsiz) { 3098 error = smbfs_smb_findnext(ctx, limit, &scred); 3099 if (error != 0) 3100 goto out; 3101 np->n_dirofs++; 3102 3103 /* Sanity check the name length. */ 3104 nmlen = ctx->f_nmlen; 3105 if (nmlen > SMB_MAXFNAMELEN) { 3106 nmlen = SMB_MAXFNAMELEN; 3107 SMBVDEBUG("Truncating name: %s\n", ctx->f_name); 3108 } 3109 if (smbfs_fastlookup) { 3110 /* See comment at smbfs_fastlookup above. */ 3111 if (smbfs_nget(vp, ctx->f_name, nmlen, 3112 &ctx->f_attr, &newvp) == 0) 3113 VN_RELE(newvp); 3114 } 3115 3116 reclen = DIRENT64_RECLEN(nmlen); 3117 bzero(dp, reclen); 3118 dp->d_reclen = reclen; 3119 bcopy(ctx->f_name, dp->d_name, nmlen); 3120 dp->d_name[nmlen] = '\0'; 3121 dp->d_ino = ctx->f_inum; 3122 dp->d_off = offset + 1; /* See d_off comment above */ 3123 error = uiomove(dp, reclen, UIO_READ, uio); 3124 if (error) 3125 goto out; 3126 /* See comment re. uio_offset above. */ 3127 uio->uio_offset = ++offset; 3128 } 3129 3130 out: 3131 /* 3132 * When we come to the end of a directory, the 3133 * SMB-level functions return ENOENT, but the 3134 * caller is not expecting an error return. 3135 * 3136 * Also note that we must delay the call to 3137 * smbfs_smb_findclose(np->n_dirseq, ...) 3138 * until smbfs_close so that all reads at the 3139 * end of the directory will return no data. 3140 */ 3141 if (error == ENOENT) { 3142 error = 0; 3143 if (eofp) 3144 *eofp = 1; 3145 } 3146 /* 3147 * If we encountered an error (i.e. "access denied") 3148 * from the FindFirst call, we will have copied out 3149 * the "." and ".." entries leaving offset == 2. 3150 * In that case, restore the original offset/resid 3151 * so the caller gets no data with the error. 3152 */ 3153 if (error != 0 && offset == FIRST_DIROFS) { 3154 uio->uio_loffset = save_offset; 3155 uio->uio_resid = save_resid; 3156 } 3157 SMBVDEBUG("out: offset=%d, resid=%d\n", 3158 (int)uio->uio_offset, (int)uio->uio_resid); 3159 3160 kmem_free(dp, dbufsiz); 3161 smb_credrele(&scred); 3162 return (error); 3163 } 3164 3165 3166 /* 3167 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK 3168 * are optional functions that are called by: 3169 * getdents, before/after VOP_READDIR 3170 * pread, before/after ... VOP_READ 3171 * pwrite, before/after ... VOP_WRITE 3172 * (other places) 3173 * 3174 * Careful here: None of the above check for any 3175 * error returns from VOP_RWLOCK / VOP_RWUNLOCK! 3176 * In fact, the return value from _rwlock is NOT 3177 * an error code, but V_WRITELOCK_TRUE / _FALSE. 3178 * 3179 * Therefore, it's up to _this_ code to make sure 3180 * the lock state remains balanced, which means 3181 * we can't "bail out" on interrupts, etc. 3182 */ 3183 3184 /* ARGSUSED2 */ 3185 static int 3186 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 3187 { 3188 smbnode_t *np = VTOSMB(vp); 3189 3190 if (!write_lock) { 3191 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE); 3192 return (V_WRITELOCK_FALSE); 3193 } 3194 3195 3196 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE); 3197 return (V_WRITELOCK_TRUE); 3198 } 3199 3200 /* ARGSUSED */ 3201 static void 3202 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 3203 { 3204 smbnode_t *np = VTOSMB(vp); 3205 3206 smbfs_rw_exit(&np->r_rwlock); 3207 } 3208 3209 3210 /* ARGSUSED */ 3211 static int 3212 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) 3213 { 3214 smbmntinfo_t *smi; 3215 3216 smi = VTOSMI(vp); 3217 3218 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3219 return (EPERM); 3220 3221 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3222 return (EIO); 3223 3224 /* 3225 * Because we stuff the readdir cookie into the offset field 3226 * someone may attempt to do an lseek with the cookie which 3227 * we want to succeed. 3228 */ 3229 if (vp->v_type == VDIR) 3230 return (0); 3231 3232 /* Like NFS3, just check for 63-bit overflow. */ 3233 if (*noffp < 0) 3234 return (EINVAL); 3235 3236 return (0); 3237 } 3238 3239 3240 /* 3241 * XXX 3242 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service. 3243 */ 3244 static int 3245 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 3246 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr, 3247 caller_context_t *ct) 3248 { 3249 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone) 3250 return (EIO); 3251 3252 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 3253 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct)); 3254 else 3255 return (ENOSYS); 3256 } 3257 3258 /* 3259 * Free storage space associated with the specified vnode. The portion 3260 * to be freed is specified by bfp->l_start and bfp->l_len (already 3261 * normalized to a "whence" of 0). 3262 * 3263 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc. 3264 */ 3265 /* ARGSUSED */ 3266 static int 3267 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 3268 offset_t offset, cred_t *cr, caller_context_t *ct) 3269 { 3270 int error; 3271 smbmntinfo_t *smi; 3272 3273 smi = VTOSMI(vp); 3274 3275 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3276 return (EIO); 3277 3278 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3279 return (EIO); 3280 3281 /* Caller (fcntl) has checked v_type */ 3282 ASSERT(vp->v_type == VREG); 3283 if (cmd != F_FREESP) 3284 return (EINVAL); 3285 3286 /* 3287 * Like NFS3, no 32-bit offset checks here. 3288 * Our SMB layer takes care to return EFBIG 3289 * when it has to fallback to a 32-bit call. 3290 */ 3291 3292 error = convoff(vp, bfp, 0, offset); 3293 if (!error) { 3294 ASSERT(bfp->l_start >= 0); 3295 if (bfp->l_len == 0) { 3296 struct vattr va; 3297 3298 /* 3299 * ftruncate should not change the ctime and 3300 * mtime if we truncate the file to its 3301 * previous size. 3302 */ 3303 va.va_mask = AT_SIZE; 3304 error = smbfsgetattr(vp, &va, cr); 3305 if (error || va.va_size == bfp->l_start) 3306 return (error); 3307 va.va_mask = AT_SIZE; 3308 va.va_size = bfp->l_start; 3309 error = smbfssetattr(vp, &va, 0, cr); 3310 } else 3311 error = EINVAL; 3312 } 3313 3314 return (error); 3315 } 3316 3317 /* ARGSUSED */ 3318 static int 3319 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, 3320 caller_context_t *ct) 3321 { 3322 vfs_t *vfs; 3323 smbmntinfo_t *smi; 3324 struct smb_share *ssp; 3325 3326 vfs = vp->v_vfsp; 3327 smi = VFTOSMI(vfs); 3328 3329 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3330 return (EIO); 3331 3332 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3333 return (EIO); 3334 3335 switch (cmd) { 3336 case _PC_FILESIZEBITS: 3337 ssp = smi->smi_share; 3338 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) 3339 *valp = 64; 3340 else 3341 *valp = 32; 3342 break; 3343 3344 case _PC_LINK_MAX: 3345 /* We only ever report one link to an object */ 3346 *valp = 1; 3347 break; 3348 3349 case _PC_ACL_ENABLED: 3350 /* 3351 * Always indicate that ACLs are enabled and 3352 * that we support ACE_T format, otherwise 3353 * libsec will ask for ACLENT_T format data 3354 * which we don't support. 3355 */ 3356 *valp = _ACL_ACE_ENABLED; 3357 break; 3358 3359 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */ 3360 *valp = 0; 3361 break; 3362 3363 case _PC_XATTR_EXISTS: 3364 if (vfs->vfs_flag & VFS_XATTR) { 3365 *valp = smbfs_xa_exists(vp, cr); 3366 break; 3367 } 3368 return (EINVAL); 3369 3370 case _PC_TIMESTAMP_RESOLUTION: 3371 /* 3372 * Windows times are tenths of microseconds 3373 * (multiples of 100 nanoseconds). 3374 */ 3375 *valp = 100L; 3376 break; 3377 3378 default: 3379 return (fs_pathconf(vp, cmd, valp, cr, ct)); 3380 } 3381 return (0); 3382 } 3383 3384 /* ARGSUSED */ 3385 static int 3386 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3387 caller_context_t *ct) 3388 { 3389 vfs_t *vfsp; 3390 smbmntinfo_t *smi; 3391 int error; 3392 uint_t mask; 3393 3394 vfsp = vp->v_vfsp; 3395 smi = VFTOSMI(vfsp); 3396 3397 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3398 return (EIO); 3399 3400 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3401 return (EIO); 3402 3403 /* 3404 * Our _pathconf indicates _ACL_ACE_ENABLED, 3405 * so we should only see VSA_ACE, etc here. 3406 * Note: vn_create asks for VSA_DFACLCNT, 3407 * and it expects ENOSYS and empty data. 3408 */ 3409 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT | 3410 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 3411 if (mask == 0) 3412 return (ENOSYS); 3413 3414 if (smi->smi_flags & SMI_ACL) 3415 error = smbfs_acl_getvsa(vp, vsa, flag, cr); 3416 else 3417 error = ENOSYS; 3418 3419 if (error == ENOSYS) 3420 error = fs_fab_acl(vp, vsa, flag, cr, ct); 3421 3422 return (error); 3423 } 3424 3425 /* ARGSUSED */ 3426 static int 3427 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3428 caller_context_t *ct) 3429 { 3430 vfs_t *vfsp; 3431 smbmntinfo_t *smi; 3432 int error; 3433 uint_t mask; 3434 3435 vfsp = vp->v_vfsp; 3436 smi = VFTOSMI(vfsp); 3437 3438 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3439 return (EIO); 3440 3441 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3442 return (EIO); 3443 3444 /* 3445 * Our _pathconf indicates _ACL_ACE_ENABLED, 3446 * so we should only see VSA_ACE, etc here. 3447 */ 3448 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT); 3449 if (mask == 0) 3450 return (ENOSYS); 3451 3452 if (vfsp->vfs_flag & VFS_RDONLY) 3453 return (EROFS); 3454 3455 /* 3456 * Allow only the mount owner to do this. 3457 * See comments at smbfs_access_rwx. 3458 */ 3459 error = secpolicy_vnode_setdac(cr, smi->smi_uid); 3460 if (error != 0) 3461 return (error); 3462 3463 if (smi->smi_flags & SMI_ACL) 3464 error = smbfs_acl_setvsa(vp, vsa, flag, cr); 3465 else 3466 error = ENOSYS; 3467 3468 return (error); 3469 } 3470 3471 3472 /* 3473 * XXX 3474 * This op should eventually support PSARC 2007/268. 3475 */ 3476 static int 3477 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr, 3478 caller_context_t *ct) 3479 { 3480 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone) 3481 return (EIO); 3482 3483 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 3484 return (fs_shrlock(vp, cmd, shr, flag, cr, ct)); 3485 else 3486 return (ENOSYS); 3487 } 3488 3489 /* correspond to bp_mapin() in bp_map.c */ 3490 static int 3491 uio_page_mapin(uio_t * uiop, page_t * pp) 3492 { 3493 u_offset_t off; 3494 size_t size; 3495 pgcnt_t npages; 3496 caddr_t kaddr; 3497 pfn_t pfnum; 3498 3499 off = (uintptr_t) uiop->uio_loffset & PAGEOFFSET; 3500 size = P2ROUNDUP(uiop->uio_resid + off, PAGESIZE); 3501 npages = btop(size); 3502 3503 ASSERT(pp != NULL); 3504 3505 if (npages == 1 && kpm_enable) { 3506 kaddr = hat_kpm_mapin(pp, NULL); 3507 if (kaddr == NULL) 3508 return (EFAULT); 3509 3510 uiop->uio_iov->iov_base = kaddr + off; 3511 uiop->uio_iov->iov_len = PAGESIZE - off; 3512 3513 } else { 3514 kaddr = vmem_xalloc(heap_arena, size, PAGESIZE, 0, 0, NULL, NULL, VM_SLEEP); 3515 if (kaddr == NULL) 3516 return (EFAULT); 3517 3518 uiop->uio_iov->iov_base = kaddr + off; 3519 uiop->uio_iov->iov_len = size - off; 3520 3521 /* map pages into kaddr */ 3522 uint_t attr = PROT_READ | PROT_WRITE | HAT_NOSYNC; 3523 while (npages-- > 0) { 3524 pfnum = pp->p_pagenum; 3525 pp = pp->p_next; 3526 3527 hat_devload(kas.a_hat, kaddr, PAGESIZE, pfnum, attr, HAT_LOAD_LOCK); 3528 kaddr += PAGESIZE; 3529 } 3530 } 3531 return (0); 3532 } 3533 3534 /* correspond to bp_mapout() in bp_map.c */ 3535 static void 3536 uio_page_mapout(uio_t * uiop, page_t * pp) 3537 { 3538 u_offset_t off; 3539 size_t size; 3540 pgcnt_t npages; 3541 caddr_t kaddr; 3542 3543 kaddr = uiop->uio_iov->iov_base; 3544 off = (uintptr_t) kaddr & PAGEOFFSET; 3545 size = P2ROUNDUP(uiop->uio_iov->iov_len + off, PAGESIZE); 3546 npages = btop(size); 3547 3548 ASSERT(pp != NULL); 3549 3550 kaddr = (caddr_t) ((uintptr_t) kaddr & MMU_PAGEMASK); 3551 3552 if (npages == 1 && kpm_enable) { 3553 hat_kpm_mapout(pp, NULL, kaddr); 3554 3555 } else { 3556 hat_unload(kas.a_hat, (void *) kaddr, size, 3557 HAT_UNLOAD_NOSYNC | HAT_UNLOAD_UNLOCK); 3558 vmem_free(heap_arena, (void *) kaddr, size); 3559 } 3560 uiop->uio_iov->iov_base = 0; 3561 uiop->uio_iov->iov_len = 0; 3562 } 3563 3564 static int 3565 smbfs_map(vnode_t * vp, offset_t off, struct as * as, caddr_t * addrp, 3566 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t * cr, 3567 caller_context_t * ct) 3568 { 3569 smbnode_t *np; 3570 smbmntinfo_t *smi; 3571 struct vattr va; 3572 segvn_crargs_t vn_a; 3573 int error; 3574 3575 np = VTOSMB(vp); 3576 smi = VTOSMI(vp); 3577 3578 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3579 return (EIO); 3580 3581 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3582 return (EIO); 3583 3584 if (vp->v_flag & VNOMAP || vp->v_flag & VNOCACHE) 3585 return (EAGAIN); 3586 3587 if (vp->v_type != VREG) 3588 return (ENODEV); 3589 3590 va.va_mask = AT_ALL; 3591 if (error = smbfsgetattr(vp, &va, cr)) 3592 return (error); 3593 3594 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 3595 return (EINTR); 3596 3597 if (MANDLOCK(vp, va.va_mode)) { 3598 error = EAGAIN; 3599 goto out; 3600 } 3601 as_rangelock(as); 3602 error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags); 3603 3604 if (error != 0) { 3605 as_rangeunlock(as); 3606 goto out; 3607 } 3608 vn_a.vp = vp; 3609 vn_a.offset = off; 3610 vn_a.type = flags & MAP_TYPE; 3611 vn_a.prot = prot; 3612 vn_a.maxprot = maxprot; 3613 vn_a.flags = flags & ~MAP_TYPE; 3614 vn_a.cred = cr; 3615 vn_a.amp = NULL; 3616 vn_a.szc = 0; 3617 vn_a.lgrp_mem_policy_flags = 0; 3618 3619 error = as_map(as, *addrp, len, segvn_create, &vn_a); 3620 3621 as_rangeunlock(as); 3622 3623 out: 3624 smbfs_rw_exit(&np->r_lkserlock); 3625 3626 return (error); 3627 } 3628 3629 static int 3630 smbfs_addmap(vnode_t * vp, offset_t off, struct as * as, caddr_t addr, 3631 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t * cr, 3632 caller_context_t * ct) 3633 { 3634 atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, btopr(len)); 3635 return (0); 3636 } 3637 3638 static int 3639 smbfs_delmap(vnode_t * vp, offset_t off, struct as * as, caddr_t addr, 3640 size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t * cr, 3641 caller_context_t * ct) 3642 { 3643 3644 smbnode_t *np; 3645 3646 atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, -btopr(len)); 3647 3648 /* 3649 * mark RDIRTY here, will be used to check if a file is dirty when 3650 * unmount smbfs 3651 */ 3652 if (vn_has_cached_data(vp) && !vn_is_readonly(vp) && (maxprot & PROT_WRITE) 3653 && (flags == MAP_SHARED)) { 3654 np = VTOSMB(vp); 3655 mutex_enter(&np->r_statelock); 3656 np->r_flags |= RDIRTY; 3657 mutex_exit(&np->r_statelock); 3658 } 3659 return (0); 3660 } 3661 3662 static int 3663 smbfs_putpage(vnode_t * vp, offset_t off, size_t len, int flags, 3664 cred_t * cr, caller_context_t * ct) 3665 { 3666 3667 smbnode_t *np; 3668 size_t io_len; 3669 u_offset_t io_off; 3670 u_offset_t eoff; 3671 int error = 0; 3672 page_t *pp; 3673 int rdirty; 3674 3675 np = VTOSMB(vp); 3676 3677 if (len == 0) { 3678 3679 /* will flush the whole file, so clear RDIRTY */ 3680 if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) { 3681 mutex_enter(&np->r_statelock); 3682 rdirty = np->r_flags & RDIRTY; 3683 np->r_flags &= ~RDIRTY; 3684 mutex_exit(&np->r_statelock); 3685 } else 3686 rdirty = 0; 3687 3688 error = pvn_vplist_dirty(vp, off, smbfs_putapage, flags, cr); 3689 3690 /* 3691 * if failed and the vnode was dirty before and we aren't 3692 * forcibly invalidating pages, then mark RDIRTY again. 3693 */ 3694 if (error && rdirty && 3695 (flags & (B_INVAL | B_FORCE)) != (B_INVAL | B_FORCE)) { 3696 mutex_enter(&np->r_statelock); 3697 np->r_flags |= RDIRTY; 3698 mutex_exit(&np->r_statelock); 3699 } 3700 } else { 3701 3702 eoff = off + len; 3703 3704 mutex_enter(&np->r_statelock); 3705 if (eoff > np->r_size) 3706 eoff = np->r_size; 3707 mutex_exit(&np->r_statelock); 3708 3709 for (io_off = off; io_off < eoff; io_off += io_len) { 3710 if ((flags & B_INVAL) || (flags & B_ASYNC) == 0) { 3711 pp = page_lookup(vp, io_off, 3712 (flags & (B_INVAL | B_FREE) ? SE_EXCL : SE_SHARED)); 3713 } else { 3714 pp = page_lookup_nowait(vp, io_off, 3715 (flags & B_FREE) ? SE_EXCL : SE_SHARED); 3716 } 3717 3718 if (pp == NULL || !pvn_getdirty(pp, flags)) 3719 io_len = PAGESIZE; 3720 else { 3721 error = smbfs_putapage(vp, pp, &io_off, &io_len, flags, cr); 3722 } 3723 } 3724 3725 } 3726 3727 return (error); 3728 } 3729 3730 static int 3731 smbfs_putapage(vnode_t * vp, page_t * pp, u_offset_t * offp, size_t * lenp, 3732 int flags, cred_t * cr) 3733 { 3734 3735 struct smb_cred scred; 3736 smbnode_t *np; 3737 smbmntinfo_t *smi; 3738 smb_share_t *ssp; 3739 uio_t uio; 3740 iovec_t uiov, uiov_bak; 3741 3742 size_t io_len; 3743 u_offset_t io_off; 3744 size_t limit; 3745 size_t bsize; 3746 size_t blksize; 3747 u_offset_t blkoff; 3748 int error; 3749 3750 np = VTOSMB(vp); 3751 smi = VTOSMI(vp); 3752 ssp = smi->smi_share; 3753 3754 /* do block io, get a kluster of dirty pages in a block. */ 3755 bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); 3756 blkoff = pp->p_offset / bsize; 3757 blkoff *= bsize; 3758 blksize = roundup(bsize, PAGESIZE); 3759 3760 pp = pvn_write_kluster(vp, pp, &io_off, &io_len, blkoff, blksize, flags); 3761 3762 ASSERT(pp->p_offset >= blkoff); 3763 3764 if (io_off + io_len > blkoff + blksize) { 3765 ASSERT((io_off + io_len) - (blkoff + blksize) < PAGESIZE); 3766 } 3767 3768 /* Don't allow put pages beyond EOF */ 3769 mutex_enter(&np->r_statelock); 3770 limit=MIN(np->r_size, blkoff + blksize); 3771 mutex_exit(&np->r_statelock); 3772 3773 if (io_off >= limit) { 3774 error = 0; 3775 goto out; 3776 } else if (io_off + io_len > limit) { 3777 int npages = btopr(limit - io_off); 3778 page_t *trunc; 3779 page_list_break(&pp, &trunc, npages); 3780 if (trunc) 3781 pvn_write_done(trunc, flags); 3782 io_len = limit - io_off; 3783 } 3784 3785 /* 3786 * Taken from NFS4. The RMODINPROGRESS flag makes sure that 3787 * smbfs_putapage() sees a consistent value of r_size. RMODINPROGRESS 3788 * is set in writenp(). When RMODINPROGRESS is set it indicates that 3789 * a uiomove() is in progress and the r_size has not been made 3790 * consistent with the new size of the file. When the uiomove() 3791 * completes the r_size is updated and the RMODINPROGRESS flag is 3792 * cleared. 3793 * 3794 * The RMODINPROGRESS flag makes sure that smbfs_putapage() sees a 3795 * consistent value of r_size. Without this handshaking, it is 3796 * possible that smbfs_putapage() picks up the old value of r_size 3797 * before the uiomove() in writenp() completes. This will result in 3798 * the write through smbfs_putapage() being dropped. 3799 * 3800 * More precisely, there is a window between the time the uiomove() 3801 * completes and the time the r_size is updated. If a VOP_PUTPAGE() 3802 * operation intervenes in this window, the page will be picked up, 3803 * because it is dirty (it will be unlocked, unless it was 3804 * pagecreate'd). When the page is picked up as dirty, the dirty bit 3805 * is reset (pvn_getdirty()). In smbfs_putapage(), r_size is checked. 3806 * This will still be the old size. Therefore the page will not be 3807 * written out. When segmap_release() calls VOP_PUTPAGE(), the page 3808 * will be found to be clean and the write will be dropped. 3809 */ 3810 if (np->r_flags & RMODINPROGRESS) { 3811 3812 mutex_enter(&np->r_statelock); 3813 if ((np->r_flags & RMODINPROGRESS) && 3814 np->r_modaddr + MAXBSIZE > io_off && 3815 np->r_modaddr < io_off + io_len) { 3816 page_t *plist; 3817 /* 3818 * A write is in progress for this region of the 3819 * file. If we did not detect RMODINPROGRESS here, 3820 * the data beyond the file size won't be write out. 3821 * We end up losing data. So we decide to set the 3822 * modified bit on each page in the page list and 3823 * mark the smbnode with RDIRTY. This write will be 3824 * restarted at some later time. 3825 */ 3826 plist = pp; 3827 while (plist != NULL) { 3828 pp = plist; 3829 page_sub(&plist, pp); 3830 hat_setmod(pp); 3831 page_io_unlock(pp); 3832 page_unlock(pp); 3833 } 3834 np->r_flags |= RDIRTY; 3835 mutex_exit(&np->r_statelock); 3836 if (offp) 3837 *offp = io_off; 3838 if (lenp) 3839 *lenp = io_len; 3840 return (0); 3841 } 3842 mutex_exit(&np->r_statelock); 3843 } 3844 3845 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 3846 return (EINTR); 3847 smb_credinit(&scred, cr); 3848 3849 if (np->n_vcgenid != ssp->ss_vcgenid) 3850 error = ESTALE; 3851 else { 3852 /* just use uio instead of buf, since smb_rwuio need uio. */ 3853 uiov.iov_base = 0; 3854 uiov.iov_len = 0; 3855 uio.uio_iov = &uiov; 3856 uio.uio_iovcnt = 1; 3857 uio.uio_loffset = io_off; 3858 uio.uio_resid = io_len; 3859 uio.uio_segflg = UIO_SYSSPACE; 3860 uio.uio_llimit = MAXOFFSET_T; 3861 /* map pages into kernel address space, and setup uio. */ 3862 error = uio_page_mapin(&uio, pp); 3863 if (error == 0) { 3864 uiov_bak.iov_base = uiov.iov_base; 3865 uiov_bak.iov_len = uiov.iov_len; 3866 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE, &uio, &scred, smb_timo_write); 3867 if (error == 0) { 3868 mutex_enter(&np->r_statelock); 3869 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 3870 mutex_exit(&np->r_statelock); 3871 (void) smbfs_smb_flush(np, &scred); 3872 } 3873 /* unmap pages from kernel address space. */ 3874 uio.uio_iov = &uiov_bak; 3875 uio_page_mapout(&uio, pp); 3876 } 3877 } 3878 3879 smb_credrele(&scred); 3880 smbfs_rw_exit(&np->r_lkserlock); 3881 3882 out: 3883 pvn_write_done(pp, ((error) ? B_ERROR : 0) | B_WRITE | flags); 3884 3885 if (offp) 3886 *offp = io_off; 3887 if (lenp) 3888 *lenp = io_len; 3889 3890 return (error); 3891 } 3892 3893 static int 3894 smbfs_getpage(vnode_t * vp, offset_t off, size_t len, uint_t * protp, 3895 page_t * pl[], size_t plsz, struct seg * seg, caddr_t addr, 3896 enum seg_rw rw, cred_t * cr, caller_context_t * ct) 3897 { 3898 3899 smbnode_t *np; 3900 int error; 3901 3902 /* these pages have all protections. */ 3903 if (protp) 3904 *protp = PROT_ALL; 3905 3906 np = VTOSMB(vp); 3907 3908 /* Don't allow get pages beyond EOF, unless it's segkmap. */ 3909 mutex_enter(&np->r_statelock); 3910 if (off + len > np->r_size + PAGESIZE && seg != segkmap){ 3911 mutex_exit(&np->r_statelock); 3912 return (EFAULT); 3913 } 3914 mutex_exit(&np->r_statelock); 3915 3916 if (len <= PAGESIZE) { 3917 error = smbfs_getapage(vp, off, len, protp, pl, plsz, seg, addr, rw, 3918 cr); 3919 } else { 3920 error = pvn_getpages(smbfs_getapage, vp, off, len, protp, pl, plsz, seg, 3921 addr, rw, cr); 3922 } 3923 3924 return (error); 3925 } 3926 3927 static int 3928 smbfs_getapage(vnode_t * vp, u_offset_t off, size_t len, 3929 uint_t * protp, page_t * pl[], size_t plsz, struct seg * seg, caddr_t addr, 3930 enum seg_rw rw, cred_t * cr) 3931 { 3932 3933 smbnode_t *np; 3934 smbmntinfo_t *smi; 3935 smb_share_t *ssp; 3936 smb_cred_t scred; 3937 3938 page_t *pp; 3939 uio_t uio; 3940 iovec_t uiov, uiov_bak; 3941 3942 u_offset_t blkoff; 3943 size_t bsize; 3944 size_t blksize; 3945 3946 u_offset_t io_off; 3947 size_t io_len; 3948 size_t pages_len; 3949 3950 int error = 0; 3951 3952 np = VTOSMB(vp); 3953 smi = VTOSMI(vp); 3954 ssp = smi->smi_share; 3955 3956 /* if pl is null,it's meaningless */ 3957 if (pl == NULL) 3958 return (EFAULT); 3959 3960 again: 3961 if (page_exists(vp, off) == NULL) { 3962 if (rw == S_CREATE) { 3963 /* just return a empty page if asked to create. */ 3964 if ((pp = page_create_va(vp, off, PAGESIZE, PG_WAIT | PG_EXCL, seg, addr)) == NULL) 3965 goto again; 3966 pages_len = PAGESIZE; 3967 } else { 3968 3969 /* 3970 * do block io, get a kluster of non-exist pages in a 3971 * block. 3972 */ 3973 bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); 3974 blkoff = off / bsize; 3975 blkoff *= bsize; 3976 blksize = roundup(bsize, PAGESIZE); 3977 3978 pp = pvn_read_kluster(vp, off, seg, addr, &io_off, &io_len, blkoff, blksize, 0); 3979 3980 if (pp == NULL) 3981 goto again; 3982 3983 pages_len = io_len; 3984 3985 /* Don't need to get pages from server if it's segkmap 3986 * that reads beyond EOF. */ 3987 mutex_enter(&np->r_statelock); 3988 if (io_off >= np->r_size && seg == segkmap) { 3989 mutex_exit(&np->r_statelock); 3990 error = 0; 3991 goto out; 3992 } else if (io_off + io_len > np->r_size) { 3993 int npages = btopr(np->r_size - io_off); 3994 page_t *trunc; 3995 3996 page_list_break(&pp, &trunc, npages); 3997 if (trunc) 3998 pvn_read_done(trunc, 0); 3999 io_len = np->r_size - io_off; 4000 } 4001 mutex_exit(&np->r_statelock); 4002 4003 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 4004 return EINTR; 4005 smb_credinit(&scred, cr); 4006 4007 /* 4008 * just use uio instead of buf, since smb_rwuio need 4009 * uio. 4010 */ 4011 uiov.iov_base = 0; 4012 uiov.iov_len = 0; 4013 uio.uio_iov = &uiov; 4014 uio.uio_iovcnt = 1; 4015 uio.uio_loffset = io_off; 4016 uio.uio_resid = io_len; 4017 uio.uio_segflg = UIO_SYSSPACE; 4018 uio.uio_llimit = MAXOFFSET_T; 4019 4020 /* 4021 * map pages into kernel address space, and setup 4022 * uio. 4023 */ 4024 error = uio_page_mapin(&uio, pp); 4025 if (error == 0) { 4026 uiov_bak.iov_base = uiov.iov_base; 4027 uiov_bak.iov_len = uiov.iov_len; 4028 error = smb_rwuio(ssp, np->n_fid, UIO_READ, &uio, &scred, smb_timo_read); 4029 /* unmap pages from kernel address space. */ 4030 uio.uio_iov = &uiov_bak; 4031 uio_page_mapout(&uio, pp); 4032 } 4033 smb_credrele(&scred); 4034 smbfs_rw_exit(&np->r_lkserlock); 4035 } 4036 } else { 4037 se_t se = rw == S_CREATE ? SE_EXCL : SE_SHARED; 4038 if ((pp = page_lookup(vp, off, se)) == NULL) { 4039 goto again; 4040 } 4041 } 4042 4043 out: 4044 if (pp) { 4045 if (error) { 4046 pvn_read_done(pp, B_ERROR); 4047 } else { 4048 /* init page list, unlock pages. */ 4049 pvn_plist_init(pp, pl, plsz, off, pages_len, rw); 4050 } 4051 } 4052 return (error); 4053 } 4054 4055 /* correspond to nfs_invalidate_pages() in nfs_client.c */ 4056 void 4057 smbfs_invalidate_pages(vnode_t * vp, u_offset_t off, cred_t * cr) 4058 { 4059 4060 smbnode_t *np; 4061 4062 np = VTOSMB(vp); 4063 /* will flush the whole file, so clear RDIRTY */ 4064 if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) { 4065 mutex_enter(&np->r_statelock); 4066 np->r_flags &= ~RDIRTY; 4067 mutex_exit(&np->r_statelock); 4068 } 4069 (void) pvn_vplist_dirty(vp, off, smbfs_putapage, B_INVAL | B_TRUNC, cr); 4070 }