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 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 np = VTOSMB(vp); 664 smi = VTOSMI(vp); 665 ssp = smi->smi_share; 666 667 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 668 return (EIO); 669 670 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 671 return (EIO); 672 673 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER)); 674 675 if (vp->v_type != VREG) 676 return (EISDIR); 677 678 if (uiop->uio_resid == 0) 679 return (0); 680 681 /* 682 * Like NFS3, just check for 63-bit overflow. 683 * Our SMB layer takes care to return EFBIG 684 * when it has to fallback to a 32-bit call. 685 */ 686 endoff = uiop->uio_loffset + uiop->uio_resid; 687 if (uiop->uio_loffset < 0 || endoff < 0) 688 return (EINVAL); 689 690 /* get vnode attributes from server */ 691 va.va_mask = AT_SIZE | AT_MTIME; 692 if (error = smbfsgetattr(vp, &va, cr)) 693 return (error); 694 695 /* Update mtime with mtime from server here? */ 696 697 /* if offset is beyond EOF, read nothing */ 698 if (uiop->uio_loffset >= va.va_size) 699 return (0); 700 701 /* 702 * Limit the read to the remaining file size. 703 * Do this by temporarily reducing uio_resid 704 * by the amount the lies beyoned the EOF. 705 */ 706 if (endoff > va.va_size) { 707 past_eof = (ssize_t)(endoff - va.va_size); 708 uiop->uio_resid -= past_eof; 709 } else 710 past_eof = 0; 711 712 /* Shared lock for n_fid use in smb_rwuio */ 713 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 714 return (EINTR); 715 smb_credinit(&scred, cr); 716 717 /* After reconnect, n_fid is invalid */ 718 if (np->n_vcgenid != ssp->ss_vcgenid) 719 error = ESTALE; 720 else 721 error = smb_rwuio(ssp, np->n_fid, UIO_READ, 722 uiop, &scred, smb_timo_read); 723 724 smb_credrele(&scred); 725 smbfs_rw_exit(&np->r_lkserlock); 726 727 /* undo adjustment of resid */ 728 uiop->uio_resid += past_eof; 729 730 return (error); 731 } 732 733 734 /* ARGSUSED */ 735 static int 736 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, 737 caller_context_t *ct) 738 { 739 struct smb_cred scred; 740 struct vattr va; 741 smbnode_t *np; 742 smbmntinfo_t *smi; 743 smb_share_t *ssp; 744 offset_t endoff, limit; 745 ssize_t past_limit; 746 int error, timo; 747 748 np = VTOSMB(vp); 749 smi = VTOSMI(vp); 750 ssp = smi->smi_share; 751 752 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 753 return (EIO); 754 755 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 756 return (EIO); 757 758 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER)); 759 760 if (vp->v_type != VREG) 761 return (EISDIR); 762 763 if (uiop->uio_resid == 0) 764 return (0); 765 766 /* 767 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC) 768 */ 769 if (ioflag & (FAPPEND | FSYNC)) { 770 if (np->n_flag & NMODIFIED) { 771 smbfs_attrcache_remove(np); 772 /* XXX: smbfs_vinvalbuf? */ 773 } 774 } 775 if (ioflag & FAPPEND) { 776 /* 777 * File size can be changed by another client 778 */ 779 va.va_mask = AT_SIZE; 780 if (error = smbfsgetattr(vp, &va, cr)) 781 return (error); 782 uiop->uio_loffset = va.va_size; 783 } 784 785 /* 786 * Like NFS3, just check for 63-bit overflow. 787 */ 788 endoff = uiop->uio_loffset + uiop->uio_resid; 789 if (uiop->uio_loffset < 0 || endoff < 0) 790 return (EINVAL); 791 792 /* 793 * Check to make sure that the process will not exceed 794 * its limit on file size. It is okay to write up to 795 * the limit, but not beyond. Thus, the write which 796 * reaches the limit will be short and the next write 797 * will return an error. 798 * 799 * So if we're starting at or beyond the limit, EFBIG. 800 * Otherwise, temporarily reduce resid to the amount 801 * the falls after the limit. 802 */ 803 limit = uiop->uio_llimit; 804 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) 805 limit = MAXOFFSET_T; 806 if (uiop->uio_loffset >= limit) 807 return (EFBIG); 808 if (endoff > limit) { 809 past_limit = (ssize_t)(endoff - limit); 810 uiop->uio_resid -= past_limit; 811 } else 812 past_limit = 0; 813 814 /* Timeout: longer for append. */ 815 timo = smb_timo_write; 816 if (endoff > np->r_size) 817 timo = smb_timo_append; 818 819 /* Shared lock for n_fid use in smb_rwuio */ 820 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 821 return (EINTR); 822 smb_credinit(&scred, cr); 823 824 /* After reconnect, n_fid is invalid */ 825 if (np->n_vcgenid != ssp->ss_vcgenid) 826 error = ESTALE; 827 else 828 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE, 829 uiop, &scred, timo); 830 831 if (error == 0) { 832 mutex_enter(&np->r_statelock); 833 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 834 if (uiop->uio_loffset > (offset_t)np->r_size) 835 np->r_size = (len_t)uiop->uio_loffset; 836 mutex_exit(&np->r_statelock); 837 if (ioflag & (FSYNC|FDSYNC)) { 838 /* Don't error the I/O if this fails. */ 839 (void) smbfs_smb_flush(np, &scred); 840 } 841 } 842 843 smb_credrele(&scred); 844 smbfs_rw_exit(&np->r_lkserlock); 845 846 /* undo adjustment of resid */ 847 uiop->uio_resid += past_limit; 848 849 return (error); 850 } 851 852 853 /* ARGSUSED */ 854 static int 855 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, 856 cred_t *cr, int *rvalp, caller_context_t *ct) 857 { 858 int error; 859 smbmntinfo_t *smi; 860 861 smi = VTOSMI(vp); 862 863 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 864 return (EIO); 865 866 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 867 return (EIO); 868 869 switch (cmd) { 870 /* First three from ZFS. XXX - need these? */ 871 872 case _FIOFFS: 873 error = smbfs_fsync(vp, 0, cr, ct); 874 break; 875 876 /* 877 * The following two ioctls are used by bfu. 878 * Silently ignore to avoid bfu errors. 879 */ 880 case _FIOGDIO: 881 case _FIOSDIO: 882 error = 0; 883 break; 884 885 #ifdef NOT_YET /* XXX - from the NFS code. */ 886 case _FIODIRECTIO: 887 error = smbfs_directio(vp, (int)arg, cr); 888 #endif 889 890 /* 891 * Allow get/set with "raw" security descriptor (SD) data. 892 * Useful for testing, diagnosing idmap problems, etc. 893 */ 894 case SMBFSIO_GETSD: 895 error = smbfs_acl_iocget(vp, arg, flag, cr); 896 break; 897 898 case SMBFSIO_SETSD: 899 error = smbfs_acl_iocset(vp, arg, flag, cr); 900 break; 901 902 default: 903 error = ENOTTY; 904 break; 905 } 906 907 return (error); 908 } 909 910 911 /* 912 * Return either cached or remote attributes. If get remote attr 913 * use them to check and invalidate caches, then cache the new attributes. 914 * 915 * XXX 916 * This op should eventually support PSARC 2007/315, Extensible Attribute 917 * Interfaces, for richer metadata. 918 */ 919 /* ARGSUSED */ 920 static int 921 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 922 caller_context_t *ct) 923 { 924 smbnode_t *np; 925 smbmntinfo_t *smi; 926 927 smi = VTOSMI(vp); 928 929 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 930 return (EIO); 931 932 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 933 return (EIO); 934 935 /* 936 * If it has been specified that the return value will 937 * just be used as a hint, and we are only being asked 938 * for size, fsid or rdevid, then return the client's 939 * notion of these values without checking to make sure 940 * that the attribute cache is up to date. 941 * The whole point is to avoid an over the wire GETATTR 942 * call. 943 */ 944 np = VTOSMB(vp); 945 if (flags & ATTR_HINT) { 946 if (vap->va_mask == 947 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) { 948 mutex_enter(&np->r_statelock); 949 if (vap->va_mask | AT_SIZE) 950 vap->va_size = np->r_size; 951 if (vap->va_mask | AT_FSID) 952 vap->va_fsid = vp->v_vfsp->vfs_dev; 953 if (vap->va_mask | AT_RDEV) 954 vap->va_rdev = vp->v_rdev; 955 mutex_exit(&np->r_statelock); 956 return (0); 957 } 958 } 959 960 return (smbfsgetattr(vp, vap, cr)); 961 } 962 963 /* smbfsgetattr() in smbfs_client.c */ 964 965 /* 966 * XXX 967 * This op should eventually support PSARC 2007/315, Extensible Attribute 968 * Interfaces, for richer metadata. 969 */ 970 /*ARGSUSED4*/ 971 static int 972 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 973 caller_context_t *ct) 974 { 975 vfs_t *vfsp; 976 smbmntinfo_t *smi; 977 int error; 978 uint_t mask; 979 struct vattr oldva; 980 981 vfsp = vp->v_vfsp; 982 smi = VFTOSMI(vfsp); 983 984 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 985 return (EIO); 986 987 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 988 return (EIO); 989 990 mask = vap->va_mask; 991 if (mask & AT_NOSET) 992 return (EINVAL); 993 994 if (vfsp->vfs_flag & VFS_RDONLY) 995 return (EROFS); 996 997 /* 998 * This is a _local_ access check so that only the owner of 999 * this mount can set attributes. With ACLs enabled, the 1000 * file owner can be different from the mount owner, and we 1001 * need to check the _mount_ owner here. See _access_rwx 1002 */ 1003 bzero(&oldva, sizeof (oldva)); 1004 oldva.va_mask = AT_TYPE | AT_MODE; 1005 error = smbfsgetattr(vp, &oldva, cr); 1006 if (error) 1007 return (error); 1008 oldva.va_mask |= AT_UID | AT_GID; 1009 oldva.va_uid = smi->smi_uid; 1010 oldva.va_gid = smi->smi_gid; 1011 1012 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 1013 smbfs_accessx, vp); 1014 if (error) 1015 return (error); 1016 1017 if (mask & (AT_UID | AT_GID)) { 1018 if (smi->smi_flags & SMI_ACL) 1019 error = smbfs_acl_setids(vp, vap, cr); 1020 else 1021 error = ENOSYS; 1022 if (error != 0) { 1023 SMBVDEBUG("error %d seting UID/GID on %s", 1024 error, VTOSMB(vp)->n_rpath); 1025 /* 1026 * It might be more correct to return the 1027 * error here, but that causes complaints 1028 * when root extracts a cpio archive, etc. 1029 * So ignore this error, and go ahead with 1030 * the rest of the setattr work. 1031 */ 1032 } 1033 } 1034 1035 return (smbfssetattr(vp, vap, flags, cr)); 1036 } 1037 1038 /* 1039 * Mostly from Darwin smbfs_setattr() 1040 * but then modified a lot. 1041 */ 1042 /* ARGSUSED */ 1043 static int 1044 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) 1045 { 1046 int error = 0; 1047 smbnode_t *np = VTOSMB(vp); 1048 uint_t mask = vap->va_mask; 1049 struct timespec *mtime, *atime; 1050 struct smb_cred scred; 1051 int cerror, modified = 0; 1052 unsigned short fid; 1053 int have_fid = 0; 1054 uint32_t rights = 0; 1055 1056 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone); 1057 1058 /* 1059 * There are no settable attributes on the XATTR dir, 1060 * so just silently ignore these. On XATTR files, 1061 * you can set the size but nothing else. 1062 */ 1063 if (vp->v_flag & V_XATTRDIR) 1064 return (0); 1065 if (np->n_flag & N_XATTR) { 1066 if (mask & AT_TIMES) 1067 SMBVDEBUG("ignore set time on xattr\n"); 1068 mask &= AT_SIZE; 1069 } 1070 1071 /* 1072 * If our caller is trying to set multiple attributes, they 1073 * can make no assumption about what order they are done in. 1074 * Here we try to do them in order of decreasing likelihood 1075 * of failure, just to minimize the chance we'll wind up 1076 * with a partially complete request. 1077 */ 1078 1079 /* Shared lock for (possible) n_fid use. */ 1080 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1081 return (EINTR); 1082 smb_credinit(&scred, cr); 1083 1084 /* 1085 * Will we need an open handle for this setattr? 1086 * If so, what rights will we need? 1087 */ 1088 if (mask & (AT_ATIME | AT_MTIME)) { 1089 rights |= 1090 SA_RIGHT_FILE_WRITE_ATTRIBUTES; 1091 } 1092 if (mask & AT_SIZE) { 1093 rights |= 1094 SA_RIGHT_FILE_WRITE_DATA | 1095 SA_RIGHT_FILE_APPEND_DATA; 1096 } 1097 1098 /* 1099 * Only SIZE really requires a handle, but it's 1100 * simpler and more reliable to set via a handle. 1101 * Some servers like NT4 won't set times by path. 1102 * Also, we're usually setting everything anyway. 1103 */ 1104 if (mask & (AT_SIZE | AT_ATIME | AT_MTIME)) { 1105 error = smbfs_smb_tmpopen(np, rights, &scred, &fid); 1106 if (error) { 1107 SMBVDEBUG("error %d opening %s\n", 1108 error, np->n_rpath); 1109 goto out; 1110 } 1111 have_fid = 1; 1112 } 1113 1114 /* 1115 * If the server supports the UNIX extensions, right here is where 1116 * we'd support changes to uid, gid, mode, and possibly va_flags. 1117 * For now we claim to have made any such changes. 1118 */ 1119 1120 if (mask & AT_SIZE) { 1121 /* 1122 * If the new file size is less than what the client sees as 1123 * the file size, then just change the size and invalidate 1124 * the pages. 1125 * I am commenting this code at present because the function 1126 * smbfs_putapage() is not yet implemented. 1127 */ 1128 1129 /* 1130 * Set the file size to vap->va_size. 1131 */ 1132 ASSERT(have_fid); 1133 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred); 1134 if (error) { 1135 SMBVDEBUG("setsize error %d file %s\n", 1136 error, np->n_rpath); 1137 } else { 1138 /* 1139 * Darwin had code here to zero-extend. 1140 * Tests indicate the server will zero-fill, 1141 * so looks like we don't need to do this. 1142 * Good thing, as this could take forever. 1143 * 1144 * XXX: Reportedly, writing one byte of zero 1145 * at the end offset avoids problems here. 1146 */ 1147 mutex_enter(&np->r_statelock); 1148 np->r_size = vap->va_size; 1149 mutex_exit(&np->r_statelock); 1150 modified = 1; 1151 } 1152 } 1153 1154 /* 1155 * XXX: When Solaris has create_time, set that too. 1156 * Note: create_time is different from ctime. 1157 */ 1158 mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0); 1159 atime = ((mask & AT_ATIME) ? &vap->va_atime : 0); 1160 1161 if (mtime || atime) { 1162 /* 1163 * Always use the handle-based set attr call now. 1164 * Not trying to set DOS attributes here so pass zero. 1165 */ 1166 ASSERT(have_fid); 1167 error = smbfs_smb_setfattr(np, fid, 1168 0, mtime, atime, &scred); 1169 if (error) { 1170 SMBVDEBUG("set times error %d file %s\n", 1171 error, np->n_rpath); 1172 } else { 1173 modified = 1; 1174 } 1175 } 1176 1177 out: 1178 if (modified) { 1179 /* 1180 * Invalidate attribute cache in case the server 1181 * doesn't set exactly the attributes we asked. 1182 */ 1183 smbfs_attrcache_remove(np); 1184 } 1185 1186 if (have_fid) { 1187 cerror = smbfs_smb_tmpclose(np, fid, &scred); 1188 if (cerror) 1189 SMBVDEBUG("error %d closing %s\n", 1190 cerror, np->n_rpath); 1191 } 1192 1193 smb_credrele(&scred); 1194 smbfs_rw_exit(&np->r_lkserlock); 1195 1196 return (error); 1197 } 1198 1199 /* 1200 * smbfs_access_rwx() 1201 * Common function for smbfs_access, etc. 1202 * 1203 * The security model implemented by the FS is unusual 1204 * due to the current "single user mounts" restriction: 1205 * All access under a given mount point uses the CIFS 1206 * credentials established by the owner of the mount. 1207 * 1208 * Most access checking is handled by the CIFS server, 1209 * but we need sufficient Unix access checks here to 1210 * prevent other local Unix users from having access 1211 * to objects under this mount that the uid/gid/mode 1212 * settings in the mount would not allow. 1213 * 1214 * With this model, there is a case where we need the 1215 * ability to do an access check before we have the 1216 * vnode for an object. This function takes advantage 1217 * of the fact that the uid/gid/mode is per mount, and 1218 * avoids the need for a vnode. 1219 * 1220 * We still (sort of) need a vnode when we call 1221 * secpolicy_vnode_access, but that only uses 1222 * the vtype field, so we can use a pair of fake 1223 * vnodes that have only v_type filled in. 1224 * 1225 * XXX: Later, add a new secpolicy_vtype_access() 1226 * that takes the vtype instead of a vnode, and 1227 * get rid of the tmpl_vxxx fake vnodes below. 1228 */ 1229 static int 1230 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr) 1231 { 1232 /* See the secpolicy call below. */ 1233 static const vnode_t tmpl_vdir = { .v_type = VDIR }; 1234 static const vnode_t tmpl_vreg = { .v_type = VREG }; 1235 vattr_t va; 1236 vnode_t *tvp; 1237 struct smbmntinfo *smi = VFTOSMI(vfsp); 1238 int shift = 0; 1239 1240 /* 1241 * Build our (fabricated) vnode attributes. 1242 * XXX: Could make these templates in the 1243 * per-mount struct and use them here. 1244 */ 1245 bzero(&va, sizeof (va)); 1246 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 1247 va.va_type = vtype; 1248 va.va_mode = (vtype == VDIR) ? 1249 smi->smi_dmode : smi->smi_fmode; 1250 va.va_uid = smi->smi_uid; 1251 va.va_gid = smi->smi_gid; 1252 1253 /* 1254 * Disallow write attempts on read-only file systems, 1255 * unless the file is a device or fifo node. Note: 1256 * Inline vn_is_readonly and IS_DEVVP here because 1257 * we may not have a vnode ptr. Original expr. was: 1258 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp)) 1259 */ 1260 if ((mode & VWRITE) && 1261 (vfsp->vfs_flag & VFS_RDONLY) && 1262 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO)) 1263 return (EROFS); 1264 1265 /* 1266 * Disallow attempts to access mandatory lock files. 1267 * Similarly, expand MANDLOCK here. 1268 * XXX: not sure we need this. 1269 */ 1270 if ((mode & (VWRITE | VREAD | VEXEC)) && 1271 va.va_type == VREG && MANDMODE(va.va_mode)) 1272 return (EACCES); 1273 1274 /* 1275 * Access check is based on only 1276 * one of owner, group, public. 1277 * If not owner, then check group. 1278 * If not a member of the group, 1279 * then check public access. 1280 */ 1281 if (crgetuid(cr) != va.va_uid) { 1282 shift += 3; 1283 if (!groupmember(va.va_gid, cr)) 1284 shift += 3; 1285 } 1286 1287 /* 1288 * We need a vnode for secpolicy_vnode_access, 1289 * but the only thing it looks at is v_type, 1290 * so pass one of the templates above. 1291 */ 1292 tvp = (va.va_type == VDIR) ? 1293 (vnode_t *)&tmpl_vdir : 1294 (vnode_t *)&tmpl_vreg; 1295 1296 return (secpolicy_vnode_access2(cr, tvp, va.va_uid, 1297 va.va_mode << shift, mode)); 1298 } 1299 1300 /* 1301 * See smbfs_setattr 1302 */ 1303 static int 1304 smbfs_accessx(void *arg, int mode, cred_t *cr) 1305 { 1306 vnode_t *vp = arg; 1307 /* 1308 * Note: The caller has checked the current zone, 1309 * the SMI_DEAD and VFS_UNMOUNTED flags, etc. 1310 */ 1311 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr)); 1312 } 1313 1314 /* 1315 * XXX 1316 * This op should support PSARC 2007/403, Modified Access Checks for CIFS 1317 */ 1318 /* ARGSUSED */ 1319 static int 1320 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct) 1321 { 1322 vfs_t *vfsp; 1323 smbmntinfo_t *smi; 1324 1325 vfsp = vp->v_vfsp; 1326 smi = VFTOSMI(vfsp); 1327 1328 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1329 return (EIO); 1330 1331 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1332 return (EIO); 1333 1334 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr)); 1335 } 1336 1337 1338 /* 1339 * Flush local dirty pages to stable storage on the server. 1340 * 1341 * If FNODSYNC is specified, then there is nothing to do because 1342 * metadata changes are not cached on the client before being 1343 * sent to the server. 1344 */ 1345 /* ARGSUSED */ 1346 static int 1347 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) 1348 { 1349 int error = 0; 1350 smbmntinfo_t *smi; 1351 smbnode_t *np; 1352 struct smb_cred scred; 1353 1354 np = VTOSMB(vp); 1355 smi = VTOSMI(vp); 1356 1357 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1358 return (EIO); 1359 1360 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 1361 return (EIO); 1362 1363 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp)) 1364 return (0); 1365 1366 if ((syncflag & (FSYNC|FDSYNC)) == 0) 1367 return (0); 1368 1369 /* Shared lock for n_fid use in _flush */ 1370 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1371 return (EINTR); 1372 smb_credinit(&scred, cr); 1373 1374 error = smbfs_smb_flush(np, &scred); 1375 1376 smb_credrele(&scred); 1377 smbfs_rw_exit(&np->r_lkserlock); 1378 1379 return (error); 1380 } 1381 1382 /* 1383 * Last reference to vnode went away. 1384 */ 1385 /* ARGSUSED */ 1386 static void 1387 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 1388 { 1389 smbnode_t *np; 1390 struct smb_cred scred; 1391 1392 /* 1393 * Don't "bail out" for VFS_UNMOUNTED here, 1394 * as we want to do cleanup, etc. 1395 * See also pcfs_inactive 1396 */ 1397 1398 np = VTOSMB(vp); 1399 1400 /* 1401 * If this is coming from the wrong zone, we let someone in the right 1402 * zone take care of it asynchronously. We can get here due to 1403 * VN_RELE() being called from pageout() or fsflush(). This call may 1404 * potentially turn into an expensive no-op if, for instance, v_count 1405 * gets incremented in the meantime, but it's still correct. 1406 */ 1407 1408 /* 1409 * Defend against the possibility that higher-level callers 1410 * might not correctly balance open and close calls. If we 1411 * get here with open references remaining, it means there 1412 * was a missing VOP_CLOSE somewhere. If that happens, do 1413 * the close here so we don't "leak" FIDs on the server. 1414 * 1415 * Exclusive lock for modifying n_fid stuff. 1416 * Don't want this one ever interruptible. 1417 */ 1418 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 1419 smb_credinit(&scred, cr); 1420 1421 switch (np->n_ovtype) { 1422 case VNON: 1423 /* not open (OK) */ 1424 break; 1425 1426 case VDIR: 1427 if (np->n_dirrefs == 0) 1428 break; 1429 SMBVDEBUG("open dir: refs %d path %s\n", 1430 np->n_dirrefs, np->n_rpath); 1431 /* Force last close. */ 1432 np->n_dirrefs = 1; 1433 smbfs_rele_fid(np, &scred); 1434 break; 1435 1436 case VREG: 1437 if (np->n_fidrefs == 0) 1438 break; 1439 SMBVDEBUG("open file: refs %d id 0x%x path %s\n", 1440 np->n_fidrefs, np->n_fid, np->n_rpath); 1441 /* 1442 * Before otW close, make sure dirty pages written back. 1443 */ 1444 if (vn_has_cached_data(vp)) { 1445 /* smbfs_putapage() will acquire shared lock, so release 1446 * exclusive lock temporally. 1447 */ 1448 smbfs_rw_exit(&np->r_lkserlock); 1449 1450 (void) smbfs_putpage(vp, (offset_t) 0, 0, B_INVAL | B_ASYNC, cr, ct); 1451 1452 /* acquire exclusive lock again. */ 1453 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 1454 } 1455 /* Force last close. */ 1456 np->n_fidrefs = 1; 1457 smbfs_rele_fid(np, &scred); 1458 break; 1459 1460 default: 1461 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype); 1462 np->n_ovtype = VNON; 1463 break; 1464 } 1465 1466 smb_credrele(&scred); 1467 smbfs_rw_exit(&np->r_lkserlock); 1468 1469 smbfs_addfree(np); 1470 } 1471 1472 /* 1473 * Remote file system operations having to do with directory manipulation. 1474 */ 1475 /* ARGSUSED */ 1476 static int 1477 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, 1478 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, 1479 int *direntflags, pathname_t *realpnp) 1480 { 1481 vfs_t *vfs; 1482 smbmntinfo_t *smi; 1483 smbnode_t *dnp; 1484 int error; 1485 1486 vfs = dvp->v_vfsp; 1487 smi = VFTOSMI(vfs); 1488 1489 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1490 return (EPERM); 1491 1492 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED) 1493 return (EIO); 1494 1495 dnp = VTOSMB(dvp); 1496 1497 /* 1498 * Are we looking up extended attributes? If so, "dvp" is 1499 * the file or directory for which we want attributes, and 1500 * we need a lookup of the (faked up) attribute directory 1501 * before we lookup the rest of the path. 1502 */ 1503 if (flags & LOOKUP_XATTR) { 1504 /* 1505 * Require the xattr mount option. 1506 */ 1507 if ((vfs->vfs_flag & VFS_XATTR) == 0) 1508 return (EINVAL); 1509 1510 error = smbfs_get_xattrdir(dvp, vpp, cr, flags); 1511 return (error); 1512 } 1513 1514 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp))) 1515 return (EINTR); 1516 1517 error = smbfslookup(dvp, nm, vpp, cr, 1, ct); 1518 1519 smbfs_rw_exit(&dnp->r_rwlock); 1520 1521 return (error); 1522 } 1523 1524 /* ARGSUSED */ 1525 static int 1526 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, 1527 int cache_ok, caller_context_t *ct) 1528 { 1529 int error; 1530 int supplen; /* supported length */ 1531 vnode_t *vp; 1532 smbnode_t *np; 1533 smbnode_t *dnp; 1534 smbmntinfo_t *smi; 1535 /* struct smb_vc *vcp; */ 1536 const char *ill; 1537 const char *name = (const char *)nm; 1538 int nmlen = strlen(nm); 1539 int rplen; 1540 struct smb_cred scred; 1541 struct smbfattr fa; 1542 1543 smi = VTOSMI(dvp); 1544 dnp = VTOSMB(dvp); 1545 1546 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone); 1547 1548 #ifdef NOT_YET 1549 vcp = SSTOVC(smi->smi_share); 1550 1551 /* XXX: Should compute this once and store it in smbmntinfo_t */ 1552 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12; 1553 #else 1554 supplen = 255; 1555 #endif 1556 1557 /* 1558 * RWlock must be held, either reader or writer. 1559 * XXX: Can we check without looking directly 1560 * inside the struct smbfs_rwlock_t? 1561 */ 1562 ASSERT(dnp->r_rwlock.count != 0); 1563 1564 /* 1565 * If lookup is for "", just return dvp. 1566 * No need to perform any access checks. 1567 */ 1568 if (nmlen == 0) { 1569 VN_HOLD(dvp); 1570 *vpp = dvp; 1571 return (0); 1572 } 1573 1574 /* 1575 * Can't do lookups in non-directories. 1576 */ 1577 if (dvp->v_type != VDIR) 1578 return (ENOTDIR); 1579 1580 /* 1581 * Need search permission in the directory. 1582 */ 1583 error = smbfs_access(dvp, VEXEC, 0, cr, ct); 1584 if (error) 1585 return (error); 1586 1587 /* 1588 * If lookup is for ".", just return dvp. 1589 * Access check was done above. 1590 */ 1591 if (nmlen == 1 && name[0] == '.') { 1592 VN_HOLD(dvp); 1593 *vpp = dvp; 1594 return (0); 1595 } 1596 1597 /* 1598 * Now some sanity checks on the name. 1599 * First check the length. 1600 */ 1601 if (nmlen > supplen) 1602 return (ENAMETOOLONG); 1603 1604 /* 1605 * Avoid surprises with characters that are 1606 * illegal in Windows file names. 1607 * Todo: CATIA mappings XXX 1608 */ 1609 ill = illegal_chars; 1610 if (dnp->n_flag & N_XATTR) 1611 ill++; /* allow colon */ 1612 if (strpbrk(nm, ill)) 1613 return (EINVAL); 1614 1615 /* 1616 * Special handling for lookup of ".." 1617 * 1618 * We keep full pathnames (as seen on the server) 1619 * so we can just trim off the last component to 1620 * get the full pathname of the parent. Note: 1621 * We don't actually copy and modify, but just 1622 * compute the trimmed length and pass that with 1623 * the current dir path (not null terminated). 1624 * 1625 * We don't go over-the-wire to get attributes 1626 * for ".." because we know it's a directory, 1627 * and we can just leave the rest "stale" 1628 * until someone does a getattr. 1629 */ 1630 if (nmlen == 2 && name[0] == '.' && name[1] == '.') { 1631 if (dvp->v_flag & VROOT) { 1632 /* 1633 * Already at the root. This can happen 1634 * with directory listings at the root, 1635 * which lookup "." and ".." to get the 1636 * inode numbers. Let ".." be the same 1637 * as "." in the FS root. 1638 */ 1639 VN_HOLD(dvp); 1640 *vpp = dvp; 1641 return (0); 1642 } 1643 1644 /* 1645 * Special case for XATTR directory 1646 */ 1647 if (dvp->v_flag & V_XATTRDIR) { 1648 error = smbfs_xa_parent(dvp, vpp); 1649 return (error); 1650 } 1651 1652 /* 1653 * Find the parent path length. 1654 */ 1655 rplen = dnp->n_rplen; 1656 ASSERT(rplen > 0); 1657 while (--rplen >= 0) { 1658 if (dnp->n_rpath[rplen] == '\\') 1659 break; 1660 } 1661 if (rplen <= 0) { 1662 /* Found our way to the root. */ 1663 vp = SMBTOV(smi->smi_root); 1664 VN_HOLD(vp); 1665 *vpp = vp; 1666 return (0); 1667 } 1668 np = smbfs_node_findcreate(smi, 1669 dnp->n_rpath, rplen, NULL, 0, 0, 1670 &smbfs_fattr0); /* force create */ 1671 ASSERT(np != NULL); 1672 vp = SMBTOV(np); 1673 vp->v_type = VDIR; 1674 1675 /* Success! */ 1676 *vpp = vp; 1677 return (0); 1678 } 1679 1680 /* 1681 * Normal lookup of a name under this directory. 1682 * Note we handled "", ".", ".." above. 1683 */ 1684 if (cache_ok) { 1685 /* 1686 * The caller indicated that it's OK to use a 1687 * cached result for this lookup, so try to 1688 * reclaim a node from the smbfs node cache. 1689 */ 1690 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr); 1691 if (error) 1692 return (error); 1693 if (vp != NULL) { 1694 /* hold taken in lookup_cache */ 1695 *vpp = vp; 1696 return (0); 1697 } 1698 } 1699 1700 /* 1701 * OK, go over-the-wire to get the attributes, 1702 * then create the node. 1703 */ 1704 smb_credinit(&scred, cr); 1705 /* Note: this can allocate a new "name" */ 1706 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred); 1707 smb_credrele(&scred); 1708 if (error == ENOTDIR) { 1709 /* 1710 * Lookup failed because this directory was 1711 * removed or renamed by another client. 1712 * Remove any cached attributes under it. 1713 */ 1714 smbfs_attrcache_remove(dnp); 1715 smbfs_attrcache_prune(dnp); 1716 } 1717 if (error) 1718 goto out; 1719 1720 error = smbfs_nget(dvp, name, nmlen, &fa, &vp); 1721 if (error) 1722 goto out; 1723 1724 /* Success! */ 1725 *vpp = vp; 1726 1727 out: 1728 /* smbfs_smb_lookup may have allocated name. */ 1729 if (name != nm) 1730 smbfs_name_free(name, nmlen); 1731 1732 return (error); 1733 } 1734 1735 /* 1736 * smbfslookup_cache 1737 * 1738 * Try to reclaim a node from the smbfs node cache. 1739 * Some statistics for DEBUG. 1740 * 1741 * This mechanism lets us avoid many of the five (or more) 1742 * OtW lookup calls per file seen with "ls -l" if we search 1743 * the smbfs node cache for recently inactive(ated) nodes. 1744 */ 1745 #ifdef DEBUG 1746 int smbfs_lookup_cache_calls = 0; 1747 int smbfs_lookup_cache_error = 0; 1748 int smbfs_lookup_cache_miss = 0; 1749 int smbfs_lookup_cache_stale = 0; 1750 int smbfs_lookup_cache_hits = 0; 1751 #endif /* DEBUG */ 1752 1753 /* ARGSUSED */ 1754 static int 1755 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen, 1756 vnode_t **vpp, cred_t *cr) 1757 { 1758 struct vattr va; 1759 smbnode_t *dnp; 1760 smbnode_t *np; 1761 vnode_t *vp; 1762 int error; 1763 char sep; 1764 1765 dnp = VTOSMB(dvp); 1766 *vpp = NULL; 1767 1768 #ifdef DEBUG 1769 smbfs_lookup_cache_calls++; 1770 #endif 1771 1772 /* 1773 * First make sure we can get attributes for the 1774 * directory. Cached attributes are OK here. 1775 * If we removed or renamed the directory, this 1776 * will return ENOENT. If someone else removed 1777 * this directory or file, we'll find out when we 1778 * try to open or get attributes. 1779 */ 1780 va.va_mask = AT_TYPE | AT_MODE; 1781 error = smbfsgetattr(dvp, &va, cr); 1782 if (error) { 1783 #ifdef DEBUG 1784 smbfs_lookup_cache_error++; 1785 #endif 1786 return (error); 1787 } 1788 1789 /* 1790 * Passing NULL smbfattr here so we will 1791 * just look, not create. 1792 */ 1793 sep = SMBFS_DNP_SEP(dnp); 1794 np = smbfs_node_findcreate(dnp->n_mount, 1795 dnp->n_rpath, dnp->n_rplen, 1796 nm, nmlen, sep, NULL); 1797 if (np == NULL) { 1798 #ifdef DEBUG 1799 smbfs_lookup_cache_miss++; 1800 #endif 1801 return (0); 1802 } 1803 1804 /* 1805 * Found it. Attributes still valid? 1806 */ 1807 vp = SMBTOV(np); 1808 if (np->r_attrtime <= gethrtime()) { 1809 /* stale */ 1810 #ifdef DEBUG 1811 smbfs_lookup_cache_stale++; 1812 #endif 1813 VN_RELE(vp); 1814 return (0); 1815 } 1816 1817 /* 1818 * Success! 1819 * Caller gets hold from smbfs_node_findcreate 1820 */ 1821 #ifdef DEBUG 1822 smbfs_lookup_cache_hits++; 1823 #endif 1824 *vpp = vp; 1825 return (0); 1826 } 1827 1828 /* 1829 * XXX 1830 * vsecattr_t is new to build 77, and we need to eventually support 1831 * it in order to create an ACL when an object is created. 1832 * 1833 * This op should support the new FIGNORECASE flag for case-insensitive 1834 * lookups, per PSARC 2007/244. 1835 */ 1836 /* ARGSUSED */ 1837 static int 1838 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, 1839 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct, 1840 vsecattr_t *vsecp) 1841 { 1842 int error; 1843 int cerror; 1844 vfs_t *vfsp; 1845 vnode_t *vp; 1846 #ifdef NOT_YET 1847 smbnode_t *np; 1848 #endif 1849 smbnode_t *dnp; 1850 smbmntinfo_t *smi; 1851 struct vattr vattr; 1852 struct smbfattr fattr; 1853 struct smb_cred scred; 1854 const char *name = (const char *)nm; 1855 int nmlen = strlen(nm); 1856 uint32_t disp; 1857 uint16_t fid; 1858 int xattr; 1859 1860 vfsp = dvp->v_vfsp; 1861 smi = VFTOSMI(vfsp); 1862 dnp = VTOSMB(dvp); 1863 vp = NULL; 1864 1865 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1866 return (EPERM); 1867 1868 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1869 return (EIO); 1870 1871 /* 1872 * Note: this may break mknod(2) calls to create a directory, 1873 * but that's obscure use. Some other filesystems do this. 1874 * XXX: Later, redirect VDIR type here to _mkdir. 1875 */ 1876 if (va->va_type != VREG) 1877 return (EINVAL); 1878 1879 /* 1880 * If the pathname is "", just use dvp, no checks. 1881 * Do this outside of the rwlock (like zfs). 1882 */ 1883 if (nmlen == 0) { 1884 VN_HOLD(dvp); 1885 *vpp = dvp; 1886 return (0); 1887 } 1888 1889 /* Don't allow "." or ".." through here. */ 1890 if ((nmlen == 1 && name[0] == '.') || 1891 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 1892 return (EISDIR); 1893 1894 /* 1895 * We make a copy of the attributes because the caller does not 1896 * expect us to change what va points to. 1897 */ 1898 vattr = *va; 1899 1900 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 1901 return (EINTR); 1902 smb_credinit(&scred, cr); 1903 1904 /* 1905 * XXX: Do we need r_lkserlock too? 1906 * No use of any shared fid or fctx... 1907 */ 1908 1909 /* 1910 * NFS needs to go over the wire, just to be sure whether the 1911 * file exists or not. Using a cached result is dangerous in 1912 * this case when making a decision regarding existence. 1913 * 1914 * The SMB protocol does NOT really need to go OTW here 1915 * thanks to the expressive NTCREATE disposition values. 1916 * Unfortunately, to do Unix access checks correctly, 1917 * we need to know if the object already exists. 1918 * When the object does not exist, we need VWRITE on 1919 * the directory. Note: smbfslookup() checks VEXEC. 1920 */ 1921 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 1922 if (error == 0) { 1923 /* 1924 * The file already exists. Error? 1925 * NB: have a hold from smbfslookup 1926 */ 1927 if (exclusive == EXCL) { 1928 error = EEXIST; 1929 VN_RELE(vp); 1930 goto out; 1931 } 1932 /* 1933 * Verify requested access. 1934 */ 1935 error = smbfs_access(vp, mode, 0, cr, ct); 1936 if (error) { 1937 VN_RELE(vp); 1938 goto out; 1939 } 1940 1941 /* 1942 * Truncate (if requested). 1943 */ 1944 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) { 1945 vattr.va_mask = AT_SIZE; 1946 error = smbfssetattr(vp, &vattr, 0, cr); 1947 if (error) { 1948 VN_RELE(vp); 1949 goto out; 1950 } 1951 } 1952 /* Success! */ 1953 #ifdef NOT_YET 1954 vnevent_create(vp, ct); 1955 #endif 1956 *vpp = vp; 1957 goto out; 1958 } 1959 1960 /* 1961 * The file did not exist. Need VWRITE in the directory. 1962 */ 1963 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 1964 if (error) 1965 goto out; 1966 1967 /* 1968 * Now things get tricky. We also need to check the 1969 * requested open mode against the file we may create. 1970 * See comments at smbfs_access_rwx 1971 */ 1972 error = smbfs_access_rwx(vfsp, VREG, mode, cr); 1973 if (error) 1974 goto out; 1975 1976 /* 1977 * Now the code derived from Darwin, 1978 * but with greater use of NT_CREATE 1979 * disposition options. Much changed. 1980 * 1981 * Create (or open) a new child node. 1982 * Note we handled "." and ".." above. 1983 */ 1984 1985 if (exclusive == EXCL) 1986 disp = NTCREATEX_DISP_CREATE; 1987 else { 1988 /* Truncate regular files if requested. */ 1989 if ((va->va_type == VREG) && 1990 (va->va_mask & AT_SIZE) && 1991 (va->va_size == 0)) 1992 disp = NTCREATEX_DISP_OVERWRITE_IF; 1993 else 1994 disp = NTCREATEX_DISP_OPEN_IF; 1995 } 1996 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0; 1997 error = smbfs_smb_create(dnp, 1998 name, nmlen, xattr, 1999 disp, &scred, &fid); 2000 if (error) 2001 goto out; 2002 2003 /* 2004 * XXX: Missing some code here to deal with 2005 * the case where we opened an existing file, 2006 * it's size is larger than 32-bits, and we're 2007 * setting the size from a process that's not 2008 * aware of large file offsets. i.e. 2009 * from the NFS3 code: 2010 */ 2011 #if NOT_YET /* XXX */ 2012 if ((vattr.va_mask & AT_SIZE) && 2013 vp->v_type == VREG) { 2014 np = VTOSMB(vp); 2015 /* 2016 * Check here for large file handled 2017 * by LF-unaware process (as 2018 * ufs_create() does) 2019 */ 2020 if (!(lfaware & FOFFMAX)) { 2021 mutex_enter(&np->r_statelock); 2022 if (np->r_size > MAXOFF32_T) 2023 error = EOVERFLOW; 2024 mutex_exit(&np->r_statelock); 2025 } 2026 if (!error) { 2027 vattr.va_mask = AT_SIZE; 2028 error = smbfssetattr(vp, 2029 &vattr, 0, cr); 2030 } 2031 } 2032 #endif /* XXX */ 2033 /* 2034 * Should use the fid to get/set the size 2035 * while we have it opened here. See above. 2036 */ 2037 2038 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred); 2039 if (cerror) 2040 SMBVDEBUG("error %d closing %s\\%s\n", 2041 cerror, dnp->n_rpath, name); 2042 2043 /* 2044 * In the open case, the name may differ a little 2045 * from what we passed to create (case, etc.) 2046 * so call lookup to get the (opened) name. 2047 * 2048 * XXX: Could avoid this extra lookup if the 2049 * "createact" result from NT_CREATE says we 2050 * created the object. 2051 */ 2052 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 2053 if (error) 2054 goto out; 2055 2056 /* update attr and directory cache */ 2057 smbfs_attr_touchdir(dnp); 2058 2059 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 2060 if (error) 2061 goto out; 2062 2063 /* XXX invalidate pages if we truncated? */ 2064 2065 /* Success! */ 2066 *vpp = vp; 2067 error = 0; 2068 2069 out: 2070 smb_credrele(&scred); 2071 smbfs_rw_exit(&dnp->r_rwlock); 2072 if (name != nm) 2073 smbfs_name_free(name, nmlen); 2074 return (error); 2075 } 2076 2077 /* 2078 * XXX 2079 * This op should support the new FIGNORECASE flag for case-insensitive 2080 * lookups, per PSARC 2007/244. 2081 */ 2082 /* ARGSUSED */ 2083 static int 2084 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct, 2085 int flags) 2086 { 2087 int error; 2088 vnode_t *vp; 2089 smbnode_t *np; 2090 smbnode_t *dnp; 2091 struct smb_cred scred; 2092 /* enum smbfsstat status; */ 2093 smbmntinfo_t *smi; 2094 2095 smi = VTOSMI(dvp); 2096 2097 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2098 return (EPERM); 2099 2100 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2101 return (EIO); 2102 2103 dnp = VTOSMB(dvp); 2104 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2105 return (EINTR); 2106 smb_credinit(&scred, cr); 2107 2108 /* 2109 * Verify access to the dirctory. 2110 */ 2111 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct); 2112 if (error) 2113 goto out; 2114 2115 /* 2116 * NOTE: the darwin code gets the "vp" passed in so it looks 2117 * like the "vp" has probably been "lookup"ed by the VFS layer. 2118 * It looks like we will need to lookup the vp to check the 2119 * caches and check if the object being deleted is a directory. 2120 */ 2121 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2122 if (error) 2123 goto out; 2124 2125 /* Never allow link/unlink directories on CIFS. */ 2126 if (vp->v_type == VDIR) { 2127 VN_RELE(vp); 2128 error = EPERM; 2129 goto out; 2130 } 2131 2132 /* 2133 * Now we have the real reference count on the vnode 2134 * Do we have the file open? 2135 */ 2136 np = VTOSMB(vp); 2137 mutex_enter(&np->r_statelock); 2138 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) { 2139 /* 2140 * NFS does a rename on remove here. 2141 * Probably not applicable for SMB. 2142 * Like Darwin, just return EBUSY. 2143 * 2144 * XXX: Todo - Use Trans2rename, and 2145 * if that fails, ask the server to 2146 * set the delete-on-close flag. 2147 */ 2148 mutex_exit(&np->r_statelock); 2149 error = EBUSY; 2150 } else { 2151 smbfs_attrcache_rm_locked(np); 2152 mutex_exit(&np->r_statelock); 2153 2154 error = smbfs_smb_delete(np, &scred, NULL, 0, 0); 2155 2156 /* 2157 * If the file should no longer exist, discard 2158 * any cached attributes under this node. 2159 */ 2160 switch (error) { 2161 case 0: 2162 case ENOENT: 2163 case ENOTDIR: 2164 smbfs_attrcache_prune(np); 2165 break; 2166 } 2167 } 2168 2169 VN_RELE(vp); 2170 2171 out: 2172 smb_credrele(&scred); 2173 smbfs_rw_exit(&dnp->r_rwlock); 2174 2175 return (error); 2176 } 2177 2178 2179 /* 2180 * XXX 2181 * This op should support the new FIGNORECASE flag for case-insensitive 2182 * lookups, per PSARC 2007/244. 2183 */ 2184 /* ARGSUSED */ 2185 static int 2186 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, 2187 caller_context_t *ct, int flags) 2188 { 2189 /* vnode_t *realvp; */ 2190 2191 if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone || 2192 curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone) 2193 return (EPERM); 2194 2195 if (VTOSMI(odvp)->smi_flags & SMI_DEAD || 2196 VTOSMI(ndvp)->smi_flags & SMI_DEAD || 2197 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED || 2198 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2199 return (EIO); 2200 2201 return (smbfsrename(odvp, onm, ndvp, nnm, cr, ct)); 2202 } 2203 2204 /* 2205 * smbfsrename does the real work of renaming in SMBFS 2206 */ 2207 /* ARGSUSED */ 2208 static int 2209 smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, 2210 caller_context_t *ct) 2211 { 2212 int error; 2213 int nvp_locked = 0; 2214 vnode_t *nvp = NULL; 2215 vnode_t *ovp = NULL; 2216 smbnode_t *onp; 2217 smbnode_t *nnp; 2218 smbnode_t *odnp; 2219 smbnode_t *ndnp; 2220 struct smb_cred scred; 2221 /* enum smbfsstat status; */ 2222 2223 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone); 2224 2225 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 || 2226 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0) 2227 return (EINVAL); 2228 2229 /* 2230 * Check that everything is on the same filesystem. 2231 * vn_rename checks the fsid's, but in case we don't 2232 * fill those in correctly, check here too. 2233 */ 2234 if (odvp->v_vfsp != ndvp->v_vfsp) 2235 return (EXDEV); 2236 2237 odnp = VTOSMB(odvp); 2238 ndnp = VTOSMB(ndvp); 2239 2240 /* 2241 * Avoid deadlock here on old vs new directory nodes 2242 * by always taking the locks in order of address. 2243 * The order is arbitrary, but must be consistent. 2244 */ 2245 if (odnp < ndnp) { 2246 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2247 SMBINTR(odvp))) 2248 return (EINTR); 2249 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2250 SMBINTR(ndvp))) { 2251 smbfs_rw_exit(&odnp->r_rwlock); 2252 return (EINTR); 2253 } 2254 } else { 2255 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2256 SMBINTR(ndvp))) 2257 return (EINTR); 2258 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2259 SMBINTR(odvp))) { 2260 smbfs_rw_exit(&ndnp->r_rwlock); 2261 return (EINTR); 2262 } 2263 } 2264 smb_credinit(&scred, cr); 2265 /* 2266 * No returns after this point (goto out) 2267 */ 2268 2269 /* 2270 * Need write access on source and target. 2271 * Server takes care of most checks. 2272 */ 2273 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct); 2274 if (error) 2275 goto out; 2276 if (odvp != ndvp) { 2277 error = smbfs_access(ndvp, VWRITE, 0, cr, ct); 2278 if (error) 2279 goto out; 2280 } 2281 2282 /* 2283 * Lookup the source name. Must already exist. 2284 */ 2285 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct); 2286 if (error) 2287 goto out; 2288 2289 /* 2290 * Lookup the target file. If it exists, it needs to be 2291 * checked to see whether it is a mount point and whether 2292 * it is active (open). 2293 */ 2294 error = smbfslookup(ndvp, nnm, &nvp, cr, 0, ct); 2295 if (!error) { 2296 /* 2297 * Target (nvp) already exists. Check that it 2298 * has the same type as the source. The server 2299 * will check this also, (and more reliably) but 2300 * this lets us return the correct error codes. 2301 */ 2302 if (ovp->v_type == VDIR) { 2303 if (nvp->v_type != VDIR) { 2304 error = ENOTDIR; 2305 goto out; 2306 } 2307 } else { 2308 if (nvp->v_type == VDIR) { 2309 error = EISDIR; 2310 goto out; 2311 } 2312 } 2313 2314 /* 2315 * POSIX dictates that when the source and target 2316 * entries refer to the same file object, rename 2317 * must do nothing and exit without error. 2318 */ 2319 if (ovp == nvp) { 2320 error = 0; 2321 goto out; 2322 } 2323 2324 /* 2325 * Also must ensure the target is not a mount point, 2326 * and keep mount/umount away until we're done. 2327 */ 2328 if (vn_vfsrlock(nvp)) { 2329 error = EBUSY; 2330 goto out; 2331 } 2332 nvp_locked = 1; 2333 if (vn_mountedvfs(nvp) != NULL) { 2334 error = EBUSY; 2335 goto out; 2336 } 2337 2338 /* 2339 * CIFS gives a SHARING_VIOLATION error when 2340 * trying to rename onto an exising object, 2341 * so try to remove the target first. 2342 * (Only for files, not directories.) 2343 */ 2344 if (nvp->v_type == VDIR) { 2345 error = EEXIST; 2346 goto out; 2347 } 2348 2349 /* 2350 * Nodes that are "not active" here have v_count=2 2351 * because vn_renameat (our caller) did a lookup on 2352 * both the source and target before this call. 2353 * Otherwise this similar to smbfs_remove. 2354 */ 2355 nnp = VTOSMB(nvp); 2356 mutex_enter(&nnp->r_statelock); 2357 if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) { 2358 /* 2359 * The target file exists, is not the same as 2360 * the source file, and is active. Other FS 2361 * implementations unlink the target here. 2362 * For SMB, we don't assume we can remove an 2363 * open file. Return an error instead. 2364 */ 2365 mutex_exit(&nnp->r_statelock); 2366 error = EBUSY; 2367 goto out; 2368 } 2369 2370 /* 2371 * Target file is not active. Try to remove it. 2372 */ 2373 smbfs_attrcache_rm_locked(nnp); 2374 mutex_exit(&nnp->r_statelock); 2375 2376 error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0); 2377 2378 /* 2379 * Similar to smbfs_remove 2380 */ 2381 switch (error) { 2382 case 0: 2383 case ENOENT: 2384 case ENOTDIR: 2385 smbfs_attrcache_prune(nnp); 2386 break; 2387 } 2388 2389 if (error) 2390 goto out; 2391 /* 2392 * OK, removed the target file. Continue as if 2393 * lookup target had failed (nvp == NULL). 2394 */ 2395 vn_vfsunlock(nvp); 2396 nvp_locked = 0; 2397 VN_RELE(nvp); 2398 nvp = NULL; 2399 } /* nvp */ 2400 2401 onp = VTOSMB(ovp); 2402 smbfs_attrcache_remove(onp); 2403 2404 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred); 2405 2406 /* 2407 * If the old name should no longer exist, 2408 * discard any cached attributes under it. 2409 */ 2410 if (error == 0) 2411 smbfs_attrcache_prune(onp); 2412 2413 out: 2414 if (nvp) { 2415 if (nvp_locked) 2416 vn_vfsunlock(nvp); 2417 VN_RELE(nvp); 2418 } 2419 if (ovp) 2420 VN_RELE(ovp); 2421 2422 smb_credrele(&scred); 2423 smbfs_rw_exit(&odnp->r_rwlock); 2424 smbfs_rw_exit(&ndnp->r_rwlock); 2425 2426 return (error); 2427 } 2428 2429 /* 2430 * XXX 2431 * vsecattr_t is new to build 77, and we need to eventually support 2432 * it in order to create an ACL when an object is created. 2433 * 2434 * This op should support the new FIGNORECASE flag for case-insensitive 2435 * lookups, per PSARC 2007/244. 2436 */ 2437 /* ARGSUSED */ 2438 static int 2439 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, 2440 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp) 2441 { 2442 vnode_t *vp; 2443 struct smbnode *dnp = VTOSMB(dvp); 2444 struct smbmntinfo *smi = VTOSMI(dvp); 2445 struct smb_cred scred; 2446 struct smbfattr fattr; 2447 const char *name = (const char *) nm; 2448 int nmlen = strlen(name); 2449 int error, hiderr; 2450 2451 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2452 return (EPERM); 2453 2454 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2455 return (EIO); 2456 2457 if ((nmlen == 1 && name[0] == '.') || 2458 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 2459 return (EEXIST); 2460 2461 /* Only plain files are allowed in V_XATTRDIR. */ 2462 if (dvp->v_flag & V_XATTRDIR) 2463 return (EINVAL); 2464 2465 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2466 return (EINTR); 2467 smb_credinit(&scred, cr); 2468 2469 /* 2470 * XXX: Do we need r_lkserlock too? 2471 * No use of any shared fid or fctx... 2472 */ 2473 2474 /* 2475 * Require write access in the containing directory. 2476 */ 2477 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 2478 if (error) 2479 goto out; 2480 2481 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred); 2482 if (error) 2483 goto out; 2484 2485 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 2486 if (error) 2487 goto out; 2488 2489 smbfs_attr_touchdir(dnp); 2490 2491 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 2492 if (error) 2493 goto out; 2494 2495 if (name[0] == '.') 2496 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred))) 2497 SMBVDEBUG("hide failure %d\n", hiderr); 2498 2499 /* Success! */ 2500 *vpp = vp; 2501 error = 0; 2502 out: 2503 smb_credrele(&scred); 2504 smbfs_rw_exit(&dnp->r_rwlock); 2505 2506 if (name != nm) 2507 smbfs_name_free(name, nmlen); 2508 2509 return (error); 2510 } 2511 2512 /* 2513 * XXX 2514 * This op should support the new FIGNORECASE flag for case-insensitive 2515 * lookups, per PSARC 2007/244. 2516 */ 2517 /* ARGSUSED */ 2518 static int 2519 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr, 2520 caller_context_t *ct, int flags) 2521 { 2522 vnode_t *vp = NULL; 2523 int vp_locked = 0; 2524 struct smbmntinfo *smi = VTOSMI(dvp); 2525 struct smbnode *dnp = VTOSMB(dvp); 2526 struct smbnode *np; 2527 struct smb_cred scred; 2528 int error; 2529 2530 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2531 return (EPERM); 2532 2533 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2534 return (EIO); 2535 2536 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2537 return (EINTR); 2538 smb_credinit(&scred, cr); 2539 2540 /* 2541 * Require w/x access in the containing directory. 2542 * Server handles all other access checks. 2543 */ 2544 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct); 2545 if (error) 2546 goto out; 2547 2548 /* 2549 * First lookup the entry to be removed. 2550 */ 2551 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2552 if (error) 2553 goto out; 2554 np = VTOSMB(vp); 2555 2556 /* 2557 * Disallow rmdir of "." or current dir, or the FS root. 2558 * Also make sure it's a directory, not a mount point, 2559 * and lock to keep mount/umount away until we're done. 2560 */ 2561 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) { 2562 error = EINVAL; 2563 goto out; 2564 } 2565 if (vp->v_type != VDIR) { 2566 error = ENOTDIR; 2567 goto out; 2568 } 2569 if (vn_vfsrlock(vp)) { 2570 error = EBUSY; 2571 goto out; 2572 } 2573 vp_locked = 1; 2574 if (vn_mountedvfs(vp) != NULL) { 2575 error = EBUSY; 2576 goto out; 2577 } 2578 2579 smbfs_attrcache_remove(np); 2580 error = smbfs_smb_rmdir(np, &scred); 2581 2582 /* 2583 * Similar to smbfs_remove 2584 */ 2585 switch (error) { 2586 case 0: 2587 case ENOENT: 2588 case ENOTDIR: 2589 smbfs_attrcache_prune(np); 2590 break; 2591 } 2592 2593 if (error) 2594 goto out; 2595 2596 mutex_enter(&np->r_statelock); 2597 dnp->n_flag |= NMODIFIED; 2598 mutex_exit(&np->r_statelock); 2599 smbfs_attr_touchdir(dnp); 2600 smbfs_rmhash(np); 2601 2602 out: 2603 if (vp) { 2604 if (vp_locked) 2605 vn_vfsunlock(vp); 2606 VN_RELE(vp); 2607 } 2608 smb_credrele(&scred); 2609 smbfs_rw_exit(&dnp->r_rwlock); 2610 2611 return (error); 2612 } 2613 2614 2615 /* ARGSUSED */ 2616 static int 2617 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp, 2618 caller_context_t *ct, int flags) 2619 { 2620 struct smbnode *np = VTOSMB(vp); 2621 int error = 0; 2622 smbmntinfo_t *smi; 2623 2624 smi = VTOSMI(vp); 2625 2626 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2627 return (EIO); 2628 2629 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2630 return (EIO); 2631 2632 /* 2633 * Require read access in the directory. 2634 */ 2635 error = smbfs_access(vp, VREAD, 0, cr, ct); 2636 if (error) 2637 return (error); 2638 2639 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER)); 2640 2641 /* 2642 * XXX: Todo readdir cache here 2643 * Note: NFS code is just below this. 2644 * 2645 * I am serializing the entire readdir opreation 2646 * now since we have not yet implemented readdir 2647 * cache. This fix needs to be revisited once 2648 * we implement readdir cache. 2649 */ 2650 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 2651 return (EINTR); 2652 2653 error = smbfs_readvdir(vp, uiop, cr, eofp, ct); 2654 2655 smbfs_rw_exit(&np->r_lkserlock); 2656 2657 return (error); 2658 } 2659 2660 /* ARGSUSED */ 2661 static int 2662 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, 2663 caller_context_t *ct) 2664 { 2665 /* 2666 * Note: "limit" tells the SMB-level FindFirst/FindNext 2667 * functions how many directory entries to request in 2668 * each OtW call. It needs to be large enough so that 2669 * we don't make lots of tiny OtW requests, but there's 2670 * no point making it larger than the maximum number of 2671 * OtW entries that would fit in a maximum sized trans2 2672 * response (64k / 48). Beyond that, it's just tuning. 2673 * WinNT used 512, Win2k used 1366. We use 1000. 2674 */ 2675 static const int limit = 1000; 2676 /* Largest possible dirent size. */ 2677 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN); 2678 struct smb_cred scred; 2679 vnode_t *newvp; 2680 struct smbnode *np = VTOSMB(vp); 2681 struct smbfs_fctx *ctx; 2682 struct dirent64 *dp; 2683 ssize_t save_resid; 2684 offset_t save_offset; /* 64 bits */ 2685 int offset; /* yes, 32 bits */ 2686 int nmlen, error; 2687 ushort_t reclen; 2688 2689 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone); 2690 2691 /* Make sure we serialize for n_dirseq use. */ 2692 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER)); 2693 2694 /* 2695 * Make sure smbfs_open filled in n_dirseq 2696 */ 2697 if (np->n_dirseq == NULL) 2698 return (EBADF); 2699 2700 /* Check for overflow of (32-bit) directory offset. */ 2701 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX || 2702 (uio->uio_loffset + uio->uio_resid) > INT32_MAX) 2703 return (EINVAL); 2704 2705 /* Require space for at least one dirent. */ 2706 if (uio->uio_resid < dbufsiz) 2707 return (EINVAL); 2708 2709 SMBVDEBUG("dirname='%s'\n", np->n_rpath); 2710 smb_credinit(&scred, cr); 2711 dp = kmem_alloc(dbufsiz, KM_SLEEP); 2712 2713 save_resid = uio->uio_resid; 2714 save_offset = uio->uio_loffset; 2715 offset = uio->uio_offset; 2716 SMBVDEBUG("in: offset=%d, resid=%d\n", 2717 (int)uio->uio_offset, (int)uio->uio_resid); 2718 error = 0; 2719 2720 /* 2721 * Generate the "." and ".." entries here so we can 2722 * (1) make sure they appear (but only once), and 2723 * (2) deal with getting their I numbers which the 2724 * findnext below does only for normal names. 2725 */ 2726 while (offset < FIRST_DIROFS) { 2727 /* 2728 * Tricky bit filling in the first two: 2729 * offset 0 is ".", offset 1 is ".." 2730 * so strlen of these is offset+1. 2731 */ 2732 reclen = DIRENT64_RECLEN(offset + 1); 2733 if (uio->uio_resid < reclen) 2734 goto out; 2735 bzero(dp, reclen); 2736 dp->d_reclen = reclen; 2737 dp->d_name[0] = '.'; 2738 dp->d_name[1] = '.'; 2739 dp->d_name[offset + 1] = '\0'; 2740 /* 2741 * Want the real I-numbers for the "." and ".." 2742 * entries. For these two names, we know that 2743 * smbfslookup can get the nodes efficiently. 2744 */ 2745 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct); 2746 if (error) { 2747 dp->d_ino = np->n_ino + offset; /* fiction */ 2748 } else { 2749 dp->d_ino = VTOSMB(newvp)->n_ino; 2750 VN_RELE(newvp); 2751 } 2752 /* 2753 * Note: d_off is the offset that a user-level program 2754 * should seek to for reading the NEXT directory entry. 2755 * See libc: readdir, telldir, seekdir 2756 */ 2757 dp->d_off = offset + 1; 2758 error = uiomove(dp, reclen, UIO_READ, uio); 2759 if (error) 2760 goto out; 2761 /* 2762 * Note: uiomove updates uio->uio_offset, 2763 * but we want it to be our "cookie" value, 2764 * which just counts dirents ignoring size. 2765 */ 2766 uio->uio_offset = ++offset; 2767 } 2768 2769 /* 2770 * If there was a backward seek, we have to reopen. 2771 */ 2772 if (offset < np->n_dirofs) { 2773 SMBVDEBUG("Reopening search %d:%d\n", 2774 offset, np->n_dirofs); 2775 error = smbfs_smb_findopen(np, "*", 1, 2776 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, 2777 &scred, &ctx); 2778 if (error) { 2779 SMBVDEBUG("can not open search, error = %d", error); 2780 goto out; 2781 } 2782 /* free the old one */ 2783 (void) smbfs_smb_findclose(np->n_dirseq, &scred); 2784 /* save the new one */ 2785 np->n_dirseq = ctx; 2786 np->n_dirofs = FIRST_DIROFS; 2787 } else { 2788 ctx = np->n_dirseq; 2789 } 2790 2791 /* 2792 * Skip entries before the requested offset. 2793 */ 2794 while (np->n_dirofs < offset) { 2795 error = smbfs_smb_findnext(ctx, limit, &scred); 2796 if (error != 0) 2797 goto out; 2798 np->n_dirofs++; 2799 } 2800 2801 /* 2802 * While there's room in the caller's buffer: 2803 * get a directory entry from SMB, 2804 * convert to a dirent, copyout. 2805 * We stop when there is no longer room for a 2806 * maximum sized dirent because we must decide 2807 * before we know anything about the next entry. 2808 */ 2809 while (uio->uio_resid >= dbufsiz) { 2810 error = smbfs_smb_findnext(ctx, limit, &scred); 2811 if (error != 0) 2812 goto out; 2813 np->n_dirofs++; 2814 2815 /* Sanity check the name length. */ 2816 nmlen = ctx->f_nmlen; 2817 if (nmlen > SMB_MAXFNAMELEN) { 2818 nmlen = SMB_MAXFNAMELEN; 2819 SMBVDEBUG("Truncating name: %s\n", ctx->f_name); 2820 } 2821 if (smbfs_fastlookup) { 2822 /* See comment at smbfs_fastlookup above. */ 2823 if (smbfs_nget(vp, ctx->f_name, nmlen, 2824 &ctx->f_attr, &newvp) == 0) 2825 VN_RELE(newvp); 2826 } 2827 2828 reclen = DIRENT64_RECLEN(nmlen); 2829 bzero(dp, reclen); 2830 dp->d_reclen = reclen; 2831 bcopy(ctx->f_name, dp->d_name, nmlen); 2832 dp->d_name[nmlen] = '\0'; 2833 dp->d_ino = ctx->f_inum; 2834 dp->d_off = offset + 1; /* See d_off comment above */ 2835 error = uiomove(dp, reclen, UIO_READ, uio); 2836 if (error) 2837 goto out; 2838 /* See comment re. uio_offset above. */ 2839 uio->uio_offset = ++offset; 2840 } 2841 2842 out: 2843 /* 2844 * When we come to the end of a directory, the 2845 * SMB-level functions return ENOENT, but the 2846 * caller is not expecting an error return. 2847 * 2848 * Also note that we must delay the call to 2849 * smbfs_smb_findclose(np->n_dirseq, ...) 2850 * until smbfs_close so that all reads at the 2851 * end of the directory will return no data. 2852 */ 2853 if (error == ENOENT) { 2854 error = 0; 2855 if (eofp) 2856 *eofp = 1; 2857 } 2858 /* 2859 * If we encountered an error (i.e. "access denied") 2860 * from the FindFirst call, we will have copied out 2861 * the "." and ".." entries leaving offset == 2. 2862 * In that case, restore the original offset/resid 2863 * so the caller gets no data with the error. 2864 */ 2865 if (error != 0 && offset == FIRST_DIROFS) { 2866 uio->uio_loffset = save_offset; 2867 uio->uio_resid = save_resid; 2868 } 2869 SMBVDEBUG("out: offset=%d, resid=%d\n", 2870 (int)uio->uio_offset, (int)uio->uio_resid); 2871 2872 kmem_free(dp, dbufsiz); 2873 smb_credrele(&scred); 2874 return (error); 2875 } 2876 2877 2878 /* 2879 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK 2880 * are optional functions that are called by: 2881 * getdents, before/after VOP_READDIR 2882 * pread, before/after ... VOP_READ 2883 * pwrite, before/after ... VOP_WRITE 2884 * (other places) 2885 * 2886 * Careful here: None of the above check for any 2887 * error returns from VOP_RWLOCK / VOP_RWUNLOCK! 2888 * In fact, the return value from _rwlock is NOT 2889 * an error code, but V_WRITELOCK_TRUE / _FALSE. 2890 * 2891 * Therefore, it's up to _this_ code to make sure 2892 * the lock state remains balanced, which means 2893 * we can't "bail out" on interrupts, etc. 2894 */ 2895 2896 /* ARGSUSED2 */ 2897 static int 2898 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 2899 { 2900 smbnode_t *np = VTOSMB(vp); 2901 2902 if (!write_lock) { 2903 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE); 2904 return (V_WRITELOCK_FALSE); 2905 } 2906 2907 2908 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE); 2909 return (V_WRITELOCK_TRUE); 2910 } 2911 2912 /* ARGSUSED */ 2913 static void 2914 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 2915 { 2916 smbnode_t *np = VTOSMB(vp); 2917 2918 smbfs_rw_exit(&np->r_rwlock); 2919 } 2920 2921 2922 /* ARGSUSED */ 2923 static int 2924 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) 2925 { 2926 smbmntinfo_t *smi; 2927 2928 smi = VTOSMI(vp); 2929 2930 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2931 return (EPERM); 2932 2933 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2934 return (EIO); 2935 2936 /* 2937 * Because we stuff the readdir cookie into the offset field 2938 * someone may attempt to do an lseek with the cookie which 2939 * we want to succeed. 2940 */ 2941 if (vp->v_type == VDIR) 2942 return (0); 2943 2944 /* Like NFS3, just check for 63-bit overflow. */ 2945 if (*noffp < 0) 2946 return (EINVAL); 2947 2948 return (0); 2949 } 2950 2951 2952 /* 2953 * XXX 2954 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service. 2955 */ 2956 static int 2957 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 2958 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr, 2959 caller_context_t *ct) 2960 { 2961 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone) 2962 return (EIO); 2963 2964 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 2965 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct)); 2966 else 2967 return (ENOSYS); 2968 } 2969 2970 /* 2971 * Free storage space associated with the specified vnode. The portion 2972 * to be freed is specified by bfp->l_start and bfp->l_len (already 2973 * normalized to a "whence" of 0). 2974 * 2975 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc. 2976 */ 2977 /* ARGSUSED */ 2978 static int 2979 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 2980 offset_t offset, cred_t *cr, caller_context_t *ct) 2981 { 2982 int error; 2983 smbmntinfo_t *smi; 2984 2985 smi = VTOSMI(vp); 2986 2987 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2988 return (EIO); 2989 2990 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2991 return (EIO); 2992 2993 /* Caller (fcntl) has checked v_type */ 2994 ASSERT(vp->v_type == VREG); 2995 if (cmd != F_FREESP) 2996 return (EINVAL); 2997 2998 /* 2999 * Like NFS3, no 32-bit offset checks here. 3000 * Our SMB layer takes care to return EFBIG 3001 * when it has to fallback to a 32-bit call. 3002 */ 3003 3004 error = convoff(vp, bfp, 0, offset); 3005 if (!error) { 3006 ASSERT(bfp->l_start >= 0); 3007 if (bfp->l_len == 0) { 3008 struct vattr va; 3009 3010 /* 3011 * ftruncate should not change the ctime and 3012 * mtime if we truncate the file to its 3013 * previous size. 3014 */ 3015 va.va_mask = AT_SIZE; 3016 error = smbfsgetattr(vp, &va, cr); 3017 if (error || va.va_size == bfp->l_start) 3018 return (error); 3019 va.va_mask = AT_SIZE; 3020 va.va_size = bfp->l_start; 3021 error = smbfssetattr(vp, &va, 0, cr); 3022 } else 3023 error = EINVAL; 3024 } 3025 3026 return (error); 3027 } 3028 3029 /* ARGSUSED */ 3030 static int 3031 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, 3032 caller_context_t *ct) 3033 { 3034 vfs_t *vfs; 3035 smbmntinfo_t *smi; 3036 struct smb_share *ssp; 3037 3038 vfs = vp->v_vfsp; 3039 smi = VFTOSMI(vfs); 3040 3041 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3042 return (EIO); 3043 3044 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3045 return (EIO); 3046 3047 switch (cmd) { 3048 case _PC_FILESIZEBITS: 3049 ssp = smi->smi_share; 3050 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) 3051 *valp = 64; 3052 else 3053 *valp = 32; 3054 break; 3055 3056 case _PC_LINK_MAX: 3057 /* We only ever report one link to an object */ 3058 *valp = 1; 3059 break; 3060 3061 case _PC_ACL_ENABLED: 3062 /* 3063 * Always indicate that ACLs are enabled and 3064 * that we support ACE_T format, otherwise 3065 * libsec will ask for ACLENT_T format data 3066 * which we don't support. 3067 */ 3068 *valp = _ACL_ACE_ENABLED; 3069 break; 3070 3071 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */ 3072 *valp = 0; 3073 break; 3074 3075 case _PC_XATTR_EXISTS: 3076 if (vfs->vfs_flag & VFS_XATTR) { 3077 *valp = smbfs_xa_exists(vp, cr); 3078 break; 3079 } 3080 return (EINVAL); 3081 3082 case _PC_TIMESTAMP_RESOLUTION: 3083 /* 3084 * Windows times are tenths of microseconds 3085 * (multiples of 100 nanoseconds). 3086 */ 3087 *valp = 100L; 3088 break; 3089 3090 default: 3091 return (fs_pathconf(vp, cmd, valp, cr, ct)); 3092 } 3093 return (0); 3094 } 3095 3096 /* ARGSUSED */ 3097 static int 3098 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3099 caller_context_t *ct) 3100 { 3101 vfs_t *vfsp; 3102 smbmntinfo_t *smi; 3103 int error; 3104 uint_t mask; 3105 3106 vfsp = vp->v_vfsp; 3107 smi = VFTOSMI(vfsp); 3108 3109 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3110 return (EIO); 3111 3112 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3113 return (EIO); 3114 3115 /* 3116 * Our _pathconf indicates _ACL_ACE_ENABLED, 3117 * so we should only see VSA_ACE, etc here. 3118 * Note: vn_create asks for VSA_DFACLCNT, 3119 * and it expects ENOSYS and empty data. 3120 */ 3121 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT | 3122 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 3123 if (mask == 0) 3124 return (ENOSYS); 3125 3126 if (smi->smi_flags & SMI_ACL) 3127 error = smbfs_acl_getvsa(vp, vsa, flag, cr); 3128 else 3129 error = ENOSYS; 3130 3131 if (error == ENOSYS) 3132 error = fs_fab_acl(vp, vsa, flag, cr, ct); 3133 3134 return (error); 3135 } 3136 3137 /* ARGSUSED */ 3138 static int 3139 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3140 caller_context_t *ct) 3141 { 3142 vfs_t *vfsp; 3143 smbmntinfo_t *smi; 3144 int error; 3145 uint_t mask; 3146 3147 vfsp = vp->v_vfsp; 3148 smi = VFTOSMI(vfsp); 3149 3150 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3151 return (EIO); 3152 3153 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3154 return (EIO); 3155 3156 /* 3157 * Our _pathconf indicates _ACL_ACE_ENABLED, 3158 * so we should only see VSA_ACE, etc here. 3159 */ 3160 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT); 3161 if (mask == 0) 3162 return (ENOSYS); 3163 3164 if (vfsp->vfs_flag & VFS_RDONLY) 3165 return (EROFS); 3166 3167 /* 3168 * Allow only the mount owner to do this. 3169 * See comments at smbfs_access_rwx. 3170 */ 3171 error = secpolicy_vnode_setdac(cr, smi->smi_uid); 3172 if (error != 0) 3173 return (error); 3174 3175 if (smi->smi_flags & SMI_ACL) 3176 error = smbfs_acl_setvsa(vp, vsa, flag, cr); 3177 else 3178 error = ENOSYS; 3179 3180 return (error); 3181 } 3182 3183 3184 /* 3185 * XXX 3186 * This op should eventually support PSARC 2007/268. 3187 */ 3188 static int 3189 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr, 3190 caller_context_t *ct) 3191 { 3192 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone) 3193 return (EIO); 3194 3195 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 3196 return (fs_shrlock(vp, cmd, shr, flag, cr, ct)); 3197 else 3198 return (ENOSYS); 3199 } 3200 3201 static int uio_page_mapin(uio_t *uiop, page_t *pp) { 3202 u_offset_t off; 3203 size_t size; 3204 pgcnt_t npages; 3205 caddr_t kaddr; 3206 pfn_t pfnum; 3207 3208 off = (uintptr_t) uiop->uio_loffset & PAGEOFFSET; 3209 size = P2ROUNDUP(uiop->uio_resid + off, PAGESIZE); 3210 npages = btop(size); 3211 3212 ASSERT(pp != NULL); 3213 3214 if (npages == 1 && kpm_enable) { 3215 kaddr = hat_kpm_mapin(pp, NULL); 3216 if (kaddr == NULL) 3217 return (EFAULT); 3218 3219 uiop->uio_iov->iov_base = kaddr + off; 3220 uiop->uio_iov->iov_len = PAGESIZE - off; 3221 3222 } else { 3223 kaddr = vmem_xalloc(heap_arena, size, PAGESIZE, 0, 0, NULL, NULL, VM_SLEEP); 3224 if (kaddr == NULL) 3225 return (EFAULT); 3226 3227 uiop->uio_iov->iov_base = kaddr + off; 3228 uiop->uio_iov->iov_len = size - off; 3229 3230 /*map pages into kaddr*/ 3231 uint_t attr = PROT_READ | PROT_WRITE | HAT_NOSYNC; 3232 while (npages-- > 0) { 3233 pfnum = pp->p_pagenum; 3234 pp = pp->p_next; 3235 3236 hat_devload(kas.a_hat, kaddr, PAGESIZE, pfnum, attr, HAT_LOAD_LOCK); 3237 kaddr += PAGESIZE; 3238 } 3239 } 3240 return (0); 3241 } 3242 3243 static void uio_page_mapout(uio_t *uiop, page_t *pp) { 3244 u_offset_t off; 3245 size_t size; 3246 pgcnt_t npages; 3247 caddr_t kaddr; 3248 3249 kaddr = uiop->uio_iov->iov_base; 3250 off = (uintptr_t) kaddr & PAGEOFFSET; 3251 size = P2ROUNDUP(uiop->uio_iov->iov_len + off, PAGESIZE); 3252 npages = btop(size); 3253 3254 ASSERT(pp != NULL); 3255 3256 kaddr = (caddr_t) ((uintptr_t) kaddr & MMU_PAGEMASK); 3257 3258 if (npages == 1 && kpm_enable) { 3259 hat_kpm_mapout(pp, NULL, kaddr); 3260 3261 } else { 3262 hat_unload(kas.a_hat, (void*) kaddr, size, 3263 HAT_UNLOAD_NOSYNC | HAT_UNLOAD_UNLOCK); 3264 vmem_free(heap_arena, (void*) kaddr, size); 3265 } 3266 uiop->uio_iov->iov_base = 0; 3267 uiop->uio_iov->iov_len = 0; 3268 } 3269 3270 static int smbfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, 3271 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr, 3272 caller_context_t *ct) { 3273 smbnode_t *np; 3274 smbmntinfo_t *smi; 3275 struct vattr va; 3276 segvn_crargs_t vn_a; 3277 int error; 3278 3279 np = VTOSMB(vp); 3280 smi = VTOSMI(vp); 3281 3282 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3283 return (EIO); 3284 3285 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3286 return (EIO); 3287 3288 if (vp->v_flag & VNOMAP || vp->v_flag & VNOCACHE) 3289 return (EAGAIN); 3290 3291 if (vp->v_type != VREG) 3292 return (ENODEV); 3293 3294 va.va_mask = AT_ALL; 3295 if (error = smbfsgetattr(vp, &va, cr)) 3296 return (error); 3297 3298 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 3299 return (EINTR); 3300 3301 if (MANDLOCK(vp, va.va_mode)) { 3302 error = EAGAIN; 3303 goto out; 3304 } 3305 3306 as_rangelock(as); 3307 error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags); 3308 3309 if (error != 0) { 3310 as_rangeunlock(as); 3311 goto out; 3312 } 3313 3314 vn_a.vp = vp; 3315 vn_a.offset = off; 3316 vn_a.type = flags & MAP_TYPE; 3317 vn_a.prot = prot; 3318 vn_a.maxprot = maxprot; 3319 vn_a.flags = flags & ~MAP_TYPE; 3320 vn_a.cred = cr; 3321 vn_a.amp = NULL; 3322 vn_a.szc = 0; 3323 vn_a.lgrp_mem_policy_flags = 0; 3324 3325 error = as_map(as, *addrp, len, segvn_create, &vn_a); 3326 3327 as_rangeunlock(as); 3328 3329 out: 3330 smbfs_rw_exit(&np->r_lkserlock); 3331 3332 return (error); 3333 } 3334 3335 static int smbfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, 3336 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr, 3337 caller_context_t *ct) { 3338 atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, btopr(len)); 3339 return (0); 3340 } 3341 3342 static int smbfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, 3343 size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr, 3344 caller_context_t *ct) { 3345 3346 smbnode_t *np; 3347 3348 atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, -btopr(len)); 3349 3350 /* mark RDIRTY here, will be used to check if a file is dirty when unmount smbfs */ 3351 if (vn_has_cached_data(vp) && !vn_is_readonly(vp) && maxprot & PROT_WRITE && flags == MAP_SHARED) { 3352 np = VTOSMB(vp); 3353 mutex_enter(&np->r_statelock); 3354 np->r_flags |= RDIRTY; 3355 mutex_exit(&np->r_statelock); 3356 } 3357 return (0); 3358 } 3359 3360 static int smbfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, 3361 cred_t *cr, caller_context_t *ct) { 3362 3363 smbnode_t *np; 3364 size_t io_len; 3365 u_offset_t io_off; 3366 u_offset_t eoff; 3367 int error = 0; 3368 page_t *pp; 3369 3370 np = VTOSMB(vp); 3371 3372 if (len == 0) { 3373 /* will flush the file, so clear RDIRTY */ 3374 if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) { 3375 mutex_enter(&np->r_statelock); 3376 np->r_flags &= ~RDIRTY; 3377 mutex_exit(&np->r_statelock); 3378 } 3379 3380 error = pvn_vplist_dirty(vp, off, smbfs_putapage, flags, cr); 3381 } else { 3382 3383 eoff = off + len; 3384 3385 mutex_enter(&np->r_statelock); 3386 if (eoff > np->r_size) 3387 eoff = np->r_size; 3388 mutex_exit(&np->r_statelock); 3389 3390 for (io_off = off; io_off < eoff; io_off += io_len) { 3391 if ((flags & B_INVAL) || (flags & B_ASYNC) == 0) { 3392 pp = page_lookup(vp, io_off, 3393 (flags & (B_INVAL | B_FREE) ? SE_EXCL : SE_SHARED)); 3394 } else { 3395 pp = page_lookup_nowait(vp, io_off, 3396 (flags & B_FREE) ? SE_EXCL : SE_SHARED); 3397 } 3398 3399 if (pp == NULL || !pvn_getdirty(pp, flags)) 3400 io_len = PAGESIZE; 3401 else { 3402 error = smbfs_putapage(vp, pp, &io_off, &io_len, flags, cr); 3403 } 3404 } 3405 3406 } 3407 3408 return (error); 3409 } 3410 3411 static int smbfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, 3412 int flags, cred_t *cr) { 3413 3414 struct smb_cred scred; 3415 smbnode_t *np; 3416 smbmntinfo_t *smi; 3417 smb_share_t *ssp; 3418 uio_t uio; 3419 iovec_t uiov, uiov_bak; 3420 3421 size_t io_len; 3422 u_offset_t io_off; 3423 size_t bsize; 3424 size_t blksize; 3425 u_offset_t blkoff; 3426 int error; 3427 3428 np = VTOSMB(vp); 3429 smi = VTOSMI(vp); 3430 ssp = smi->smi_share; 3431 3432 /*do block io, get a kluster of dirty pages in a block.*/ 3433 bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); 3434 blkoff = pp->p_offset / bsize; 3435 blkoff *= bsize; 3436 blksize = roundup(bsize, PAGESIZE); 3437 3438 pp = pvn_write_kluster(vp, pp, &io_off, &io_len, blkoff, blksize, flags); 3439 3440 ASSERT(pp->p_offset >= blkoff); 3441 3442 if (io_off + io_len > blkoff + blksize) { 3443 ASSERT((io_off + io_len)-(blkoff + blksize) < PAGESIZE); 3444 io_len = blkoff + blksize - io_off; 3445 } 3446 3447 /*currently, don't allow put pages beyond EOF, unless smbfs_read/smbfs_write 3448 *can do io through segkpm or vpm.*/ 3449 mutex_enter(&np->r_statelock); 3450 if (io_off >= np->r_size) { 3451 mutex_exit(&np->r_statelock); 3452 error = 0; 3453 goto out; 3454 } else if (io_off + io_len > np->r_size) { 3455 int npages = btopr(np->r_size - io_off); 3456 page_t *trunc; 3457 page_list_break(&pp, &trunc, npages); 3458 if (trunc) 3459 pvn_write_done(trunc, flags); 3460 io_len = np->r_size - io_off; 3461 } 3462 mutex_exit(&np->r_statelock); 3463 3464 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 3465 return (EINTR); 3466 smb_credinit(&scred, cr); 3467 3468 if (np->n_vcgenid != ssp->ss_vcgenid) 3469 error = ESTALE; 3470 else { 3471 /*just use uio instead of buf, since smb_rwuio need uio.*/ 3472 uiov.iov_base = 0; 3473 uiov.iov_len = 0; 3474 uio.uio_iov = &uiov; 3475 uio.uio_iovcnt = 1; 3476 uio.uio_loffset = io_off; 3477 uio.uio_resid = io_len; 3478 uio.uio_segflg = UIO_SYSSPACE; 3479 uio.uio_llimit = MAXOFFSET_T; 3480 /*map pages into kernel address space, and setup uio.*/ 3481 error = uio_page_mapin(&uio, pp); 3482 if (error == 0) { 3483 uiov_bak.iov_base = uiov.iov_base; 3484 uiov_bak.iov_len = uiov.iov_len; 3485 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE, &uio, &scred, smb_timo_write); 3486 if (error == 0) { 3487 mutex_enter(&np->r_statelock); 3488 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 3489 mutex_exit(&np->r_statelock); 3490 (void) smbfs_smb_flush(np, &scred); 3491 } 3492 /*unmap pages from kernel address space.*/ 3493 uio.uio_iov = &uiov_bak; 3494 uio_page_mapout(&uio, pp); 3495 } 3496 } 3497 3498 smb_credrele(&scred); 3499 smbfs_rw_exit(&np->r_lkserlock); 3500 3501 out: 3502 pvn_write_done(pp, ((error) ? B_ERROR : 0) | B_WRITE | flags); 3503 3504 if (offp) 3505 *offp = io_off; 3506 if (lenp) 3507 *lenp = io_len; 3508 3509 return (error); 3510 } 3511 3512 static int smbfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp, 3513 page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr, 3514 enum seg_rw rw, cred_t *cr, caller_context_t *ct) { 3515 3516 int error; 3517 3518 /*these pages have all protections.*/ 3519 if (protp) 3520 *protp = PROT_ALL; 3521 3522 if (len <= PAGESIZE) { 3523 error = smbfs_getapage(vp, off, len, protp, pl, plsz, seg, addr, rw, 3524 cr); 3525 } else { 3526 error = pvn_getpages(smbfs_getapage, vp, off, len, protp, pl, plsz, seg, 3527 addr, rw, cr); 3528 } 3529 3530 return (error); 3531 } 3532 3533 static int smbfs_getapage(vnode_t *vp, u_offset_t off, size_t len, 3534 uint_t *protp, page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr, 3535 enum seg_rw rw, cred_t *cr) { 3536 3537 smbnode_t *np; 3538 smbmntinfo_t *smi; 3539 smb_share_t *ssp; 3540 smb_cred_t scred; 3541 3542 page_t *pp; 3543 uio_t uio; 3544 iovec_t uiov, uiov_bak; 3545 3546 u_offset_t blkoff; 3547 size_t bsize; 3548 size_t blksize; 3549 3550 u_offset_t io_off; 3551 size_t io_len; 3552 size_t pages_len; 3553 3554 int error = 0; 3555 3556 np = VTOSMB(vp); 3557 smi = VTOSMI(vp); 3558 ssp = smi->smi_share; 3559 3560 /*if pl is null,it's meaningless*/ 3561 if (pl == NULL) 3562 return (EFAULT); 3563 3564 again: 3565 if (page_exists(vp, off) == NULL) { 3566 if (rw == S_CREATE) { 3567 /*just return a empty page if asked to create.*/ 3568 if ((pp = page_create_va(vp, off, PAGESIZE, PG_WAIT | PG_EXCL, seg, addr)) == NULL) 3569 goto again; 3570 pages_len = PAGESIZE; 3571 } else { 3572 3573 /*do block io, get a kluster of non-exist pages in a block.*/ 3574 bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE); 3575 blkoff = off / bsize; 3576 blkoff *= bsize; 3577 blksize = roundup(bsize, PAGESIZE); 3578 3579 pp = pvn_read_kluster(vp, off, seg, addr, &io_off, &io_len, blkoff, blksize, 0); 3580 3581 if (pp == NULL) 3582 goto again; 3583 3584 pages_len = io_len; 3585 3586 /*currently, don't allow get pages beyond EOF, unless smbfs_read/smbfs_write 3587 *can do io through segkpm or vpm.*/ 3588 mutex_enter(&np->r_statelock); 3589 if (io_off >= np->r_size) { 3590 mutex_exit(&np->r_statelock); 3591 error = 0; 3592 goto out; 3593 } else if (io_off + io_len > np->r_size) { 3594 int npages = btopr(np->r_size - io_off); 3595 page_t *trunc; 3596 3597 page_list_break(&pp, &trunc, npages); 3598 if (trunc) 3599 pvn_read_done(trunc, 0); 3600 io_len = np->r_size - io_off; 3601 } 3602 mutex_exit(&np->r_statelock); 3603 3604 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 3605 return EINTR; 3606 smb_credinit(&scred, cr); 3607 3608 /*just use uio instead of buf, since smb_rwuio need uio.*/ 3609 uiov.iov_base = 0; 3610 uiov.iov_len = 0; 3611 uio.uio_iov = &uiov; 3612 uio.uio_iovcnt = 1; 3613 uio.uio_loffset = io_off; 3614 uio.uio_resid = io_len; 3615 uio.uio_segflg = UIO_SYSSPACE; 3616 uio.uio_llimit = MAXOFFSET_T; 3617 3618 /*map pages into kernel address space, and setup uio.*/ 3619 error = uio_page_mapin(&uio, pp); 3620 if (error == 0) { 3621 uiov_bak.iov_base = uiov.iov_base; 3622 uiov_bak.iov_len = uiov.iov_len; 3623 error = smb_rwuio(ssp, np->n_fid, UIO_READ, &uio, &scred, smb_timo_read); 3624 /*unmap pages from kernel address space.*/ 3625 uio.uio_iov = &uiov_bak; 3626 uio_page_mapout(&uio, pp); 3627 } 3628 3629 smb_credrele(&scred); 3630 smbfs_rw_exit(&np->r_lkserlock); 3631 } 3632 } else { 3633 se_t se = rw == S_CREATE ? SE_EXCL : SE_SHARED; 3634 if ((pp = page_lookup(vp, off, se)) == NULL) { 3635 goto again; 3636 } 3637 } 3638 3639 out: 3640 if (pp) { 3641 if (error) { 3642 pvn_read_done(pp, B_ERROR); 3643 } else { 3644 /*init page list, unlock pages.*/ 3645 pvn_plist_init(pp, pl, plsz, off, pages_len, rw); 3646 } 3647 } 3648 3649 return (error); 3650 } 3651 3652 3653 void smbfs_invalidate_pages(vnode_t *vp, u_offset_t off, cred_t *cr) { 3654 3655 smbnode_t *np; 3656 3657 np = VTOSMB(vp); 3658 /* will flush the file, so clear RDIRTY */ 3659 if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) { 3660 mutex_enter(&np->r_statelock); 3661 np->r_flags &= ~RDIRTY; 3662 mutex_exit(&np->r_statelock); 3663 } 3664 3665 (void) pvn_vplist_dirty(vp, off, smbfs_putapage, B_INVAL | B_TRUNC, cr); 3666 } 3667 3668