Print this page
cstyle
Fix missing logic for ESTALE and NFS_EOF
Implement ioctl _FIODIRECTIO
Kill flags arg in smbfs_purge_caches
Lots of comment cleanup
5404 smbfs needs mmap support
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>


  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 <netsmb/smb_osdep.h>
  55 #include <netsmb/smb.h>
  56 #include <netsmb/smb_conn.h>
  57 #include <netsmb/smb_subr.h>
  58 
  59 #include <smbfs/smbfs.h>
  60 #include <smbfs/smbfs_node.h>
  61 #include <smbfs/smbfs_subr.h>
  62 
  63 #include <sys/fs/smbfs_ioctl.h>
  64 #include <fs/fs_subr.h>
  65 
  66 /*
  67  * We assign directory offsets like the NFS client, where the
  68  * offset increments by _one_ after each directory entry.
  69  * Further, the entries "." and ".." are always at offsets
  70  * zero and one (respectively) and the "real" entries from
  71  * the server appear at offsets starting with two.  This
  72  * macro is used to initialize the n_dirofs field after
  73  * setting n_dirseq with a _findopen call.


  84 static const char illegal_chars[] = {
  85         ':',    /* colon - keep this first! */
  86         '\\',   /* back slash */
  87         '/',    /* slash */
  88         '*',    /* asterisk */
  89         '?',    /* question mark */
  90         '"',    /* double quote */
  91         '<', /* less than sign */
  92         '>', /* greater than sign */
  93         '|',    /* vertical bar */
  94         0
  95 };
  96 
  97 /*
  98  * Turning this on causes nodes to be created in the cache
  99  * during directory listings, normally avoiding a second
 100  * OtW attribute fetch just after a readdir.
 101  */
 102 int smbfs_fastlookup = 1;
 103 


 104 /* local static function defines */
 105 
 106 static int      smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
 107                         cred_t *);
 108 static int      smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
 109                         int cache_ok, caller_context_t *);
 110 static int      smbfsremove(vnode_t *dvp, vnode_t *vp, struct smb_cred *scred,
 111                         int flags);
 112 static int      smbfsrename(vnode_t *odvp, vnode_t *ovp, vnode_t *ndvp,
 113                         char *nnm, struct smb_cred *scred, int flags);
 114 static int      smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
 115 static int      smbfs_accessx(void *, int, cred_t *);
 116 static int      smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
 117                         caller_context_t *);
 118 static void     smbfs_rele_fid(smbnode_t *, struct smb_cred *);
 119 static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *);
 120 
















 121 /*









 122  * These are the vnode ops routines which implement the vnode interface to
 123  * the networked file system.  These routines just take their parameters,
 124  * make them look networkish by putting the right info into interface structs,
 125  * and then calling the appropriate remote routine(s) to do the work.
 126  *
 127  * Note on directory name lookup cacheing:  If we detect a stale fhandle,
 128  * we purge the directory cache relative to that vnode.  This way, the
 129  * user won't get burned by the cache repeatedly.  See <smbfs/smbnode.h> for
 130  * more details on smbnode locking.
 131  */
 132 
 133 static int      smbfs_open(vnode_t **, int, cred_t *, caller_context_t *);
 134 static int      smbfs_close(vnode_t *, int, int, offset_t, cred_t *,
 135                         caller_context_t *);
 136 static int      smbfs_read(vnode_t *, struct uio *, int, cred_t *,
 137                         caller_context_t *);
 138 static int      smbfs_write(vnode_t *, struct uio *, int, cred_t *,
 139                         caller_context_t *);
 140 static int      smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
 141                         caller_context_t *);
 142 static int      smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *,
 143                         caller_context_t *);
 144 static int      smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *,
 145                         caller_context_t *);
 146 static int      smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *);
 147 static int      smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
 148 static void     smbfs_inactive(vnode_t *, cred_t *, caller_context_t *);
 149 static int      smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *,
 150                         int, vnode_t *, cred_t *, caller_context_t *,
 151                         int *, pathname_t *);
 152 static int      smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl,
 153                         int, vnode_t **, cred_t *, int, caller_context_t *,
 154                         vsecattr_t *);
 155 static int      smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *,
 156                         int);
 157 static int      smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *,
 158                         caller_context_t *, int);
 159 static int      smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **,
 160                         cred_t *, caller_context_t *, int, vsecattr_t *);
 161 static int      smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
 162                         caller_context_t *, int);
 163 static int      smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
 164                         caller_context_t *, int);
 165 static int      smbfs_rwlock(vnode_t *, int, caller_context_t *);
 166 static void     smbfs_rwunlock(vnode_t *, int, caller_context_t *);
 167 static int      smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
 168 static int      smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
 169                         struct flk_callback *, cred_t *, caller_context_t *);
 170 static int      smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
 171                         cred_t *, caller_context_t *);
 172 static int      smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
 173                         caller_context_t *);
 174 static int      smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
 175                         caller_context_t *);
 176 static int      smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
 177                         caller_context_t *);
 178 static int      smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
 179                         caller_context_t *);
 180 
 181 /* Dummy function to use until correct function is ported in */
 182 int noop_vnodeop() {
 183         return (0);
 184 }
 185 
 186 struct vnodeops *smbfs_vnodeops = NULL;
 187 
 188 /*
 189  * Most unimplemented ops will return ENOSYS because of fs_nosys().
 190  * The only ops where that won't work are ACCESS (due to open(2)
 191  * failures) and ... (anything else left?)
 192  */
 193 const fs_operation_def_t smbfs_vnodeops_template[] = {
 194         { VOPNAME_OPEN,         { .vop_open = smbfs_open } },
 195         { VOPNAME_CLOSE,        { .vop_close = smbfs_close } },
 196         { VOPNAME_READ,         { .vop_read = smbfs_read } },
 197         { VOPNAME_WRITE,        { .vop_write = smbfs_write } },
 198         { VOPNAME_IOCTL,        { .vop_ioctl = smbfs_ioctl } },
 199         { VOPNAME_GETATTR,      { .vop_getattr = smbfs_getattr } },
 200         { VOPNAME_SETATTR,      { .vop_setattr = smbfs_setattr } },
 201         { VOPNAME_ACCESS,       { .vop_access = smbfs_access } },
 202         { VOPNAME_LOOKUP,       { .vop_lookup = smbfs_lookup } },
 203         { VOPNAME_CREATE,       { .vop_create = smbfs_create } },
 204         { VOPNAME_REMOVE,       { .vop_remove = smbfs_remove } },
 205         { VOPNAME_LINK,         { .error = fs_nosys } }, /* smbfs_link, */
 206         { VOPNAME_RENAME,       { .vop_rename = smbfs_rename } },
 207         { VOPNAME_MKDIR,        { .vop_mkdir = smbfs_mkdir } },
 208         { VOPNAME_RMDIR,        { .vop_rmdir = smbfs_rmdir } },
 209         { VOPNAME_READDIR,      { .vop_readdir = smbfs_readdir } },
 210         { VOPNAME_SYMLINK,      { .error = fs_nosys } }, /* smbfs_symlink, */
 211         { VOPNAME_READLINK,     { .error = fs_nosys } }, /* smbfs_readlink, */
 212         { VOPNAME_FSYNC,        { .vop_fsync = smbfs_fsync } },
 213         { VOPNAME_INACTIVE,     { .vop_inactive = smbfs_inactive } },
 214         { VOPNAME_FID,          { .error = fs_nosys } }, /* smbfs_fid, */
 215         { VOPNAME_RWLOCK,       { .vop_rwlock = smbfs_rwlock } },
 216         { VOPNAME_RWUNLOCK,     { .vop_rwunlock = smbfs_rwunlock } },
 217         { VOPNAME_SEEK,         { .vop_seek = smbfs_seek } },
 218         { VOPNAME_FRLOCK,       { .vop_frlock = smbfs_frlock } },
 219         { VOPNAME_SPACE,        { .vop_space = smbfs_space } },
 220         { VOPNAME_REALVP,       { .error = fs_nosys } }, /* smbfs_realvp, */
 221         { VOPNAME_GETPAGE,      { .error = fs_nosys } }, /* smbfs_getpage, */
 222         { VOPNAME_PUTPAGE,      { .error = fs_nosys } }, /* smbfs_putpage, */
 223         { VOPNAME_MAP,          { .error = fs_nosys } }, /* smbfs_map, */
 224         { VOPNAME_ADDMAP,       { .error = fs_nosys } }, /* smbfs_addmap, */
 225         { VOPNAME_DELMAP,       { .error = fs_nosys } }, /* smbfs_delmap, */
 226         { VOPNAME_DUMP,         { .error = fs_nosys } }, /* smbfs_dump, */
 227         { VOPNAME_PATHCONF,     { .vop_pathconf = smbfs_pathconf } },
 228         { VOPNAME_PAGEIO,       { .error = fs_nosys } }, /* smbfs_pageio, */
 229         { VOPNAME_SETSECATTR,   { .vop_setsecattr = smbfs_setsecattr } },
 230         { VOPNAME_GETSECATTR,   { .vop_getsecattr = smbfs_getsecattr } },
 231         { VOPNAME_SHRLOCK,      { .vop_shrlock = smbfs_shrlock } },
 232         { NULL, NULL }
 233 };
 234 
 235 /*
 236  * XXX
 237  * When new and relevant functionality is enabled, we should be
 238  * calling vfs_set_feature() to inform callers that pieces of
 239  * functionality are available, per PSARC 2007/227.
 240  */
 241 /* ARGSUSED */
 242 static int
 243 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
 244 {
 245         smbnode_t       *np;
 246         vnode_t         *vp;
 247         smbfattr_t      fa;
 248         u_int32_t       rights, rightsrcvd;
 249         u_int16_t       fid, oldfid;
 250         int             oldgenid;
 251         struct smb_cred scred;
 252         smbmntinfo_t    *smi;
 253         smb_share_t     *ssp;
 254         cred_t          *oldcr;
 255         int             tmperror;


 267                 return (EIO);
 268 
 269         if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */
 270                 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type);
 271                 return (EACCES);
 272         }
 273 
 274         /*
 275          * Get exclusive access to n_fid and related stuff.
 276          * No returns after this until out.
 277          */
 278         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
 279                 return (EINTR);
 280         smb_credinit(&scred, cr);
 281 
 282         /*
 283          * Keep track of the vnode type at first open.
 284          * It may change later, and we need close to do
 285          * cleanup for the type we opened.  Also deny
 286          * open of new types until old type is closed.
 287          * XXX: Per-open instance nodes whould help.
 288          */
 289         if (np->n_ovtype == VNON) {
 290                 ASSERT(np->n_dirrefs == 0);
 291                 ASSERT(np->n_fidrefs == 0);
 292         } else if (np->n_ovtype != vp->v_type) {
 293                 SMBVDEBUG("open n_ovtype=%d v_type=%d\n",
 294                     np->n_ovtype, vp->v_type);
 295                 error = EACCES;
 296                 goto out;
 297         }
 298 
 299         /*
 300          * Directory open.  See smbfs_readvdir()
 301          */
 302         if (vp->v_type == VDIR) {
 303                 if (np->n_dirseq == NULL) {
 304                         /* first open */
 305                         error = smbfs_smb_findopen(np, "*", 1,
 306                             SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
 307                             &scred, &np->n_dirseq);


 406          * Keep track of the vnode type at first open.
 407          * (see comments above)
 408          */
 409         if (np->n_ovtype == VNON)
 410                 np->n_ovtype = vp->v_type;
 411 
 412 out:
 413         smb_credrele(&scred);
 414         smbfs_rw_exit(&np->r_lkserlock);
 415         return (error);
 416 }
 417 
 418 /*ARGSUSED*/
 419 static int
 420 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
 421         caller_context_t *ct)
 422 {
 423         smbnode_t       *np;
 424         smbmntinfo_t    *smi;
 425         struct smb_cred scred;

 426 
 427         np = VTOSMB(vp);
 428         smi = VTOSMI(vp);
 429 
 430         /*
 431          * Don't "bail out" for VFS_UNMOUNTED here,
 432          * as we want to do cleanup, etc.
 433          */
 434 
 435         /*
 436          * zone_enter(2) prevents processes from changing zones with SMBFS files
 437          * open; if we happen to get here from the wrong zone we can't do
 438          * anything over the wire.
 439          */
 440         if (smi->smi_zone_ref.zref_zone != curproc->p_zone) {
 441                 /*
 442                  * We could attempt to clean up locks, except we're sure
 443                  * that the current process didn't acquire any locks on
 444                  * the file: any attempt to lock a file belong to another zone
 445                  * will fail, and one can't lock an SMBFS file and then change


 453                  * everything (minus the final smbfs_getattr_otw() call) should
 454                  * be OK. If the zone is going away smbfs_async_inactive() will
 455                  * throw away cached pages inline.
 456                  */
 457                 return (EIO);
 458         }
 459 
 460         /*
 461          * If we are using local locking for this filesystem, then
 462          * release all of the SYSV style record locks.  Otherwise,
 463          * we are doing network locking and we need to release all
 464          * of the network locks.  All of the locks held by this
 465          * process on this file are released no matter what the
 466          * incoming reference count is.
 467          */
 468         if (smi->smi_flags & SMI_LLOCK) {
 469                 pid_t pid = ddi_get_pid();
 470                 cleanlocks(vp, pid, 0);
 471                 cleanshares(vp, pid);
 472         }




 473 
 474         /*
 475          * This (passed in) count is the ref. count from the
 476          * user's file_t before the closef call (fio.c).
 477          * We only care when the reference goes away.
 478          */
 479         if (count > 1)
 480                 return (0);
 481 


 482         /*




















 483          * Decrement the reference count for the FID
 484          * and possibly do the OtW close.
 485          *
 486          * Exclusive lock for modifying n_fid stuff.
 487          * Don't want this one ever interruptible.
 488          */
 489         (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
 490         smb_credinit(&scred, cr);
 491 
 492         smbfs_rele_fid(np, &scred);
 493 
 494         smb_credrele(&scred);
 495         smbfs_rw_exit(&np->r_lkserlock);
 496 
 497         return (0);
 498 }
 499 
 500 /*
 501  * Helper for smbfs_close.  Decrement the reference count
 502  * for an SMB-level file or directory ID, and when the last


 573         np->r_cred = NULL;
 574         mutex_exit(&np->r_statelock);
 575         if (oldcr != NULL)
 576                 crfree(oldcr);
 577 }
 578 
 579 /* ARGSUSED */
 580 static int
 581 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
 582         caller_context_t *ct)
 583 {
 584         struct smb_cred scred;
 585         struct vattr    va;
 586         smbnode_t       *np;
 587         smbmntinfo_t    *smi;
 588         smb_share_t     *ssp;
 589         offset_t        endoff;
 590         ssize_t         past_eof;
 591         int             error;
 592 






 593         np = VTOSMB(vp);
 594         smi = VTOSMI(vp);
 595         ssp = smi->smi_share;
 596 
 597         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 598                 return (EIO);
 599 
 600         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
 601                 return (EIO);
 602 
 603         ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
 604 
 605         if (vp->v_type != VREG)
 606                 return (EISDIR);
 607 
 608         if (uiop->uio_resid == 0)
 609                 return (0);
 610 
 611         /*
 612          * Like NFS3, just check for 63-bit overflow.


 622         if (error = smbfsgetattr(vp, &va, cr))
 623                 return (error);
 624 
 625         /* Update mtime with mtime from server here? */
 626 
 627         /* if offset is beyond EOF, read nothing */
 628         if (uiop->uio_loffset >= va.va_size)
 629                 return (0);
 630 
 631         /*
 632          * Limit the read to the remaining file size.
 633          * Do this by temporarily reducing uio_resid
 634          * by the amount the lies beyoned the EOF.
 635          */
 636         if (endoff > va.va_size) {
 637                 past_eof = (ssize_t)(endoff - va.va_size);
 638                 uiop->uio_resid -= past_eof;
 639         } else
 640                 past_eof = 0;
 641 










 642         /* Shared lock for n_fid use in smb_rwuio */
 643         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
 644                 return (EINTR);
 645         smb_credinit(&scred, cr);
 646 
 647         /* After reconnect, n_fid is invalid */
 648         if (np->n_vcgenid != ssp->ss_vcgenid)
 649                 error = ESTALE;
 650         else
 651                 error = smb_rwuio(ssp, np->n_fid, UIO_READ,
 652                     uiop, &scred, smb_timo_read);
 653 
 654         smb_credrele(&scred);
 655         smbfs_rw_exit(&np->r_lkserlock);
 656 
 657         /* undo adjustment of resid */
 658         uiop->uio_resid += past_eof;
 659 
 660         return (error);

























































 661 }
 662 
 663 
 664 /* ARGSUSED */
 665 static int
 666 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
 667         caller_context_t *ct)
 668 {
 669         struct smb_cred scred;
 670         struct vattr    va;
 671         smbnode_t       *np;
 672         smbmntinfo_t    *smi;
 673         smb_share_t     *ssp;
 674         offset_t        endoff, limit;
 675         ssize_t         past_limit;
 676         int             error, timo;








 677 
 678         np = VTOSMB(vp);
 679         smi = VTOSMI(vp);
 680         ssp = smi->smi_share;
 681 
 682         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 683                 return (EIO);
 684 
 685         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
 686                 return (EIO);
 687 
 688         ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
 689 
 690         if (vp->v_type != VREG)
 691                 return (EISDIR);
 692 
 693         if (uiop->uio_resid == 0)
 694                 return (0);
 695 
 696         /*
 697          * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
 698          */
 699         if (ioflag & (FAPPEND | FSYNC)) {
 700                 if (np->n_flag & NMODIFIED) {
 701                         smbfs_attrcache_remove(np);
 702                         /* XXX: smbfs_vinvalbuf? */
 703                 }
 704         }
 705         if (ioflag & FAPPEND) {
 706                 /*
 707                  * File size can be changed by another client



 708                  */
 709                 va.va_mask = AT_SIZE;
 710                 if (error = smbfsgetattr(vp, &va, cr))
 711                         return (error);
 712                 uiop->uio_loffset = va.va_size;
 713         }
 714 
 715         /*
 716          * Like NFS3, just check for 63-bit overflow.
 717          */
 718         endoff = uiop->uio_loffset + uiop->uio_resid;
 719         if (uiop->uio_loffset < 0 || endoff < 0)
 720                 return (EINVAL);
 721 
 722         /*
 723          * Check to make sure that the process will not exceed
 724          * its limit on file size.  It is okay to write up to
 725          * the limit, but not beyond.  Thus, the write which
 726          * reaches the limit will be short and the next write
 727          * will return an error.
 728          *
 729          * So if we're starting at or beyond the limit, EFBIG.
 730          * Otherwise, temporarily reduce resid to the amount
 731          * the falls after the limit.
 732          */
 733         limit = uiop->uio_llimit;
 734         if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
 735                 limit = MAXOFFSET_T;
 736         if (uiop->uio_loffset >= limit)






 737                 return (EFBIG);

 738         if (endoff > limit) {
 739                 past_limit = (ssize_t)(endoff - limit);
 740                 uiop->uio_resid -= past_limit;
 741         } else
 742                 past_limit = 0;
 743 
























 744         /* Timeout: longer for append. */
 745         timo = smb_timo_write;
 746         if (endoff > np->r_size)
 747                 timo = smb_timo_append;
 748 
 749         /* Shared lock for n_fid use in smb_rwuio */
 750         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
 751                 return (EINTR);
 752         smb_credinit(&scred, cr);
 753 
 754         /* After reconnect, n_fid is invalid */
 755         if (np->n_vcgenid != ssp->ss_vcgenid)
 756                 error = ESTALE;
 757         else
 758                 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
 759                     uiop, &scred, timo);
 760 
 761         if (error == 0) {
 762                 mutex_enter(&np->r_statelock);
 763                 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
 764                 if (uiop->uio_loffset > (offset_t)np->r_size)
 765                         np->r_size = (len_t)uiop->uio_loffset;
 766                 mutex_exit(&np->r_statelock);
 767                 if (ioflag & (FSYNC|FDSYNC)) {
 768                         /* Don't error the I/O if this fails. */
 769                         (void) smbfs_smb_flush(np, &scred);
 770                 }
 771         }
 772 
 773         smb_credrele(&scred);
 774         smbfs_rw_exit(&np->r_lkserlock);
 775 
 776         /* undo adjustment of resid */
 777         uiop->uio_resid += past_limit;
 778 
 779         return (error);













































































































































 780 }
 781 





 782 



































































































































































































































































































































































 783 /* ARGSUSED */
 784 static int
 785 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
 786         cred_t *cr, int *rvalp, caller_context_t *ct)
 787 {
 788         int             error;
 789         smbmntinfo_t    *smi;
 790 
 791         smi = VTOSMI(vp);
 792 
 793         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 794                 return (EIO);
 795 
 796         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
 797                 return (EIO);
 798 
 799         switch (cmd) {
 800                 /* First three from ZFS. XXX - need these? */
 801 
 802         case _FIOFFS:
 803                 error = smbfs_fsync(vp, 0, cr, ct);
 804                 break;
 805 
 806                 /*
 807                  * The following two ioctls are used by bfu.
 808                  * Silently ignore to avoid bfu errors.
 809                  */
 810         case _FIOGDIO:
 811         case _FIOSDIO:
 812                 error = 0;
 813                 break;
 814 
 815 #ifdef NOT_YET  /* XXX - from the NFS code. */




 816         case _FIODIRECTIO:
 817                 error = smbfs_directio(vp, (int)arg, cr);
 818 #endif
 819 
 820                 /*
 821                  * Allow get/set with "raw" security descriptor (SD) data.
 822                  * Useful for testing, diagnosing idmap problems, etc.
 823                  */
 824         case SMBFSIO_GETSD:
 825                 error = smbfs_acl_iocget(vp, arg, flag, cr);
 826                 break;
 827 
 828         case SMBFSIO_SETSD:
 829                 error = smbfs_acl_iocset(vp, arg, flag, cr);
 830                 break;
 831 
 832         default:
 833                 error = ENOTTY;
 834                 break;
 835         }
 836 
 837         return (error);
 838 }
 839 
 840 
 841 /*
 842  * Return either cached or remote attributes. If get remote attr
 843  * use them to check and invalidate caches, then cache the new attributes.
 844  */
 845 /* ARGSUSED */
 846 static int
 847 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
 848         caller_context_t *ct)
 849 {
 850         smbnode_t *np;
 851         smbmntinfo_t *smi;

 852 
 853         smi = VTOSMI(vp);
 854 
 855         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 856                 return (EIO);
 857 
 858         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
 859                 return (EIO);
 860 
 861         /*
 862          * If it has been specified that the return value will
 863          * just be used as a hint, and we are only being asked
 864          * for size, fsid or rdevid, then return the client's
 865          * notion of these values without checking to make sure
 866          * that the attribute cache is up to date.
 867          * The whole point is to avoid an over the wire GETATTR
 868          * call.
 869          */
 870         np = VTOSMB(vp);
 871         if (flags & ATTR_HINT) {
 872                 if (vap->va_mask ==
 873                     (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) {
 874                         mutex_enter(&np->r_statelock);
 875                         if (vap->va_mask | AT_SIZE)
 876                                 vap->va_size = np->r_size;
 877                         if (vap->va_mask | AT_FSID)
 878                                 vap->va_fsid = vp->v_vfsp->vfs_dev;
 879                         if (vap->va_mask | AT_RDEV)
 880                                 vap->va_rdev = vp->v_rdev;
 881                         mutex_exit(&np->r_statelock);
 882                         return (0);
 883                 }
 884         }
 885 
























 886         return (smbfsgetattr(vp, vap, cr));
 887 }
 888 
 889 /* smbfsgetattr() in smbfs_client.c */
 890 
 891 /*ARGSUSED4*/
 892 static int
 893 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
 894                 caller_context_t *ct)
 895 {
 896         vfs_t           *vfsp;
 897         smbmntinfo_t    *smi;
 898         int             error;
 899         uint_t          mask;
 900         struct vattr    oldva;
 901 
 902         vfsp = vp->v_vfsp;
 903         smi = VFTOSMI(vfsp);
 904 
 905         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)


 936                 return (error);
 937 
 938         if (mask & (AT_UID | AT_GID)) {
 939                 if (smi->smi_flags & SMI_ACL)
 940                         error = smbfs_acl_setids(vp, vap, cr);
 941                 else
 942                         error = ENOSYS;
 943                 if (error != 0) {
 944                         SMBVDEBUG("error %d seting UID/GID on %s",
 945                             error, VTOSMB(vp)->n_rpath);
 946                         /*
 947                          * It might be more correct to return the
 948                          * error here, but that causes complaints
 949                          * when root extracts a cpio archive, etc.
 950                          * So ignore this error, and go ahead with
 951                          * the rest of the setattr work.
 952                          */
 953                 }
 954         }
 955 
 956         return (smbfssetattr(vp, vap, flags, cr));







 957 }
 958 
 959 /*
 960  * Mostly from Darwin smbfs_setattr()
 961  * but then modified a lot.
 962  */
 963 /* ARGSUSED */
 964 static int
 965 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
 966 {
 967         int             error = 0;
 968         smbnode_t       *np = VTOSMB(vp);
 969         uint_t          mask = vap->va_mask;
 970         struct timespec *mtime, *atime;
 971         struct smb_cred scred;
 972         int             cerror, modified = 0;
 973         unsigned short  fid;
 974         int have_fid = 0;
 975         uint32_t rights = 0;
 976         uint32_t dosattr = 0;
 977 
 978         ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
 979 
 980         /*
 981          * There are no settable attributes on the XATTR dir,
 982          * so just silently ignore these.  On XATTR files,
 983          * you can set the size but nothing else.
 984          */
 985         if (vp->v_flag & V_XATTRDIR)
 986                 return (0);
 987         if (np->n_flag & N_XATTR) {
 988                 if (mask & AT_TIMES)
 989                         SMBVDEBUG("ignore set time on xattr\n");
 990                 mask &= AT_SIZE;
 991         }
 992 
 993         /*

























 994          * If our caller is trying to set multiple attributes, they
 995          * can make no assumption about what order they are done in.
 996          * Here we try to do them in order of decreasing likelihood
 997          * of failure, just to minimize the chance we'll wind up
 998          * with a partially complete request.
 999          */
1000 
1001         /* Shared lock for (possible) n_fid use. */
1002         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1003                 return (EINTR);
1004         smb_credinit(&scred, cr);
1005 
1006         /*
1007          * If the caller has provided extensible attributes,
1008          * map those into DOS attributes supported by SMB.
1009          * Note: zero means "no change".
1010          */
1011         if (mask & AT_XVATTR)
1012                 dosattr = xvattr_to_dosattr(np, vap);
1013 


1035                 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
1036                 if (error) {
1037                         SMBVDEBUG("error %d opening %s\n",
1038                             error, np->n_rpath);
1039                         goto out;
1040                 }
1041                 have_fid = 1;
1042         }
1043 
1044         /*
1045          * If the server supports the UNIX extensions, right here is where
1046          * we'd support changes to uid, gid, mode, and possibly va_flags.
1047          * For now we claim to have made any such changes.
1048          */
1049 
1050         if (mask & AT_SIZE) {
1051                 /*
1052                  * If the new file size is less than what the client sees as
1053                  * the file size, then just change the size and invalidate
1054                  * the pages.
1055                  * I am commenting this code at present because the function
1056                  * smbfs_putapage() is not yet implemented.
1057                  */
1058 
1059                 /*
1060                  * Set the file size to vap->va_size.
1061                  */
1062                 ASSERT(have_fid);
1063                 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred);
1064                 if (error) {
1065                         SMBVDEBUG("setsize error %d file %s\n",
1066                             error, np->n_rpath);
1067                 } else {
1068                         /*
1069                          * Darwin had code here to zero-extend.
1070                          * Tests indicate the server will zero-fill,
1071                          * so looks like we don't need to do this.
1072                          * Good thing, as this could take forever.
1073                          *
1074                          * XXX: Reportedly, writing one byte of zero
1075                          * at the end offset avoids problems here.
1076                          */
1077                         mutex_enter(&np->r_statelock);
1078                         np->r_size = vap->va_size;
1079                         mutex_exit(&np->r_statelock);
1080                         modified = 1;
1081                 }
1082         }
1083 
1084         /*
1085          * XXX: When Solaris has create_time, set that too.
1086          * Note: create_time is different from ctime.
1087          */
1088         mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
1089         atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
1090 
1091         if (dosattr || mtime || atime) {
1092                 /*
1093                  * Always use the handle-based set attr call now.
1094                  */
1095                 ASSERT(have_fid);
1096                 error = smbfs_smb_setfattr(np, fid,
1097                     dosattr, mtime, atime, &scred);
1098                 if (error) {
1099                         SMBVDEBUG("set times error %d file %s\n",
1100                             error, np->n_rpath);
1101                 } else {
1102                         modified = 1;
1103                 }
1104         }
1105 
1106 out:
1107         if (modified) {
1108                 /*
1109                  * Invalidate attribute cache in case the server
1110                  * doesn't set exactly the attributes we asked.
1111                  */
1112                 smbfs_attrcache_remove(np);
1113         }
1114 
1115         if (have_fid) {
1116                 cerror = smbfs_smb_tmpclose(np, fid, &scred);
1117                 if (cerror)
1118                         SMBVDEBUG("error %d closing %s\n",
1119                             cerror, np->n_rpath);
1120         }
1121 
1122         smb_credrele(&scred);
1123         smbfs_rw_exit(&np->r_lkserlock);
1124 

























1125         return (error);
1126 }
1127 
1128 /*
1129  * Helper function for extensible system attributes (PSARC 2007/315)
1130  * Compute the DOS attribute word to pass to _setfattr (see above).
1131  * This returns zero IFF no change is being made to attributes.
1132  * Otherwise return the new attributes or SMB_EFA_NORMAL.
1133  */
1134 static uint32_t
1135 xvattr_to_dosattr(smbnode_t *np, struct vattr *vap)
1136 {
1137         xvattr_t *xvap = (xvattr_t *)vap;
1138         xoptattr_t *xoap = NULL;
1139         uint32_t attr = np->r_attr.fa_attr;
1140         boolean_t anyset = B_FALSE;
1141 
1142         if ((xoap = xva_getxoptattr(xvap)) == NULL)
1143                 return (0);
1144 


1191  * due to the current "single user mounts" restriction:
1192  * All access under a given mount point uses the CIFS
1193  * credentials established by the owner of the mount.
1194  *
1195  * Most access checking is handled by the CIFS server,
1196  * but we need sufficient Unix access checks here to
1197  * prevent other local Unix users from having access
1198  * to objects under this mount that the uid/gid/mode
1199  * settings in the mount would not allow.
1200  *
1201  * With this model, there is a case where we need the
1202  * ability to do an access check before we have the
1203  * vnode for an object.  This function takes advantage
1204  * of the fact that the uid/gid/mode is per mount, and
1205  * avoids the need for a vnode.
1206  *
1207  * We still (sort of) need a vnode when we call
1208  * secpolicy_vnode_access, but that only uses
1209  * the vtype field, so we can use a pair of fake
1210  * vnodes that have only v_type filled in.
1211  *
1212  * XXX: Later, add a new secpolicy_vtype_access()
1213  * that takes the vtype instead of a vnode, and
1214  * get rid of the tmpl_vxxx fake vnodes below.
1215  */
1216 static int
1217 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
1218 {
1219         /* See the secpolicy call below. */
1220         static const vnode_t tmpl_vdir = { .v_type = VDIR };
1221         static const vnode_t tmpl_vreg = { .v_type = VREG };
1222         vattr_t         va;
1223         vnode_t         *tvp;
1224         struct smbmntinfo *smi = VFTOSMI(vfsp);
1225         int shift = 0;
1226 
1227         /*
1228          * Build our (fabricated) vnode attributes.
1229          * XXX: Could make these templates in the
1230          * per-mount struct and use them here.
1231          */
1232         bzero(&va, sizeof (va));
1233         va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1234         va.va_type = vtype;
1235         va.va_mode = (vtype == VDIR) ?
1236             smi->smi_dmode : smi->smi_fmode;
1237         va.va_uid = smi->smi_uid;
1238         va.va_gid = smi->smi_gid;
1239 
1240         /*
1241          * Disallow write attempts on read-only file systems,
1242          * unless the file is a device or fifo node.  Note:
1243          * Inline vn_is_readonly and IS_DEVVP here because
1244          * we may not have a vnode ptr.  Original expr. was:
1245          * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp))
1246          */
1247         if ((mode & VWRITE) &&
1248             (vfsp->vfs_flag & VFS_RDONLY) &&
1249             !(vtype == VCHR || vtype == VBLK || vtype == VFIFO))
1250                 return (EROFS);
1251 
1252         /*
1253          * Disallow attempts to access mandatory lock files.
1254          * Similarly, expand MANDLOCK here.
1255          * XXX: not sure we need this.
1256          */
1257         if ((mode & (VWRITE | VREAD | VEXEC)) &&
1258             va.va_type == VREG && MANDMODE(va.va_mode))
1259                 return (EACCES);
1260 
1261         /*
1262          * Access check is based on only
1263          * one of owner, group, public.
1264          * If not owner, then check group.
1265          * If not a member of the group,
1266          * then check public access.
1267          */
1268         if (crgetuid(cr) != va.va_uid) {
1269                 shift += 3;
1270                 if (!groupmember(va.va_gid, cr))
1271                         shift += 3;
1272         }
1273 
1274         /*
1275          * We need a vnode for secpolicy_vnode_access,


1305 /* ARGSUSED */
1306 static int
1307 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1308 {
1309         vfs_t           *vfsp;
1310         smbmntinfo_t    *smi;
1311 
1312         vfsp = vp->v_vfsp;
1313         smi = VFTOSMI(vfsp);
1314 
1315         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1316                 return (EIO);
1317 
1318         if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1319                 return (EIO);
1320 
1321         return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr));
1322 }
1323 
1324 









1325 /*
1326  * Flush local dirty pages to stable storage on the server.
1327  *
1328  * If FNODSYNC is specified, then there is nothing to do because
1329  * metadata changes are not cached on the client before being
1330  * sent to the server.
1331  */
1332 /* ARGSUSED */
1333 static int
1334 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
1335 {
1336         int             error = 0;
1337         smbmntinfo_t    *smi;
1338         smbnode_t       *np;
1339         struct smb_cred scred;
1340 
1341         np = VTOSMB(vp);
1342         smi = VTOSMI(vp);
1343 
1344         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1345                 return (EIO);
1346 
1347         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1348                 return (EIO);
1349 
1350         if ((syncflag & FNODSYNC) || IS_SWAPVP(vp))
1351                 return (0);
1352 
1353         if ((syncflag & (FSYNC|FDSYNC)) == 0)
1354                 return (0);
1355 




1356         /* Shared lock for n_fid use in _flush */
1357         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1358                 return (EINTR);
1359         smb_credinit(&scred, cr);
1360 
1361         error = smbfs_smb_flush(np, &scred);
1362 
1363         smb_credrele(&scred);
1364         smbfs_rw_exit(&np->r_lkserlock);
1365 
1366         return (error);
1367 }
1368 
1369 /*
1370  * Last reference to vnode went away.
1371  */
1372 /* ARGSUSED */
1373 static void
1374 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
1375 {
1376         smbnode_t       *np;
1377         struct smb_cred scred;


1378 
1379         /*
1380          * Don't "bail out" for VFS_UNMOUNTED here,
1381          * as we want to do cleanup, etc.
1382          * See also pcfs_inactive
1383          */
1384 
1385         np = VTOSMB(vp);
1386 
1387         /*
1388          * If this is coming from the wrong zone, we let someone in the right
1389          * zone take care of it asynchronously.  We can get here due to
1390          * VN_RELE() being called from pageout() or fsflush().  This call may
1391          * potentially turn into an expensive no-op if, for instance, v_count
1392          * gets incremented in the meantime, but it's still correct.
1393          */
1394 
1395         /*

































1396          * Defend against the possibility that higher-level callers
1397          * might not correctly balance open and close calls.  If we
1398          * get here with open references remaining, it means there
1399          * was a missing VOP_CLOSE somewhere.  If that happens, do
1400          * the close here so we don't "leak" FIDs on the server.
1401          *
1402          * Exclusive lock for modifying n_fid stuff.
1403          * Don't want this one ever interruptible.
1404          */
1405         (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1406         smb_credinit(&scred, cr);
1407 
1408         switch (np->n_ovtype) {
1409         case VNON:
1410                 /* not open (OK) */
1411                 break;
1412 
1413         case VDIR:
1414                 if (np->n_dirrefs == 0)
1415                         break;


1523         int             rplen;
1524         struct smb_cred scred;
1525         struct smbfattr fa;
1526 
1527         smi = VTOSMI(dvp);
1528         dnp = VTOSMB(dvp);
1529 
1530         ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1531 
1532 #ifdef NOT_YET
1533         vcp = SSTOVC(smi->smi_share);
1534 
1535         /* XXX: Should compute this once and store it in smbmntinfo_t */
1536         supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12;
1537 #else
1538         supplen = 255;
1539 #endif
1540 
1541         /*
1542          * RWlock must be held, either reader or writer.
1543          * XXX: Can we check without looking directly
1544          * inside the struct smbfs_rwlock_t?
1545          */
1546         ASSERT(dnp->r_rwlock.count != 0);
1547 
1548         /*
1549          * If lookup is for "", just return dvp.
1550          * No need to perform any access checks.
1551          */
1552         if (nmlen == 0) {
1553                 VN_HOLD(dvp);
1554                 *vpp = dvp;
1555                 return (0);
1556         }
1557 
1558         /*
1559          * Can't do lookups in non-directories.
1560          */
1561         if (dvp->v_type != VDIR)
1562                 return (ENOTDIR);
1563 
1564         /*


1571         /*
1572          * If lookup is for ".", just return dvp.
1573          * Access check was done above.
1574          */
1575         if (nmlen == 1 && name[0] == '.') {
1576                 VN_HOLD(dvp);
1577                 *vpp = dvp;
1578                 return (0);
1579         }
1580 
1581         /*
1582          * Now some sanity checks on the name.
1583          * First check the length.
1584          */
1585         if (nmlen > supplen)
1586                 return (ENAMETOOLONG);
1587 
1588         /*
1589          * Avoid surprises with characters that are
1590          * illegal in Windows file names.
1591          * Todo: CATIA mappings  XXX
1592          */
1593         ill = illegal_chars;
1594         if (dnp->n_flag & N_XATTR)
1595                 ill++; /* allow colon */
1596         if (strpbrk(nm, ill))
1597                 return (EINVAL);
1598 
1599         /*
1600          * Special handling for lookup of ".."
1601          *
1602          * We keep full pathnames (as seen on the server)
1603          * so we can just trim off the last component to
1604          * get the full pathname of the parent.  Note:
1605          * We don't actually copy and modify, but just
1606          * compute the trimmed length and pass that with
1607          * the current dir path (not null terminated).
1608          *
1609          * We don't go over-the-wire to get attributes
1610          * for ".." because we know it's a directory,
1611          * and we can just leave the rest "stale"


1792         if (np->r_attrtime <= gethrtime()) {
1793                 /* stale */
1794 #ifdef DEBUG
1795                 smbfs_lookup_cache_stale++;
1796 #endif
1797                 VN_RELE(vp);
1798                 return (0);
1799         }
1800 
1801         /*
1802          * Success!
1803          * Caller gets hold from smbfs_node_findcreate
1804          */
1805 #ifdef DEBUG
1806         smbfs_lookup_cache_hits++;
1807 #endif
1808         *vpp = vp;
1809         return (0);
1810 }
1811 

1812 /*
1813  * XXX
1814  * vsecattr_t is new to build 77, and we need to eventually support
1815  * it in order to create an ACL when an object is created.
1816  *
1817  * This op should support the new FIGNORECASE flag for case-insensitive
1818  * lookups, per PSARC 2007/244.
1819  */
1820 /* ARGSUSED */
1821 static int
1822 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
1823         int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
1824         vsecattr_t *vsecp)
1825 {
1826         int             error;
1827         int             cerror;
1828         vfs_t           *vfsp;
1829         vnode_t         *vp;
1830 #ifdef NOT_YET
1831         smbnode_t       *np;
1832 #endif
1833         smbnode_t       *dnp;
1834         smbmntinfo_t    *smi;
1835         struct vattr    vattr;
1836         struct smbfattr fattr;
1837         struct smb_cred scred;
1838         const char *name = (const char *)nm;
1839         int             nmlen = strlen(nm);
1840         uint32_t        disp;
1841         uint16_t        fid;
1842         int             xattr;
1843 
1844         vfsp = dvp->v_vfsp;
1845         smi = VFTOSMI(vfsp);
1846         dnp = VTOSMB(dvp);
1847         vp = NULL;
1848 
1849         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1850                 return (EPERM);
1851 
1852         if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1853                 return (EIO);
1854 
1855         /*
1856          * Note: this may break mknod(2) calls to create a directory,
1857          * but that's obscure use.  Some other filesystems do this.
1858          * XXX: Later, redirect VDIR type here to _mkdir.
1859          */
1860         if (va->va_type != VREG)
1861                 return (EINVAL);
1862 
1863         /*
1864          * If the pathname is "", just use dvp, no checks.
1865          * Do this outside of the rwlock (like zfs).
1866          */
1867         if (nmlen == 0) {
1868                 VN_HOLD(dvp);
1869                 *vpp = dvp;
1870                 return (0);
1871         }
1872 
1873         /* Don't allow "." or ".." through here. */
1874         if ((nmlen == 1 && name[0] == '.') ||
1875             (nmlen == 2 && name[0] == '.' && name[1] == '.'))
1876                 return (EISDIR);
1877 
1878         /*


1903                  * The file already exists.  Error?
1904                  * NB: have a hold from smbfslookup
1905                  */
1906                 if (exclusive == EXCL) {
1907                         error = EEXIST;
1908                         VN_RELE(vp);
1909                         goto out;
1910                 }
1911                 /*
1912                  * Verify requested access.
1913                  */
1914                 error = smbfs_access(vp, mode, 0, cr, ct);
1915                 if (error) {
1916                         VN_RELE(vp);
1917                         goto out;
1918                 }
1919 
1920                 /*
1921                  * Truncate (if requested).
1922                  */
1923                 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) {















1924                         vattr.va_mask = AT_SIZE;
1925                         error = smbfssetattr(vp, &vattr, 0, cr);
1926                         if (error) {
1927                                 VN_RELE(vp);
1928                                 goto out;
1929                         }
1930                 }
1931                 /* Success! */
1932 #ifdef NOT_YET
1933                 vnevent_create(vp, ct);
1934 #endif



1935                 *vpp = vp;
1936                 goto out;
1937         }
1938 
1939         /*
1940          * The file did not exist.  Need VWRITE in the directory.
1941          */
1942         error = smbfs_access(dvp, VWRITE, 0, cr, ct);
1943         if (error)
1944                 goto out;
1945 
1946         /*
1947          * Now things get tricky.  We also need to check the
1948          * requested open mode against the file we may create.
1949          * See comments at smbfs_access_rwx
1950          */
1951         error = smbfs_access_rwx(vfsp, VREG, mode, cr);
1952         if (error)
1953                 goto out;
1954 


1963 
1964         if (exclusive == EXCL)
1965                 disp = NTCREATEX_DISP_CREATE;
1966         else {
1967                 /* Truncate regular files if requested. */
1968                 if ((va->va_type == VREG) &&
1969                     (va->va_mask & AT_SIZE) &&
1970                     (va->va_size == 0))
1971                         disp = NTCREATEX_DISP_OVERWRITE_IF;
1972                 else
1973                         disp = NTCREATEX_DISP_OPEN_IF;
1974         }
1975         xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
1976         error = smbfs_smb_create(dnp,
1977             name, nmlen, xattr,
1978             disp, &scred, &fid);
1979         if (error)
1980                 goto out;
1981 
1982         /*
1983          * XXX: Missing some code here to deal with
1984          * the case where we opened an existing file,
1985          * it's size is larger than 32-bits, and we're
1986          * setting the size from a process that's not
1987          * aware of large file offsets.  i.e.
1988          * from the NFS3 code:
1989          */
1990 #if NOT_YET /* XXX */
1991         if ((vattr.va_mask & AT_SIZE) &&
1992             vp->v_type == VREG) {
1993                 np = VTOSMB(vp);
1994                 /*
1995                  * Check here for large file handled
1996                  * by LF-unaware process (as
1997                  * ufs_create() does)
1998                  */
1999                 if (!(lfaware & FOFFMAX)) {
2000                         mutex_enter(&np->r_statelock);
2001                         if (np->r_size > MAXOFF32_T)
2002                                 error = EOVERFLOW;
2003                         mutex_exit(&np->r_statelock);
2004                 }
2005                 if (!error) {
2006                         vattr.va_mask = AT_SIZE;
2007                         error = smbfssetattr(vp,
2008                             &vattr, 0, cr);
2009                 }
2010         }
2011 #endif /* XXX */
2012         /*
2013          * Should use the fid to get/set the size
2014          * while we have it opened here.  See above.
2015          */
2016 
2017         cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
2018         if (cerror)
2019                 SMBVDEBUG("error %d closing %s\\%s\n",
2020                     cerror, dnp->n_rpath, name);
2021 
2022         /*
2023          * In the open case, the name may differ a little
2024          * from what we passed to create (case, etc.)
2025          * so call lookup to get the (opened) name.
2026          *
2027          * XXX: Could avoid this extra lookup if the
2028          * "createact" result from NT_CREATE says we
2029          * created the object.
2030          */
2031         error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2032         if (error)
2033                 goto out;
2034 
2035         /* update attr and directory cache */
2036         smbfs_attr_touchdir(dnp);
2037 
2038         error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2039         if (error)
2040                 goto out;
2041 
2042         /* XXX invalidate pages if we truncated? */
2043 
2044         /* Success! */
2045         *vpp = vp;
2046         error = 0;
2047 
2048 out:
2049         smb_credrele(&scred);
2050         smbfs_rw_exit(&dnp->r_rwlock);
2051         if (name != nm)
2052                 smbfs_name_free(name, nmlen);
2053         return (error);
2054 }
2055 
2056 /*
2057  * XXX
2058  * This op should support the new FIGNORECASE flag for case-insensitive
2059  * lookups, per PSARC 2007/244.
2060  */
2061 /* ARGSUSED */
2062 static int
2063 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,


2129     int flags)
2130 {
2131         smbnode_t       *dnp = VTOSMB(dvp);
2132         smbnode_t       *np = VTOSMB(vp);
2133         char            *tmpname = NULL;
2134         int             tnlen;
2135         int             error;
2136         unsigned short  fid;
2137         boolean_t       have_fid = B_FALSE;
2138         boolean_t       renamed = B_FALSE;
2139 
2140         /*
2141          * The dvp RWlock must be held as writer.
2142          */
2143         ASSERT(dnp->r_rwlock.owner == curthread);
2144 
2145         /* Never allow link/unlink directories on SMB. */
2146         if (vp->v_type == VDIR)
2147                 return (EPERM);
2148 


















2149         /* Shared lock for n_fid use in smbfs_smb_setdisp etc. */
2150         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
2151                 return (EINTR);
2152 
2153         /* Force lookup to go OtW */
2154         smbfs_attrcache_remove(np);
2155 
2156         /*
2157          * Get a file handle with delete access.
2158          * Close this FID before return.
2159          */
2160         error = smbfs_smb_tmpopen(np, STD_RIGHT_DELETE_ACCESS,
2161             scred, &fid);
2162         if (error) {
2163                 SMBVDEBUG("error %d opening %s\n",
2164                     error, np->n_rpath);
2165                 goto out;
2166         }
2167         have_fid = B_TRUE;
2168 
2169         /*
2170          * If we have the file open, try to rename it to a temporary name.
2171          * If we can't rename, continue on and try setting DoC anyway.
2172          */
2173         if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
2174                 tmpname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
2175                 tnlen = smbfs_newname(tmpname, MAXNAMELEN);


2198                  * the separator ('/' or ':')
2199                  */
2200                 if (renamed) {
2201                         char *oldname;
2202                         int oldnlen;
2203                         int err2;
2204 
2205                         oldname = np->n_rpath + (dnp->n_rplen + 1);
2206                         oldnlen = np->n_rplen - (dnp->n_rplen + 1);
2207                         err2 = smbfs_smb_t2rename(np, oldname, oldnlen,
2208                             scred, fid, 0);
2209                         SMBVDEBUG("error %d un-renaming %s -> %s\n",
2210                           err2, tmpname, np->n_rpath);
2211                 }
2212                 error = EBUSY;
2213                 goto out;
2214         }
2215         /* Done! */
2216         smbfs_attrcache_prune(np);
2217 




2218 out:
2219         if (tmpname != NULL)
2220                 kmem_free(tmpname, MAXNAMELEN);
2221 
2222         if (have_fid)
2223                 (void) smbfs_smb_tmpclose(np, fid, scred);
2224         smbfs_rw_exit(&np->r_lkserlock);
2225 
2226         if (error == 0) {
2227                 /* Keep lookup from finding this node anymore. */
2228                 smbfs_rmhash(np);
2229         }
2230 
2231         return (error);
2232 }
2233 
2234 










2235 /*
2236  * XXX
2237  * This op should support the new FIGNORECASE flag for case-insensitive
2238  * lookups, per PSARC 2007/244.
2239  */
2240 /* ARGSUSED */
2241 static int
2242 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2243         caller_context_t *ct, int flags)
2244 {
2245         struct smb_cred scred;
2246         smbnode_t       *odnp = VTOSMB(odvp);
2247         smbnode_t       *ndnp = VTOSMB(ndvp);
2248         vnode_t         *ovp;
2249         int error;
2250 
2251         if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone ||
2252             curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone)
2253                 return (EPERM);
2254 


2407                  */
2408                 if (nvp->v_type == VDIR) {
2409                         error = EEXIST;
2410                         goto out;
2411                 }
2412                 error = smbfsremove(ndvp, nvp, scred, flags);
2413                 if (error != 0)
2414                         goto out;
2415 
2416                 /*
2417                  * OK, removed the target file.  Continue as if
2418                  * lookup target had failed (nvp == NULL).
2419                  */
2420                 vn_vfsunlock(nvp);
2421                 nvp_locked = 0;
2422                 VN_RELE(nvp);
2423                 nvp = NULL;
2424         } /* nvp */
2425 
2426         smbfs_attrcache_remove(onp);
2427 
2428         error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), scred);
2429 
2430         /*
2431          * If the old name should no longer exist,
2432          * discard any cached attributes under it.
2433          */
2434         if (error == 0)
2435                 smbfs_attrcache_prune(onp);


2436 
2437 out:
2438         if (nvp) {
2439                 if (nvp_locked)
2440                         vn_vfsunlock(nvp);
2441                 VN_RELE(nvp);
2442         }
2443 
2444         return (error);
2445 }
2446 
2447 /*
2448  * XXX
2449  * vsecattr_t is new to build 77, and we need to eventually support
2450  * it in order to create an ACL when an object is created.
2451  *
2452  * This op should support the new FIGNORECASE flag for case-insensitive
2453  * lookups, per PSARC 2007/244.
2454  */
2455 /* ARGSUSED */


2468 
2469         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2470                 return (EPERM);
2471 
2472         if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2473                 return (EIO);
2474 
2475         if ((nmlen == 1 && name[0] == '.') ||
2476             (nmlen == 2 && name[0] == '.' && name[1] == '.'))
2477                 return (EEXIST);
2478 
2479         /* Only plain files are allowed in V_XATTRDIR. */
2480         if (dvp->v_flag & V_XATTRDIR)
2481                 return (EINVAL);
2482 
2483         if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2484                 return (EINTR);
2485         smb_credinit(&scred, cr);
2486 
2487         /*
2488          * XXX: Do we need r_lkserlock too?
2489          * No use of any shared fid or fctx...
2490          */
2491 
2492         /*
2493          * Require write access in the containing directory.
2494          */
2495         error = smbfs_access(dvp, VWRITE, 0, cr, ct);
2496         if (error)
2497                 goto out;
2498 
2499         error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
2500         if (error)
2501                 goto out;
2502 
2503         error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2504         if (error)
2505                 goto out;
2506 
2507         smbfs_attr_touchdir(dnp);
2508 
2509         error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2510         if (error)
2511                 goto out;
2512 


2615         dnp->n_flag |= NMODIFIED;
2616         mutex_exit(&np->r_statelock);
2617         smbfs_attr_touchdir(dnp);
2618         smbfs_rmhash(np);
2619 
2620 out:
2621         if (vp) {
2622                 if (vp_locked)
2623                         vn_vfsunlock(vp);
2624                 VN_RELE(vp);
2625         }
2626         smb_credrele(&scred);
2627         smbfs_rw_exit(&dnp->r_rwlock);
2628 
2629         return (error);
2630 }
2631 
2632 
2633 /* ARGSUSED */
2634 static int










2635 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
2636         caller_context_t *ct, int flags)
2637 {
2638         struct smbnode  *np = VTOSMB(vp);
2639         int             error = 0;
2640         smbmntinfo_t    *smi;
2641 
2642         smi = VTOSMI(vp);
2643 
2644         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2645                 return (EIO);
2646 
2647         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2648                 return (EIO);
2649 
2650         /*
2651          * Require read access in the directory.
2652          */
2653         error = smbfs_access(vp, VREAD, 0, cr, ct);
2654         if (error)
2655                 return (error);
2656 
2657         ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
2658 
2659         /*
2660          * XXX: Todo readdir cache here
2661          * Note: NFS code is just below this.
2662          *
2663          * I am serializing the entire readdir opreation
2664          * now since we have not yet implemented readdir
2665          * cache. This fix needs to be revisited once
2666          * we implement readdir cache.
2667          */
2668         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
2669                 return (EINTR);
2670 
2671         error = smbfs_readvdir(vp, uiop, cr, eofp, ct);
2672 
2673         smbfs_rw_exit(&np->r_lkserlock);
2674 
2675         return (error);
2676 }
2677 
2678 /* ARGSUSED */
2679 static int
2680 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
2681         caller_context_t *ct)


2875         }
2876         /*
2877          * If we encountered an error (i.e. "access denied")
2878          * from the FindFirst call, we will have copied out
2879          * the "." and ".." entries leaving offset == 2.
2880          * In that case, restore the original offset/resid
2881          * so the caller gets no data with the error.
2882          */
2883         if (error != 0 && offset == FIRST_DIROFS) {
2884                 uio->uio_loffset = save_offset;
2885                 uio->uio_resid = save_resid;
2886         }
2887         SMBVDEBUG("out: offset=%d, resid=%d\n",
2888             (int)uio->uio_offset, (int)uio->uio_resid);
2889 
2890         kmem_free(dp, dbufsiz);
2891         smb_credrele(&scred);
2892         return (error);
2893 }
2894 




2895 








2896 /*
2897  * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK
2898  * are optional functions that are called by:
2899  *    getdents, before/after VOP_READDIR
2900  *    pread, before/after ... VOP_READ
2901  *    pwrite, before/after ... VOP_WRITE
2902  *    (other places)
2903  *
2904  * Careful here: None of the above check for any
2905  * error returns from VOP_RWLOCK / VOP_RWUNLOCK!
2906  * In fact, the return value from _rwlock is NOT
2907  * an error code, but V_WRITELOCK_TRUE / _FALSE.
2908  *
2909  * Therefore, it's up to _this_ code to make sure
2910  * the lock state remains balanced, which means
2911  * we can't "bail out" on interrupts, etc.
2912  */
2913 
2914 /* ARGSUSED2 */
2915 static int


2949                 return (EPERM);
2950 
2951         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2952                 return (EIO);
2953 
2954         /*
2955          * Because we stuff the readdir cookie into the offset field
2956          * someone may attempt to do an lseek with the cookie which
2957          * we want to succeed.
2958          */
2959         if (vp->v_type == VDIR)
2960                 return (0);
2961 
2962         /* Like NFS3, just check for 63-bit overflow. */
2963         if (*noffp < 0)
2964                 return (EINVAL);
2965 
2966         return (0);
2967 }
2968 

2969 




2970 /*




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































2971  * XXX
2972  * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service.
2973  */
2974 static int
2975 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2976         offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
2977         caller_context_t *ct)
2978 {
2979         if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
2980                 return (EIO);
2981 
2982         if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
2983                 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
2984         else
2985                 return (ENOSYS);
2986 }
2987 
2988 /*
2989  * Free storage space associated with the specified vnode.  The portion
2990  * to be freed is specified by bfp->l_start and bfp->l_len (already


3020          */
3021 
3022         error = convoff(vp, bfp, 0, offset);
3023         if (!error) {
3024                 ASSERT(bfp->l_start >= 0);
3025                 if (bfp->l_len == 0) {
3026                         struct vattr va;
3027 
3028                         /*
3029                          * ftruncate should not change the ctime and
3030                          * mtime if we truncate the file to its
3031                          * previous size.
3032                          */
3033                         va.va_mask = AT_SIZE;
3034                         error = smbfsgetattr(vp, &va, cr);
3035                         if (error || va.va_size == bfp->l_start)
3036                                 return (error);
3037                         va.va_mask = AT_SIZE;
3038                         va.va_size = bfp->l_start;
3039                         error = smbfssetattr(vp, &va, 0, cr);

3040                 } else
3041                         error = EINVAL;
3042         }
3043 
3044         return (error);
3045 }
3046 

3047 /* ARGSUSED */
3048 static int









3049 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
3050         caller_context_t *ct)
3051 {
3052         vfs_t *vfs;
3053         smbmntinfo_t *smi;
3054         struct smb_share *ssp;
3055 
3056         vfs = vp->v_vfsp;
3057         smi = VFTOSMI(vfs);
3058 
3059         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3060                 return (EIO);
3061 
3062         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3063                 return (EIO);
3064 
3065         switch (cmd) {
3066         case _PC_FILESIZEBITS:
3067                 ssp = smi->smi_share;
3068                 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)


3203         return (error);
3204 }
3205 
3206 
3207 /*
3208  * XXX
3209  * This op should eventually support PSARC 2007/268.
3210  */
3211 static int
3212 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
3213         caller_context_t *ct)
3214 {
3215         if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3216                 return (EIO);
3217 
3218         if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3219                 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3220         else
3221                 return (ENOSYS);
3222 }





















































  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 /*
  40  * Vnode operations
  41  *
  42  * This file is similar to nfs3_vnops.c
  43  */
  44 
  45 #include <sys/param.h>
  46 #include <sys/systm.h>
  47 #include <sys/cred.h>
  48 #include <sys/vnode.h>
  49 #include <sys/vfs.h>
  50 #include <sys/filio.h>
  51 #include <sys/uio.h>
  52 #include <sys/dirent.h>
  53 #include <sys/errno.h>
  54 #include <sys/sunddi.h>
  55 #include <sys/sysmacros.h>
  56 #include <sys/kmem.h>
  57 #include <sys/cmn_err.h>
  58 #include <sys/vfs_opreg.h>
  59 #include <sys/policy.h>
  60 #include <sys/sdt.h>
  61 #include <sys/zone.h>
  62 #include <sys/vmsystm.h>
  63 
  64 #include <vm/hat.h>
  65 #include <vm/as.h>
  66 #include <vm/page.h>
  67 #include <vm/pvn.h>
  68 #include <vm/seg.h>
  69 #include <vm/seg_map.h>
  70 #include <vm/seg_kpm.h>
  71 #include <vm/seg_vn.h>
  72 
  73 #include <netsmb/smb_osdep.h>
  74 #include <netsmb/smb.h>
  75 #include <netsmb/smb_conn.h>
  76 #include <netsmb/smb_subr.h>
  77 
  78 #include <smbfs/smbfs.h>
  79 #include <smbfs/smbfs_node.h>
  80 #include <smbfs/smbfs_subr.h>
  81 
  82 #include <sys/fs/smbfs_ioctl.h>
  83 #include <fs/fs_subr.h>
  84 
  85 /*
  86  * We assign directory offsets like the NFS client, where the
  87  * offset increments by _one_ after each directory entry.
  88  * Further, the entries "." and ".." are always at offsets
  89  * zero and one (respectively) and the "real" entries from
  90  * the server appear at offsets starting with two.  This
  91  * macro is used to initialize the n_dirofs field after
  92  * setting n_dirseq with a _findopen call.


 103 static const char illegal_chars[] = {
 104         ':',    /* colon - keep this first! */
 105         '\\',   /* back slash */
 106         '/',    /* slash */
 107         '*',    /* asterisk */
 108         '?',    /* question mark */
 109         '"',    /* double quote */
 110         '<', /* less than sign */
 111         '>', /* greater than sign */
 112         '|',    /* vertical bar */
 113         0
 114 };
 115 
 116 /*
 117  * Turning this on causes nodes to be created in the cache
 118  * during directory listings, normally avoiding a second
 119  * OtW attribute fetch just after a readdir.
 120  */
 121 int smbfs_fastlookup = 1;
 122 
 123 struct vnodeops *smbfs_vnodeops = NULL;
 124 
 125 /* local static function defines */
 126 
 127 static int      smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
 128                         cred_t *);
 129 static int      smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
 130                         int cache_ok, caller_context_t *);
 131 static int      smbfsremove(vnode_t *dvp, vnode_t *vp, struct smb_cred *scred,
 132                         int flags);
 133 static int      smbfsrename(vnode_t *odvp, vnode_t *ovp, vnode_t *ndvp,
 134                         char *nnm, struct smb_cred *scred, int flags);
 135 static int      smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
 136 static int      smbfs_accessx(void *, int, cred_t *);
 137 static int      smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
 138                         caller_context_t *);
 139 static void     smbfs_rele_fid(smbnode_t *, struct smb_cred *);
 140 static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *);
 141 
 142 static int      smbfs_rdwrlbn(vnode_t *, page_t *, u_offset_t, size_t, int,
 143                         cred_t *);
 144 static int      smbfs_bio(struct buf *, int, cred_t *);
 145 static int      smbfs_writenp(smbnode_t *np, caddr_t base, int tcount,
 146                         struct uio *uiop, int pgcreated);
 147 
 148 static int      smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
 149 static int      smbfs_putpage(vnode_t *, offset_t, size_t, int, cred_t *,
 150                         caller_context_t *);
 151 static int      smbfs_getapage(vnode_t *, u_offset_t, size_t, uint_t *,
 152                         page_t *[], size_t, struct seg *, caddr_t,
 153                         enum seg_rw, cred_t *);
 154 static int      smbfs_putapage(vnode_t *, page_t *, u_offset_t *, size_t *,
 155                         int, cred_t *);
 156 static void     smbfs_delmap_callback(struct as *, void *, uint_t);
 157 
 158 /*
 159  * Error flags used to pass information about certain special errors
 160  * which need to be handled specially.
 161  */
 162 #define SMBFS_EOF                       -98
 163 
 164 /* When implementing OtW locks, make this a real function. */
 165 #define smbfs_lm_has_sleep(vp) 0
 166 
 167 /*
 168  * These are the vnode ops routines which implement the vnode interface to
 169  * the networked file system.  These routines just take their parameters,
 170  * make them look networkish by putting the right info into interface structs,
 171  * and then calling the appropriate remote routine(s) to do the work.
 172  *
 173  * Note on directory name lookup cacheing:  If we detect a stale fhandle,
 174  * we purge the directory cache relative to that vnode.  This way, the
 175  * user won't get burned by the cache repeatedly.  See <smbfs/smbnode.h> for
 176  * more details on smbnode locking.
 177  */
 178 















































 179 







 180 /*















































 181  * XXX
 182  * When new and relevant functionality is enabled, we should be
 183  * calling vfs_set_feature() to inform callers that pieces of
 184  * functionality are available, per PSARC 2007/227.
 185  */
 186 /* ARGSUSED */
 187 static int
 188 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
 189 {
 190         smbnode_t       *np;
 191         vnode_t         *vp;
 192         smbfattr_t      fa;
 193         u_int32_t       rights, rightsrcvd;
 194         u_int16_t       fid, oldfid;
 195         int             oldgenid;
 196         struct smb_cred scred;
 197         smbmntinfo_t    *smi;
 198         smb_share_t     *ssp;
 199         cred_t          *oldcr;
 200         int             tmperror;


 212                 return (EIO);
 213 
 214         if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */
 215                 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type);
 216                 return (EACCES);
 217         }
 218 
 219         /*
 220          * Get exclusive access to n_fid and related stuff.
 221          * No returns after this until out.
 222          */
 223         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
 224                 return (EINTR);
 225         smb_credinit(&scred, cr);
 226 
 227         /*
 228          * Keep track of the vnode type at first open.
 229          * It may change later, and we need close to do
 230          * cleanup for the type we opened.  Also deny
 231          * open of new types until old type is closed.

 232          */
 233         if (np->n_ovtype == VNON) {
 234                 ASSERT(np->n_dirrefs == 0);
 235                 ASSERT(np->n_fidrefs == 0);
 236         } else if (np->n_ovtype != vp->v_type) {
 237                 SMBVDEBUG("open n_ovtype=%d v_type=%d\n",
 238                     np->n_ovtype, vp->v_type);
 239                 error = EACCES;
 240                 goto out;
 241         }
 242 
 243         /*
 244          * Directory open.  See smbfs_readvdir()
 245          */
 246         if (vp->v_type == VDIR) {
 247                 if (np->n_dirseq == NULL) {
 248                         /* first open */
 249                         error = smbfs_smb_findopen(np, "*", 1,
 250                             SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
 251                             &scred, &np->n_dirseq);


 350          * Keep track of the vnode type at first open.
 351          * (see comments above)
 352          */
 353         if (np->n_ovtype == VNON)
 354                 np->n_ovtype = vp->v_type;
 355 
 356 out:
 357         smb_credrele(&scred);
 358         smbfs_rw_exit(&np->r_lkserlock);
 359         return (error);
 360 }
 361 
 362 /*ARGSUSED*/
 363 static int
 364 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
 365         caller_context_t *ct)
 366 {
 367         smbnode_t       *np;
 368         smbmntinfo_t    *smi;
 369         struct smb_cred scred;
 370         int error = 0;
 371 
 372         np = VTOSMB(vp);
 373         smi = VTOSMI(vp);
 374 
 375         /*
 376          * Don't "bail out" for VFS_UNMOUNTED here,
 377          * as we want to do cleanup, etc.
 378          */
 379 
 380         /*
 381          * zone_enter(2) prevents processes from changing zones with SMBFS files
 382          * open; if we happen to get here from the wrong zone we can't do
 383          * anything over the wire.
 384          */
 385         if (smi->smi_zone_ref.zref_zone != curproc->p_zone) {
 386                 /*
 387                  * We could attempt to clean up locks, except we're sure
 388                  * that the current process didn't acquire any locks on
 389                  * the file: any attempt to lock a file belong to another zone
 390                  * will fail, and one can't lock an SMBFS file and then change


 398                  * everything (minus the final smbfs_getattr_otw() call) should
 399                  * be OK. If the zone is going away smbfs_async_inactive() will
 400                  * throw away cached pages inline.
 401                  */
 402                 return (EIO);
 403         }
 404 
 405         /*
 406          * If we are using local locking for this filesystem, then
 407          * release all of the SYSV style record locks.  Otherwise,
 408          * we are doing network locking and we need to release all
 409          * of the network locks.  All of the locks held by this
 410          * process on this file are released no matter what the
 411          * incoming reference count is.
 412          */
 413         if (smi->smi_flags & SMI_LLOCK) {
 414                 pid_t pid = ddi_get_pid();
 415                 cleanlocks(vp, pid, 0);
 416                 cleanshares(vp, pid);
 417         }
 418         /*
 419          * else doing OtW locking.  SMB servers drop all locks
 420          * on the file ID we close here, so no _lockrelease()
 421          */
 422 
 423         /*
 424          * This (passed in) count is the ref. count from the
 425          * user's file_t before the closef call (fio.c).
 426          * The rest happens only on last close.
 427          */
 428         if (count > 1)
 429                 return (0);
 430 
 431         /* NFS has DNLC purge here. */
 432 
 433         /*
 434          * If the file was open for write and there are pages,
 435          * then make sure dirty pages written back.
 436          *
 437          * NFS does this async when "close-to-open" is off
 438          * (MI_NOCTO flag is set) to avoid blocking the caller.
 439          * For now, always do this synchronously (no B_ASYNC).
 440          */
 441         if ((flag & FWRITE) && vn_has_cached_data(vp)) {
 442                 error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, ct);
 443                 if (error == EAGAIN)
 444                         error = 0;
 445         }
 446         if (error == 0) {
 447                 mutex_enter(&np->r_statelock);
 448                 np->r_flags &= ~RSTALE;
 449                 np->r_error = 0;
 450                 mutex_exit(&np->r_statelock);
 451         }
 452 
 453         /*
 454          * Decrement the reference count for the FID
 455          * and possibly do the OtW close.
 456          *
 457          * Exclusive lock for modifying n_fid stuff.
 458          * Don't want this one ever interruptible.
 459          */
 460         (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
 461         smb_credinit(&scred, cr);
 462 
 463         smbfs_rele_fid(np, &scred);
 464 
 465         smb_credrele(&scred);
 466         smbfs_rw_exit(&np->r_lkserlock);
 467 
 468         return (0);
 469 }
 470 
 471 /*
 472  * Helper for smbfs_close.  Decrement the reference count
 473  * for an SMB-level file or directory ID, and when the last


 544         np->r_cred = NULL;
 545         mutex_exit(&np->r_statelock);
 546         if (oldcr != NULL)
 547                 crfree(oldcr);
 548 }
 549 
 550 /* ARGSUSED */
 551 static int
 552 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
 553         caller_context_t *ct)
 554 {
 555         struct smb_cred scred;
 556         struct vattr    va;
 557         smbnode_t       *np;
 558         smbmntinfo_t    *smi;
 559         smb_share_t     *ssp;
 560         offset_t        endoff;
 561         ssize_t         past_eof;
 562         int             error;
 563 
 564         caddr_t         base;
 565         u_offset_t      off;
 566         size_t          n;
 567         int             on;
 568         uint_t          flags;
 569 
 570         np = VTOSMB(vp);
 571         smi = VTOSMI(vp);
 572         ssp = smi->smi_share;
 573 
 574         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 575                 return (EIO);
 576 
 577         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
 578                 return (EIO);
 579 
 580         ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
 581 
 582         if (vp->v_type != VREG)
 583                 return (EISDIR);
 584 
 585         if (uiop->uio_resid == 0)
 586                 return (0);
 587 
 588         /*
 589          * Like NFS3, just check for 63-bit overflow.


 599         if (error = smbfsgetattr(vp, &va, cr))
 600                 return (error);
 601 
 602         /* Update mtime with mtime from server here? */
 603 
 604         /* if offset is beyond EOF, read nothing */
 605         if (uiop->uio_loffset >= va.va_size)
 606                 return (0);
 607 
 608         /*
 609          * Limit the read to the remaining file size.
 610          * Do this by temporarily reducing uio_resid
 611          * by the amount the lies beyoned the EOF.
 612          */
 613         if (endoff > va.va_size) {
 614                 past_eof = (ssize_t)(endoff - va.va_size);
 615                 uiop->uio_resid -= past_eof;
 616         } else
 617                 past_eof = 0;
 618 
 619         /*
 620          * Bypass VM if caching has been disabled (e.g., locking) or if
 621          * using client-side direct I/O and the file is not mmap'd and
 622          * there are no cached pages.
 623          */
 624         if ((vp->v_flag & VNOCACHE) ||
 625             (((np->r_flags & RDIRECTIO) || (smi->smi_flags & SMI_DIRECTIO)) &&
 626             np->r_mapcnt == 0 && np->r_inmap == 0 &&
 627             !vn_has_cached_data(vp))) {
 628 
 629                 /* Shared lock for n_fid use in smb_rwuio */
 630                 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
 631                         return (EINTR);
 632                 smb_credinit(&scred, cr);
 633 
 634                 /* After reconnect, n_fid is invalid */
 635                 if (np->n_vcgenid != ssp->ss_vcgenid)
 636                         error = ESTALE;
 637                 else
 638                         error = smb_rwuio(ssp, np->n_fid, UIO_READ,
 639                             uiop, &scred, smb_timo_read);
 640 
 641                 smb_credrele(&scred);
 642                 smbfs_rw_exit(&np->r_lkserlock);
 643 
 644                 /* undo adjustment of resid */
 645                 uiop->uio_resid += past_eof;
 646 
 647                 return (error);
 648         }
 649 
 650         /* (else) Do I/O through segmap. */
 651         do {
 652                 off = uiop->uio_loffset & MAXBMASK; /* mapping offset */
 653                 on = uiop->uio_loffset & MAXBOFFSET; /* Relative offset */
 654                 n = MIN(MAXBSIZE - on, uiop->uio_resid);
 655 
 656                 error = smbfs_validate_caches(vp, cr);
 657                 if (error)
 658                         break;
 659 
 660                 /* NFS waits for RINCACHEPURGE here. */
 661 
 662                 if (vpm_enable) {
 663                         /*
 664                          * Copy data.
 665                          */
 666                         error = vpm_data_copy(vp, off + on, n, uiop,
 667                             1, NULL, 0, S_READ);
 668                 } else {
 669                         base = segmap_getmapflt(segkmap, vp, off + on, n, 1,
 670                             S_READ);
 671 
 672                         error = uiomove(base + on, n, UIO_READ, uiop);
 673                 }
 674 
 675                 if (!error) {
 676                         /*
 677                          * If read a whole block or read to eof,
 678                          * won't need this buffer again soon.
 679                          */
 680                         mutex_enter(&np->r_statelock);
 681                         if (n + on == MAXBSIZE ||
 682                             uiop->uio_loffset == np->r_size)
 683                                 flags = SM_DONTNEED;
 684                         else
 685                                 flags = 0;
 686                         mutex_exit(&np->r_statelock);
 687                         if (vpm_enable) {
 688                                 error = vpm_sync_pages(vp, off, n, flags);
 689                         } else {
 690                                 error = segmap_release(segkmap, base, flags);
 691                         }
 692                 } else {
 693                         if (vpm_enable) {
 694                                 (void) vpm_sync_pages(vp, off, n, 0);
 695                         } else {
 696                                 (void) segmap_release(segkmap, base, 0);
 697                         }
 698                 }
 699         } while (!error && uiop->uio_resid > 0);
 700 
 701         /* undo adjustment of resid */
 702         uiop->uio_resid += past_eof;
 703 
 704         return (error);
 705 }
 706 
 707 
 708 /* ARGSUSED */
 709 static int
 710 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
 711         caller_context_t *ct)
 712 {
 713         struct smb_cred scred;
 714         struct vattr    va;
 715         smbnode_t       *np;
 716         smbmntinfo_t    *smi;
 717         smb_share_t     *ssp;
 718         offset_t        endoff, limit;
 719         ssize_t         past_limit;
 720         int             error, timo;
 721         caddr_t         base;
 722         u_offset_t      off;
 723         size_t          n;
 724         int             on;
 725         uint_t          flags;
 726         u_offset_t      last_off;
 727         size_t          last_resid;
 728         uint_t          bsize;
 729 
 730         np = VTOSMB(vp);
 731         smi = VTOSMI(vp);
 732         ssp = smi->smi_share;
 733 
 734         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 735                 return (EIO);
 736 
 737         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
 738                 return (EIO);
 739 
 740         ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
 741 
 742         if (vp->v_type != VREG)
 743                 return (EISDIR);
 744 
 745         if (uiop->uio_resid == 0)
 746                 return (0);
 747 
 748         /*
 749          * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
 750          */
 751         if (ioflag & (FAPPEND | FSYNC)) {
 752                 if (np->n_flag & NMODIFIED) {
 753                         smbfs_attrcache_remove(np);

 754                 }
 755         }
 756         if (ioflag & FAPPEND) {
 757                 /*
 758                  * File size can be changed by another client
 759                  *
 760                  * Todo: Consider redesigning this to use a
 761                  * handle opened for append instead.
 762                  */
 763                 va.va_mask = AT_SIZE;
 764                 if (error = smbfsgetattr(vp, &va, cr))
 765                         return (error);
 766                 uiop->uio_loffset = va.va_size;
 767         }
 768 
 769         /*
 770          * Like NFS3, just check for 63-bit overflow.
 771          */
 772         endoff = uiop->uio_loffset + uiop->uio_resid;
 773         if (uiop->uio_loffset < 0 || endoff < 0)
 774                 return (EINVAL);
 775 
 776         /*
 777          * Check to make sure that the process will not exceed
 778          * its limit on file size.  It is okay to write up to
 779          * the limit, but not beyond.  Thus, the write which
 780          * reaches the limit will be short and the next write
 781          * will return an error.
 782          *
 783          * So if we're starting at or beyond the limit, EFBIG.
 784          * Otherwise, temporarily reduce resid to the amount
 785          * that is after the limit.
 786          */
 787         limit = uiop->uio_llimit;
 788         if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
 789                 limit = MAXOFFSET_T;
 790         if (uiop->uio_loffset >= limit) {
 791                 proc_t *p = ttoproc(curthread);
 792 
 793                 mutex_enter(&p->p_lock);
 794                 (void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE],
 795                     p->p_rctls, p, RCA_UNSAFE_SIGINFO);
 796                 mutex_exit(&p->p_lock);
 797                 return (EFBIG);
 798         }
 799         if (endoff > limit) {
 800                 past_limit = (ssize_t)(endoff - limit);
 801                 uiop->uio_resid -= past_limit;
 802         } else
 803                 past_limit = 0;
 804 
 805         /*
 806          * Bypass VM if caching has been disabled (e.g., locking) or if
 807          * using client-side direct I/O and the file is not mmap'd and
 808          * there are no cached pages.
 809          */
 810         if ((vp->v_flag & VNOCACHE) ||
 811             (((np->r_flags & RDIRECTIO) || (smi->smi_flags & SMI_DIRECTIO)) &&
 812             np->r_mapcnt == 0 && np->r_inmap == 0 &&
 813             !vn_has_cached_data(vp))) {
 814 
 815 smbfs_fwrite:
 816                 if (np->r_flags & RSTALE) {
 817                         last_resid = uiop->uio_resid;
 818                         last_off = uiop->uio_loffset;
 819                         error = np->r_error;
 820                         /*
 821                          * A close may have cleared r_error, if so,
 822                          * propagate ESTALE error return properly
 823                          */
 824                         if (error == 0)
 825                                 error = ESTALE;
 826                         goto bottom;
 827                 }
 828 
 829                 /* Timeout: longer for append. */
 830                 timo = smb_timo_write;
 831                 if (endoff > np->r_size)
 832                         timo = smb_timo_append;
 833 
 834                 /* Shared lock for n_fid use in smb_rwuio */
 835                 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
 836                         return (EINTR);
 837                 smb_credinit(&scred, cr);
 838 
 839                 /* After reconnect, n_fid is invalid */
 840                 if (np->n_vcgenid != ssp->ss_vcgenid)
 841                         error = ESTALE;
 842                 else
 843                         error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
 844                             uiop, &scred, timo);
 845 
 846                 if (error == 0) {
 847                         mutex_enter(&np->r_statelock);
 848                         np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
 849                         if (uiop->uio_loffset > (offset_t)np->r_size)
 850                                 np->r_size = (len_t)uiop->uio_loffset;
 851                         mutex_exit(&np->r_statelock);
 852                         if (ioflag & (FSYNC | FDSYNC)) {
 853                                 /* Don't error the I/O if this fails. */
 854                                 (void) smbfs_smb_flush(np, &scred);
 855                         }
 856                 }
 857 
 858                 smb_credrele(&scred);
 859                 smbfs_rw_exit(&np->r_lkserlock);
 860 
 861                 /* undo adjustment of resid */
 862                 uiop->uio_resid += past_limit;
 863 
 864                 return (error);
 865         }
 866 
 867         /* (else) Do I/O through segmap. */
 868         bsize = vp->v_vfsp->vfs_bsize;
 869 
 870         do {
 871                 off = uiop->uio_loffset & MAXBMASK; /* mapping offset */
 872                 on = uiop->uio_loffset & MAXBOFFSET; /* Relative offset */
 873                 n = MIN(MAXBSIZE - on, uiop->uio_resid);
 874 
 875                 last_resid = uiop->uio_resid;
 876                 last_off = uiop->uio_loffset;
 877 
 878                 if (np->r_flags & RSTALE) {
 879                         error = np->r_error;
 880                         /*
 881                          * A close may have cleared r_error, if so,
 882                          * propagate ESTALE error return properly
 883                          */
 884                         if (error == 0)
 885                                 error = ESTALE;
 886                         break;
 887                 }
 888 
 889                 /*
 890                  * From NFS: Don't create dirty pages faster than they
 891                  * can be cleaned.
 892                  *
 893                  * Here NFS also checks for async writes (np->r_awcount)
 894                  */
 895                 mutex_enter(&np->r_statelock);
 896                 while (np->r_gcount > 0) {
 897                         if (SMBINTR(vp)) {
 898                                 klwp_t *lwp = ttolwp(curthread);
 899 
 900                                 if (lwp != NULL)
 901                                         lwp->lwp_nostop++;
 902                                 if (!cv_wait_sig(&np->r_cv, &np->r_statelock)) {
 903                                         mutex_exit(&np->r_statelock);
 904                                         if (lwp != NULL)
 905                                                 lwp->lwp_nostop--;
 906                                         error = EINTR;
 907                                         goto bottom;
 908                                 }
 909                                 if (lwp != NULL)
 910                                         lwp->lwp_nostop--;
 911                         } else
 912                                 cv_wait(&np->r_cv, &np->r_statelock);
 913                 }
 914                 mutex_exit(&np->r_statelock);
 915 
 916                 /*
 917                  * Touch the page and fault it in if it is not in core
 918                  * before segmap_getmapflt or vpm_data_copy can lock it.
 919                  * This is to avoid the deadlock if the buffer is mapped
 920                  * to the same file through mmap which we want to write.
 921                  */
 922                 uio_prefaultpages((long)n, uiop);
 923 
 924                 if (vpm_enable) {
 925                         /*
 926                          * It will use kpm mappings, so no need to
 927                          * pass an address.
 928                          */
 929                         error = smbfs_writenp(np, NULL, n, uiop, 0);
 930                 } else {
 931                         if (segmap_kpm) {
 932                                 int pon = uiop->uio_loffset & PAGEOFFSET;
 933                                 size_t pn = MIN(PAGESIZE - pon,
 934                                     uiop->uio_resid);
 935                                 int pagecreate;
 936 
 937                                 mutex_enter(&np->r_statelock);
 938                                 pagecreate = (pon == 0) && (pn == PAGESIZE ||
 939                                     uiop->uio_loffset + pn >= np->r_size);
 940                                 mutex_exit(&np->r_statelock);
 941 
 942                                 base = segmap_getmapflt(segkmap, vp, off + on,
 943                                     pn, !pagecreate, S_WRITE);
 944 
 945                                 error = smbfs_writenp(np, base + pon, n, uiop,
 946                                     pagecreate);
 947 
 948                         } else {
 949                                 base = segmap_getmapflt(segkmap, vp, off + on,
 950                                     n, 0, S_READ);
 951                                 error = smbfs_writenp(np, base + on, n, uiop, 0);
 952                         }
 953                 }
 954 
 955                 if (!error) {
 956                         if (smi->smi_flags & SMI_NOAC)
 957                                 flags = SM_WRITE;
 958                         else if ((uiop->uio_loffset % bsize) == 0 ||
 959                             IS_SWAPVP(vp)) {
 960                                 /*
 961                                  * Have written a whole block.
 962                                  * Start an asynchronous write
 963                                  * and mark the buffer to
 964                                  * indicate that it won't be
 965                                  * needed again soon.
 966                                  */
 967                                 flags = SM_WRITE | SM_ASYNC | SM_DONTNEED;
 968                         } else
 969                                 flags = 0;
 970                         if ((ioflag & (FSYNC|FDSYNC)) ||
 971                             (np->r_flags & ROUTOFSPACE)) {
 972                                 flags &= ~SM_ASYNC;
 973                                 flags |= SM_WRITE;
 974                         }
 975                         if (vpm_enable) {
 976                                 error = vpm_sync_pages(vp, off, n, flags);
 977                         } else {
 978                                 error = segmap_release(segkmap, base, flags);
 979                         }
 980                 } else {
 981                         if (vpm_enable) {
 982                                 (void) vpm_sync_pages(vp, off, n, 0);
 983                         } else {
 984                                 (void) segmap_release(segkmap, base, 0);
 985                         }
 986                         /*
 987                          * In the event that we got an access error while
 988                          * faulting in a page for a write-only file just
 989                          * force a write.
 990                          */
 991                         if (error == EACCES)
 992                                 goto smbfs_fwrite;
 993                 }
 994         } while (!error && uiop->uio_resid > 0);
 995 
 996 bottom:
 997         /* undo adjustment of resid */
 998         if (error) {
 999                 uiop->uio_resid = last_resid + past_limit;
1000                 uiop->uio_loffset = last_off;
1001         } else {
1002                 uiop->uio_resid += past_limit;
1003         }
1004 
1005         return (error);
1006 }
1007 
1008 /*
1009  * Like nfs_client.c: writerp()
1010  *
1011  * Write by creating pages and uiomove data onto them.
1012  */
1013 
1014 int
1015 smbfs_writenp(smbnode_t *np, caddr_t base, int tcount, struct uio *uio,
1016     int pgcreated)
1017 {
1018         int             pagecreate;
1019         int             n;
1020         int             saved_n;
1021         caddr_t         saved_base;
1022         u_offset_t      offset;
1023         int             error;
1024         int             sm_error;
1025         vnode_t         *vp = SMBTOV(np);
1026 
1027         ASSERT(tcount <= MAXBSIZE && tcount <= uio->uio_resid);
1028         ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
1029         if (!vpm_enable) {
1030                 ASSERT(((uintptr_t)base & MAXBOFFSET) + tcount <= MAXBSIZE);
1031         }
1032 
1033         /*
1034          * Move bytes in at most PAGESIZE chunks. We must avoid
1035          * spanning pages in uiomove() because page faults may cause
1036          * the cache to be invalidated out from under us. The r_size is not
1037          * updated until after the uiomove. If we push the last page of a
1038          * file before r_size is correct, we will lose the data written past
1039          * the current (and invalid) r_size.
1040          */
1041         do {
1042                 offset = uio->uio_loffset;
1043                 pagecreate = 0;
1044 
1045                 /*
1046                  * n is the number of bytes required to satisfy the request
1047                  *   or the number of bytes to fill out the page.
1048                  */
1049                 n = (int)MIN((PAGESIZE - (offset & PAGEOFFSET)), tcount);
1050 
1051                 /*
1052                  * Check to see if we can skip reading in the page
1053                  * and just allocate the memory.  We can do this
1054                  * if we are going to rewrite the entire mapping
1055                  * or if we are going to write to or beyond the current
1056                  * end of file from the beginning of the mapping.
1057                  *
1058                  * The read of r_size is now protected by r_statelock.
1059                  */
1060                 mutex_enter(&np->r_statelock);
1061                 /*
1062                  * When pgcreated is nonzero the caller has already done
1063                  * a segmap_getmapflt with forcefault 0 and S_WRITE. With
1064                  * segkpm this means we already have at least one page
1065                  * created and mapped at base.
1066                  */
1067                 pagecreate = pgcreated ||
1068                     ((offset & PAGEOFFSET) == 0 &&
1069                     (n == PAGESIZE || ((offset + n) >= np->r_size)));
1070 
1071                 mutex_exit(&np->r_statelock);
1072                 if (!vpm_enable && pagecreate) {
1073                         /*
1074                          * The last argument tells segmap_pagecreate() to
1075                          * always lock the page, as opposed to sometimes
1076                          * returning with the page locked. This way we avoid a
1077                          * fault on the ensuing uiomove(), but also
1078                          * more importantly (to fix bug 1094402) we can
1079                          * call segmap_fault() to unlock the page in all
1080                          * cases. An alternative would be to modify
1081                          * segmap_pagecreate() to tell us when it is
1082                          * locking a page, but that's a fairly major
1083                          * interface change.
1084                          */
1085                         if (pgcreated == 0)
1086                                 (void) segmap_pagecreate(segkmap, base,
1087                                     (uint_t)n, 1);
1088                         saved_base = base;
1089                         saved_n = n;
1090                 }
1091 
1092                 /*
1093                  * The number of bytes of data in the last page can not
1094                  * be accurately be determined while page is being
1095                  * uiomove'd to and the size of the file being updated.
1096                  * Thus, inform threads which need to know accurately
1097                  * how much data is in the last page of the file.  They
1098                  * will not do the i/o immediately, but will arrange for
1099                  * the i/o to happen later when this modify operation
1100                  * will have finished.
1101                  */
1102                 ASSERT(!(np->r_flags & RMODINPROGRESS));
1103                 mutex_enter(&np->r_statelock);
1104                 np->r_flags |= RMODINPROGRESS;
1105                 np->r_modaddr = (offset & MAXBMASK);
1106                 mutex_exit(&np->r_statelock);
1107 
1108                 if (vpm_enable) {
1109                         /*
1110                          * Copy data. If new pages are created, part of
1111                          * the page that is not written will be initizliazed
1112                          * with zeros.
1113                          */
1114                         error = vpm_data_copy(vp, offset, n, uio,
1115                             !pagecreate, NULL, 0, S_WRITE);
1116                 } else {
1117                         error = uiomove(base, n, UIO_WRITE, uio);
1118                 }
1119 
1120                 /*
1121                  * r_size is the maximum number of
1122                  * bytes known to be in the file.
1123                  * Make sure it is at least as high as the
1124                  * first unwritten byte pointed to by uio_loffset.
1125                  */
1126                 mutex_enter(&np->r_statelock);
1127                 if (np->r_size < uio->uio_loffset)
1128                         np->r_size = uio->uio_loffset;
1129                 np->r_flags &= ~RMODINPROGRESS;
1130                 np->r_flags |= RDIRTY;
1131                 mutex_exit(&np->r_statelock);
1132 
1133                 /* n = # of bytes written */
1134                 n = (int)(uio->uio_loffset - offset);
1135 
1136                 if (!vpm_enable) {
1137                         base += n;
1138                 }
1139                 tcount -= n;
1140                 /*
1141                  * If we created pages w/o initializing them completely,
1142                  * we need to zero the part that wasn't set up.
1143                  * This happens on a most EOF write cases and if
1144                  * we had some sort of error during the uiomove.
1145                  */
1146                 if (!vpm_enable && pagecreate) {
1147                         if ((uio->uio_loffset & PAGEOFFSET) || n == 0)
1148                                 (void) kzero(base, PAGESIZE - n);
1149 
1150                         if (pgcreated) {
1151                                 /*
1152                                  * Caller is responsible for this page,
1153                                  * it was not created in this loop.
1154                                  */
1155                                 pgcreated = 0;
1156                         } else {
1157                                 /*
1158                                  * For bug 1094402: segmap_pagecreate locks
1159                                  * page. Unlock it. This also unlocks the
1160                                  * pages allocated by page_create_va() in
1161                                  * segmap_pagecreate().
1162                                  */
1163                                 sm_error = segmap_fault(kas.a_hat, segkmap,
1164                                     saved_base, saved_n,
1165                                     F_SOFTUNLOCK, S_WRITE);
1166                                 if (error == 0)
1167                                         error = sm_error;
1168                         }
1169                 }
1170         } while (tcount > 0 && error == 0);
1171 
1172         return (error);
1173 }
1174 
1175 /*
1176  * Flags are composed of {B_ASYNC, B_INVAL, B_FREE, B_DONTNEED}
1177  * Like nfs3_rdwrlbn()
1178  */
1179 static int
1180 smbfs_rdwrlbn(vnode_t *vp, page_t *pp, u_offset_t off, size_t len,
1181         int flags, cred_t *cr)
1182 {
1183         smbmntinfo_t    *smi = VTOSMI(vp);
1184         struct buf *bp;
1185         int error;
1186         int sync;
1187 
1188         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1189                 return (EIO);
1190 
1191         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1192                 return (EIO);
1193 
1194         bp = pageio_setup(pp, len, vp, flags);
1195         ASSERT(bp != NULL);
1196 
1197         /*
1198          * pageio_setup should have set b_addr to 0.  This
1199          * is correct since we want to do I/O on a page
1200          * boundary.  bp_mapin will use this addr to calculate
1201          * an offset, and then set b_addr to the kernel virtual
1202          * address it allocated for us.
1203          */
1204         ASSERT(bp->b_un.b_addr == 0);
1205 
1206         bp->b_edev = 0;
1207         bp->b_dev = 0;
1208         bp->b_lblkno = lbtodb(off);
1209         bp->b_file = vp;
1210         bp->b_offset = (offset_t)off;
1211         bp_mapin(bp);
1212 
1213         /*
1214          * Calculate the desired level of stability to write data.
1215          */
1216         if ((flags & (B_WRITE|B_ASYNC)) == (B_WRITE|B_ASYNC) &&
1217             freemem > desfree) {
1218                 sync = 0;
1219         } else {
1220                 sync = 1;
1221         }
1222 
1223         error = smbfs_bio(bp, sync, cr);
1224 
1225         bp_mapout(bp);
1226         pageio_done(bp);
1227 
1228         return (error);
1229 }
1230 
1231 
1232 /*
1233  * Corresponds to nfs3_vnopc.c : nfs3_bio(), though the NFS code
1234  * uses nfs3read()/nfs3write() where we use smb_rwuio().  Also,
1235  * NFS has this later in the file.  Move it up here closer to
1236  * the one call site just above.
1237  */
1238 
1239 static int
1240 smbfs_bio(struct buf *bp, int sync, cred_t *cr)
1241 {
1242         struct iovec aiov[1];
1243         struct uio  auio;
1244         struct smb_cred scred;
1245         smbnode_t *np = VTOSMB(bp->b_vp);
1246         smbmntinfo_t *smi = np->n_mount;
1247         smb_share_t *ssp = smi->smi_share;
1248         offset_t offset;
1249         offset_t endoff;
1250         size_t count;
1251         size_t past_eof;
1252         int error;
1253 
1254         ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1255 
1256         offset = ldbtob(bp->b_lblkno);
1257         count = bp->b_bcount;
1258         endoff = offset + count;
1259         if (offset < 0 || endoff < 0)
1260                 return (EINVAL);
1261 
1262         /*
1263          * Limit file I/O to the remaining file size, but see
1264          * the notes in smbfs_getpage about SMBFS_EOF.
1265          */
1266         mutex_enter(&np->r_statelock);
1267         if (offset >= np->r_size) {
1268                 mutex_exit(&np->r_statelock);
1269                 if (bp->b_flags & B_READ) {
1270                         return (SMBFS_EOF);
1271                 } else {
1272                         return (EINVAL);
1273                 }
1274         }
1275         if (endoff > np->r_size) {
1276                 past_eof = (size_t)(endoff - np->r_size);
1277                 count -= past_eof;
1278         } else
1279                 past_eof = 0;
1280         mutex_exit(&np->r_statelock);
1281         ASSERT(count > 0);
1282 
1283         /* Caller did bpmapin().  Mapped address is... */
1284         aiov[0].iov_base = bp->b_un.b_addr;
1285         aiov[0].iov_len = count;
1286         auio.uio_iov = aiov;
1287         auio.uio_iovcnt = 1;
1288         auio.uio_loffset = offset;
1289         auio.uio_segflg = UIO_SYSSPACE;
1290         auio.uio_fmode = 0;
1291         auio.uio_resid = count;
1292 
1293         /* Shared lock for n_fid use in smb_rwuio */
1294         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER,
1295             smi->smi_flags & SMI_INT))
1296                 return (EINTR);
1297         smb_credinit(&scred, cr);
1298 
1299         DTRACE_IO1(start, struct buf *, bp);
1300 
1301         if (bp->b_flags & B_READ) {
1302 
1303                 /* After reconnect, n_fid is invalid */
1304                 if (np->n_vcgenid != ssp->ss_vcgenid)
1305                         error = ESTALE;
1306                 else
1307                         error = smb_rwuio(ssp, np->n_fid, UIO_READ,
1308                             &auio, &scred, smb_timo_read);
1309 
1310                 /* Like NFS, only set b_error here. */
1311                 bp->b_error = error;
1312                 bp->b_resid = auio.uio_resid;
1313 
1314                 if (!error && auio.uio_resid != 0)
1315                         error = EIO;
1316                 if (!error && past_eof != 0) {
1317                         /* Zero the memory beyond EOF. */
1318                         bzero(bp->b_un.b_addr + count, past_eof);
1319                 }
1320         } else {
1321 
1322                 /* After reconnect, n_fid is invalid */
1323                 if (np->n_vcgenid != ssp->ss_vcgenid)
1324                         error = ESTALE;
1325                 else
1326                         error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
1327                             &auio, &scred, smb_timo_write);
1328 
1329                 /* Like NFS, only set b_error here. */
1330                 bp->b_error = error;
1331                 bp->b_resid = auio.uio_resid;
1332 
1333                 if (!error && auio.uio_resid != 0)
1334                         error = EIO;
1335                 if (!error && sync) {
1336                         (void) smbfs_smb_flush(np, &scred);
1337                 }
1338         }
1339 
1340         /*
1341          * This comes from nfs3_commit()
1342          */
1343         if (error != 0) {
1344                 mutex_enter(&np->r_statelock);
1345                 if (error == ESTALE)
1346                         np->r_flags |= RSTALE;
1347                 if (!np->r_error)
1348                         np->r_error = error;
1349                 mutex_exit(&np->r_statelock);
1350                 bp->b_flags |= B_ERROR;
1351         }
1352 
1353         DTRACE_IO1(done, struct buf *, bp);
1354 
1355         smb_credrele(&scred);
1356         smbfs_rw_exit(&np->r_lkserlock);
1357 
1358         if (error == ESTALE)
1359                 smbfs_attrcache_remove(np);
1360 
1361         return (error);
1362 }
1363 
1364 /*
1365  * Here NFS has: nfs3write, nfs3read
1366  * We use smb_rwuio instead.
1367  */
1368 
1369 /* ARGSUSED */
1370 static int
1371 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
1372         cred_t *cr, int *rvalp, caller_context_t *ct)
1373 {
1374         int             error;
1375         smbmntinfo_t    *smi;
1376 
1377         smi = VTOSMI(vp);
1378 
1379         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1380                 return (EIO);
1381 
1382         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1383                 return (EIO);
1384 
1385         switch (cmd) {

1386 
1387         case _FIOFFS:
1388                 error = smbfs_fsync(vp, 0, cr, ct);
1389                 break;
1390 
1391                 /*
1392                  * The following two ioctls are used by bfu.
1393                  * Silently ignore to avoid bfu errors.
1394                  */
1395         case _FIOGDIO:
1396         case _FIOSDIO:
1397                 error = 0;
1398                 break;
1399 
1400 #if 0   /* Todo - SMB ioctl query regions */
1401         case _FIO_SEEK_DATA:
1402         case _FIO_SEEK_HOLE:
1403 #endif
1404 
1405         case _FIODIRECTIO:
1406                 error = smbfs_directio(vp, (int)arg, cr);
1407                 break;
1408 
1409                 /*
1410                  * Allow get/set with "raw" security descriptor (SD) data.
1411                  * Useful for testing, diagnosing idmap problems, etc.
1412                  */
1413         case SMBFSIO_GETSD:
1414                 error = smbfs_acl_iocget(vp, arg, flag, cr);
1415                 break;
1416 
1417         case SMBFSIO_SETSD:
1418                 error = smbfs_acl_iocset(vp, arg, flag, cr);
1419                 break;
1420 
1421         default:
1422                 error = ENOTTY;
1423                 break;
1424         }
1425 
1426         return (error);
1427 }
1428 
1429 
1430 /*
1431  * Return either cached or remote attributes. If get remote attr
1432  * use them to check and invalidate caches, then cache the new attributes.
1433  */
1434 /* ARGSUSED */
1435 static int
1436 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
1437         caller_context_t *ct)
1438 {
1439         smbnode_t *np;
1440         smbmntinfo_t *smi;
1441         int error;
1442 
1443         smi = VTOSMI(vp);
1444 
1445         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1446                 return (EIO);
1447 
1448         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1449                 return (EIO);
1450 
1451         /*
1452          * If it has been specified that the return value will
1453          * just be used as a hint, and we are only being asked
1454          * for size, fsid or rdevid, then return the client's
1455          * notion of these values without checking to make sure
1456          * that the attribute cache is up to date.
1457          * The whole point is to avoid an over the wire GETATTR
1458          * call.
1459          */
1460         np = VTOSMB(vp);
1461         if (flags & ATTR_HINT) {
1462                 if (vap->va_mask ==
1463                     (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) {
1464                         mutex_enter(&np->r_statelock);
1465                         if (vap->va_mask | AT_SIZE)
1466                                 vap->va_size = np->r_size;
1467                         if (vap->va_mask | AT_FSID)
1468                                 vap->va_fsid = vp->v_vfsp->vfs_dev;
1469                         if (vap->va_mask | AT_RDEV)
1470                                 vap->va_rdev = vp->v_rdev;
1471                         mutex_exit(&np->r_statelock);
1472                         return (0);
1473                 }
1474         }
1475 
1476         /*
1477          * Only need to flush pages if asking for the mtime
1478          * and if there any dirty pages.
1479          *
1480          * Here NFS also checks for async writes (np->r_awcount)
1481          */
1482         if (vap->va_mask & AT_MTIME) {
1483                 if (vn_has_cached_data(vp) &&
1484                     ((np->r_flags & RDIRTY) != 0)) {
1485                         mutex_enter(&np->r_statelock);
1486                         np->r_gcount++;
1487                         mutex_exit(&np->r_statelock);
1488                         error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, ct);
1489                         mutex_enter(&np->r_statelock);
1490                         if (error && (error == ENOSPC || error == EDQUOT)) {
1491                                 if (!np->r_error)
1492                                         np->r_error = error;
1493                         }
1494                         if (--np->r_gcount == 0)
1495                                 cv_broadcast(&np->r_cv);
1496                         mutex_exit(&np->r_statelock);
1497                 }
1498         }
1499 
1500         return (smbfsgetattr(vp, vap, cr));
1501 }
1502 
1503 /* smbfsgetattr() in smbfs_client.c */
1504 
1505 /*ARGSUSED4*/
1506 static int
1507 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
1508                 caller_context_t *ct)
1509 {
1510         vfs_t           *vfsp;
1511         smbmntinfo_t    *smi;
1512         int             error;
1513         uint_t          mask;
1514         struct vattr    oldva;
1515 
1516         vfsp = vp->v_vfsp;
1517         smi = VFTOSMI(vfsp);
1518 
1519         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)


1550                 return (error);
1551 
1552         if (mask & (AT_UID | AT_GID)) {
1553                 if (smi->smi_flags & SMI_ACL)
1554                         error = smbfs_acl_setids(vp, vap, cr);
1555                 else
1556                         error = ENOSYS;
1557                 if (error != 0) {
1558                         SMBVDEBUG("error %d seting UID/GID on %s",
1559                             error, VTOSMB(vp)->n_rpath);
1560                         /*
1561                          * It might be more correct to return the
1562                          * error here, but that causes complaints
1563                          * when root extracts a cpio archive, etc.
1564                          * So ignore this error, and go ahead with
1565                          * the rest of the setattr work.
1566                          */
1567                 }
1568         }
1569 
1570         error = smbfssetattr(vp, vap, flags, cr);
1571 
1572 #ifdef  SMBFS_VNEVENT
1573         if (error == 0 && (vap->va_mask & AT_SIZE) && vap->va_size == 0)
1574                 vnevent_truncate(vp, ct);
1575 #endif
1576 
1577         return (error);
1578 }
1579 
1580 /*
1581  * Mostly from Darwin smbfs_setattr()
1582  * but then modified a lot.
1583  */
1584 /* ARGSUSED */
1585 static int
1586 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
1587 {
1588         int             error = 0;
1589         smbnode_t       *np = VTOSMB(vp);
1590         uint_t          mask = vap->va_mask;
1591         struct timespec *mtime, *atime;
1592         struct smb_cred scred;
1593         int             cerror, modified = 0;
1594         unsigned short  fid;
1595         int have_fid = 0;
1596         uint32_t rights = 0;
1597         uint32_t dosattr = 0;
1598 
1599         ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
1600 
1601         /*
1602          * There are no settable attributes on the XATTR dir,
1603          * so just silently ignore these.  On XATTR files,
1604          * you can set the size but nothing else.
1605          */
1606         if (vp->v_flag & V_XATTRDIR)
1607                 return (0);
1608         if (np->n_flag & N_XATTR) {
1609                 if (mask & AT_TIMES)
1610                         SMBVDEBUG("ignore set time on xattr\n");
1611                 mask &= AT_SIZE;
1612         }
1613 
1614         /*
1615          * Only need to flush pages if there are any pages and
1616          * if the file is marked as dirty in some fashion.  The
1617          * file must be flushed so that we can accurately
1618          * determine the size of the file and the cached data
1619          * after the SETATTR returns.  A file is considered to
1620          * be dirty if it is either marked with RDIRTY, has
1621          * outstanding i/o's active, or is mmap'd.  In this
1622          * last case, we can't tell whether there are dirty
1623          * pages, so we flush just to be sure.
1624          */
1625         if (vn_has_cached_data(vp) &&
1626             ((np->r_flags & RDIRTY) ||
1627             np->r_count > 0 ||
1628             np->r_mapcnt > 0)) {
1629                 ASSERT(vp->v_type != VCHR);
1630                 error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, NULL);
1631                 if (error && (error == ENOSPC || error == EDQUOT)) {
1632                         mutex_enter(&np->r_statelock);
1633                         if (!np->r_error)
1634                                 np->r_error = error;
1635                         mutex_exit(&np->r_statelock);
1636                 }
1637         }
1638 
1639         /*
1640          * If our caller is trying to set multiple attributes, they
1641          * can make no assumption about what order they are done in.
1642          * Here we try to do them in order of decreasing likelihood
1643          * of failure, just to minimize the chance we'll wind up
1644          * with a partially complete request.
1645          */
1646 
1647         /* Shared lock for (possible) n_fid use. */
1648         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1649                 return (EINTR);
1650         smb_credinit(&scred, cr);
1651 
1652         /*
1653          * If the caller has provided extensible attributes,
1654          * map those into DOS attributes supported by SMB.
1655          * Note: zero means "no change".
1656          */
1657         if (mask & AT_XVATTR)
1658                 dosattr = xvattr_to_dosattr(np, vap);
1659 


1681                 error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
1682                 if (error) {
1683                         SMBVDEBUG("error %d opening %s\n",
1684                             error, np->n_rpath);
1685                         goto out;
1686                 }
1687                 have_fid = 1;
1688         }
1689 
1690         /*
1691          * If the server supports the UNIX extensions, right here is where
1692          * we'd support changes to uid, gid, mode, and possibly va_flags.
1693          * For now we claim to have made any such changes.
1694          */
1695 
1696         if (mask & AT_SIZE) {
1697                 /*
1698                  * If the new file size is less than what the client sees as
1699                  * the file size, then just change the size and invalidate
1700                  * the pages.


1701                  */
1702 
1703                 /*
1704                  * Set the file size to vap->va_size.
1705                  */
1706                 ASSERT(have_fid);
1707                 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred);
1708                 if (error) {
1709                         SMBVDEBUG("setsize error %d file %s\n",
1710                             error, np->n_rpath);
1711                 } else {
1712                         /*
1713                          * Darwin had code here to zero-extend.
1714                          * Tests indicate the server will zero-fill,
1715                          * so looks like we don't need to do that.




1716                          */
1717                         mutex_enter(&np->r_statelock);
1718                         np->r_size = vap->va_size;
1719                         mutex_exit(&np->r_statelock);
1720                         modified = 1;
1721                 }
1722         }
1723 
1724         /*
1725          * Todo: Implement setting create_time (which is
1726          * different from ctime).
1727          */
1728         mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
1729         atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
1730 
1731         if (dosattr || mtime || atime) {
1732                 /*
1733                  * Always use the handle-based set attr call now.
1734                  */
1735                 ASSERT(have_fid);
1736                 error = smbfs_smb_setfattr(np, fid,
1737                     dosattr, mtime, atime, &scred);
1738                 if (error) {
1739                         SMBVDEBUG("set times error %d file %s\n",
1740                             error, np->n_rpath);
1741                 } else {
1742                         modified = 1;
1743                 }
1744         }
1745 
1746 out:








1747         if (have_fid) {
1748                 cerror = smbfs_smb_tmpclose(np, fid, &scred);
1749                 if (cerror)
1750                         SMBVDEBUG("error %d closing %s\n",
1751                             cerror, np->n_rpath);
1752         }
1753 
1754         smb_credrele(&scred);
1755         smbfs_rw_exit(&np->r_lkserlock);
1756 
1757         if (modified) {
1758                 /*
1759                  * Invalidate attribute cache in case the server
1760                  * doesn't set exactly the attributes we asked.
1761                  */
1762                 smbfs_attrcache_remove(np);
1763 
1764                 /*
1765                  * If changing the size of the file, invalidate
1766                  * any local cached data which is no longer part
1767                  * of the file.  We also possibly invalidate the
1768                  * last page in the file.  We could use
1769                  * pvn_vpzero(), but this would mark the page as
1770                  * modified and require it to be written back to
1771                  * the server for no particularly good reason.
1772                  * This way, if we access it, then we bring it
1773                  * back in.  A read should be cheaper than a
1774                  * write.
1775                  */
1776                 if (mask & AT_SIZE) {
1777                         smbfs_invalidate_pages(vp,
1778                             (vap->va_size & PAGEMASK), cr);
1779                 }
1780         }
1781 
1782         return (error);
1783 }
1784 
1785 /*
1786  * Helper function for extensible system attributes (PSARC 2007/315)
1787  * Compute the DOS attribute word to pass to _setfattr (see above).
1788  * This returns zero IFF no change is being made to attributes.
1789  * Otherwise return the new attributes or SMB_EFA_NORMAL.
1790  */
1791 static uint32_t
1792 xvattr_to_dosattr(smbnode_t *np, struct vattr *vap)
1793 {
1794         xvattr_t *xvap = (xvattr_t *)vap;
1795         xoptattr_t *xoap = NULL;
1796         uint32_t attr = np->r_attr.fa_attr;
1797         boolean_t anyset = B_FALSE;
1798 
1799         if ((xoap = xva_getxoptattr(xvap)) == NULL)
1800                 return (0);
1801 


1848  * due to the current "single user mounts" restriction:
1849  * All access under a given mount point uses the CIFS
1850  * credentials established by the owner of the mount.
1851  *
1852  * Most access checking is handled by the CIFS server,
1853  * but we need sufficient Unix access checks here to
1854  * prevent other local Unix users from having access
1855  * to objects under this mount that the uid/gid/mode
1856  * settings in the mount would not allow.
1857  *
1858  * With this model, there is a case where we need the
1859  * ability to do an access check before we have the
1860  * vnode for an object.  This function takes advantage
1861  * of the fact that the uid/gid/mode is per mount, and
1862  * avoids the need for a vnode.
1863  *
1864  * We still (sort of) need a vnode when we call
1865  * secpolicy_vnode_access, but that only uses
1866  * the vtype field, so we can use a pair of fake
1867  * vnodes that have only v_type filled in.




1868  */
1869 static int
1870 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
1871 {
1872         /* See the secpolicy call below. */
1873         static const vnode_t tmpl_vdir = { .v_type = VDIR };
1874         static const vnode_t tmpl_vreg = { .v_type = VREG };
1875         vattr_t         va;
1876         vnode_t         *tvp;
1877         struct smbmntinfo *smi = VFTOSMI(vfsp);
1878         int shift = 0;
1879 
1880         /*
1881          * Build our (fabricated) vnode attributes.


1882          */
1883         bzero(&va, sizeof (va));
1884         va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1885         va.va_type = vtype;
1886         va.va_mode = (vtype == VDIR) ?
1887             smi->smi_dmode : smi->smi_fmode;
1888         va.va_uid = smi->smi_uid;
1889         va.va_gid = smi->smi_gid;
1890 
1891         /*
1892          * Disallow write attempts on read-only file systems,
1893          * unless the file is a device or fifo node.  Note:
1894          * Inline vn_is_readonly and IS_DEVVP here because
1895          * we may not have a vnode ptr.  Original expr. was:
1896          * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp))
1897          */
1898         if ((mode & VWRITE) &&
1899             (vfsp->vfs_flag & VFS_RDONLY) &&
1900             !(vtype == VCHR || vtype == VBLK || vtype == VFIFO))
1901                 return (EROFS);
1902 
1903         /*
1904          * Disallow attempts to access mandatory lock files.
1905          * Similarly, expand MANDLOCK here.

1906          */
1907         if ((mode & (VWRITE | VREAD | VEXEC)) &&
1908             va.va_type == VREG && MANDMODE(va.va_mode))
1909                 return (EACCES);
1910 
1911         /*
1912          * Access check is based on only
1913          * one of owner, group, public.
1914          * If not owner, then check group.
1915          * If not a member of the group,
1916          * then check public access.
1917          */
1918         if (crgetuid(cr) != va.va_uid) {
1919                 shift += 3;
1920                 if (!groupmember(va.va_gid, cr))
1921                         shift += 3;
1922         }
1923 
1924         /*
1925          * We need a vnode for secpolicy_vnode_access,


1955 /* ARGSUSED */
1956 static int
1957 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1958 {
1959         vfs_t           *vfsp;
1960         smbmntinfo_t    *smi;
1961 
1962         vfsp = vp->v_vfsp;
1963         smi = VFTOSMI(vfsp);
1964 
1965         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1966                 return (EIO);
1967 
1968         if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1969                 return (EIO);
1970 
1971         return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr));
1972 }
1973 
1974 
1975 /* ARGSUSED */
1976 static int
1977 smbfs_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr, caller_context_t *ct)
1978 {
1979         /* Not yet... */
1980         return (ENOSYS);
1981 }
1982 
1983 
1984 /*
1985  * Flush local dirty pages to stable storage on the server.
1986  *
1987  * If FNODSYNC is specified, then there is nothing to do because
1988  * metadata changes are not cached on the client before being
1989  * sent to the server.
1990  */
1991 /* ARGSUSED */
1992 static int
1993 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
1994 {
1995         int             error = 0;
1996         smbmntinfo_t    *smi;
1997         smbnode_t       *np;
1998         struct smb_cred scred;
1999 
2000         np = VTOSMB(vp);
2001         smi = VTOSMI(vp);
2002 
2003         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2004                 return (EIO);
2005 
2006         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2007                 return (EIO);
2008 
2009         if ((syncflag & FNODSYNC) || IS_SWAPVP(vp))
2010                 return (0);
2011 
2012         if ((syncflag & (FSYNC|FDSYNC)) == 0)
2013                 return (0);
2014 
2015         error = smbfs_putpage(vp, (offset_t)0, 0, 0, cr, ct);
2016         if (error)
2017                 return (error);
2018 
2019         /* Shared lock for n_fid use in _flush */
2020         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
2021                 return (EINTR);
2022         smb_credinit(&scred, cr);
2023 
2024         error = smbfs_smb_flush(np, &scred);
2025 
2026         smb_credrele(&scred);
2027         smbfs_rw_exit(&np->r_lkserlock);
2028 
2029         return (error);
2030 }
2031 
2032 /*
2033  * Last reference to vnode went away.
2034  */
2035 /* ARGSUSED */
2036 static void
2037 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
2038 {

2039         struct smb_cred scred;
2040         smbnode_t       *np = VTOSMB(vp);
2041         int error;
2042 
2043         /*
2044          * Don't "bail out" for VFS_UNMOUNTED here,
2045          * as we want to do cleanup, etc.
2046          * See also pcfs_inactive
2047          */
2048 


2049         /*
2050          * If this is coming from the wrong zone, we let someone in the right
2051          * zone take care of it asynchronously.  We can get here due to
2052          * VN_RELE() being called from pageout() or fsflush().  This call may
2053          * potentially turn into an expensive no-op if, for instance, v_count
2054          * gets incremented in the meantime, but it's still correct.
2055          */
2056 
2057         /*
2058          * From NFS:rinactive()
2059          *
2060          * Before freeing anything, wait until all asynchronous
2061          * activity is done on this rnode.  This will allow all
2062          * asynchronous read ahead and write behind i/o's to
2063          * finish.
2064          */
2065         mutex_enter(&np->r_statelock);
2066         while (np->r_count > 0)
2067                 cv_wait(&np->r_cv, &np->r_statelock);
2068         mutex_exit(&np->r_statelock);
2069 
2070         /*
2071          * Flush and invalidate all pages associated with the vnode.
2072          */
2073         if (vn_has_cached_data(vp)) {
2074                 if ((np->r_flags & RDIRTY) && !np->r_error) {
2075                         error = smbfs_putpage(vp, (u_offset_t)0, 0, 0, cr, ct);
2076                         if (error && (error == ENOSPC || error == EDQUOT)) {
2077                                 mutex_enter(&np->r_statelock);
2078                                 if (!np->r_error)
2079                                         np->r_error = error;
2080                                 mutex_exit(&np->r_statelock);
2081                         }
2082                 }
2083                 smbfs_invalidate_pages(vp, (u_offset_t)0, cr);
2084         }
2085         /*
2086          * This vnode should have lost all cached data.
2087          */
2088         ASSERT(vn_has_cached_data(vp) == 0);
2089 
2090         /*
2091          * Defend against the possibility that higher-level callers
2092          * might not correctly balance open and close calls.  If we
2093          * get here with open references remaining, it means there
2094          * was a missing VOP_CLOSE somewhere.  If that happens, do
2095          * the close here so we don't "leak" FIDs on the server.
2096          *
2097          * Exclusive lock for modifying n_fid stuff.
2098          * Don't want this one ever interruptible.
2099          */
2100         (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
2101         smb_credinit(&scred, cr);
2102 
2103         switch (np->n_ovtype) {
2104         case VNON:
2105                 /* not open (OK) */
2106                 break;
2107 
2108         case VDIR:
2109                 if (np->n_dirrefs == 0)
2110                         break;


2218         int             rplen;
2219         struct smb_cred scred;
2220         struct smbfattr fa;
2221 
2222         smi = VTOSMI(dvp);
2223         dnp = VTOSMB(dvp);
2224 
2225         ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
2226 
2227 #ifdef NOT_YET
2228         vcp = SSTOVC(smi->smi_share);
2229 
2230         /* XXX: Should compute this once and store it in smbmntinfo_t */
2231         supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12;
2232 #else
2233         supplen = 255;
2234 #endif
2235 
2236         /*
2237          * RWlock must be held, either reader or writer.


2238          */
2239         ASSERT(dnp->r_rwlock.count != 0);
2240 
2241         /*
2242          * If lookup is for "", just return dvp.
2243          * No need to perform any access checks.
2244          */
2245         if (nmlen == 0) {
2246                 VN_HOLD(dvp);
2247                 *vpp = dvp;
2248                 return (0);
2249         }
2250 
2251         /*
2252          * Can't do lookups in non-directories.
2253          */
2254         if (dvp->v_type != VDIR)
2255                 return (ENOTDIR);
2256 
2257         /*


2264         /*
2265          * If lookup is for ".", just return dvp.
2266          * Access check was done above.
2267          */
2268         if (nmlen == 1 && name[0] == '.') {
2269                 VN_HOLD(dvp);
2270                 *vpp = dvp;
2271                 return (0);
2272         }
2273 
2274         /*
2275          * Now some sanity checks on the name.
2276          * First check the length.
2277          */
2278         if (nmlen > supplen)
2279                 return (ENAMETOOLONG);
2280 
2281         /*
2282          * Avoid surprises with characters that are
2283          * illegal in Windows file names.
2284          * Todo: CATIA mappings?
2285          */
2286         ill = illegal_chars;
2287         if (dnp->n_flag & N_XATTR)
2288                 ill++; /* allow colon */
2289         if (strpbrk(nm, ill))
2290                 return (EINVAL);
2291 
2292         /*
2293          * Special handling for lookup of ".."
2294          *
2295          * We keep full pathnames (as seen on the server)
2296          * so we can just trim off the last component to
2297          * get the full pathname of the parent.  Note:
2298          * We don't actually copy and modify, but just
2299          * compute the trimmed length and pass that with
2300          * the current dir path (not null terminated).
2301          *
2302          * We don't go over-the-wire to get attributes
2303          * for ".." because we know it's a directory,
2304          * and we can just leave the rest "stale"


2485         if (np->r_attrtime <= gethrtime()) {
2486                 /* stale */
2487 #ifdef DEBUG
2488                 smbfs_lookup_cache_stale++;
2489 #endif
2490                 VN_RELE(vp);
2491                 return (0);
2492         }
2493 
2494         /*
2495          * Success!
2496          * Caller gets hold from smbfs_node_findcreate
2497          */
2498 #ifdef DEBUG
2499         smbfs_lookup_cache_hits++;
2500 #endif
2501         *vpp = vp;
2502         return (0);
2503 }
2504 
2505 
2506 /*
2507  * XXX
2508  * vsecattr_t is new to build 77, and we need to eventually support
2509  * it in order to create an ACL when an object is created.
2510  *
2511  * This op should support the new FIGNORECASE flag for case-insensitive
2512  * lookups, per PSARC 2007/244.
2513  */
2514 /* ARGSUSED */
2515 static int
2516 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
2517         int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
2518         vsecattr_t *vsecp)
2519 {
2520         int             error;
2521         int             cerror;
2522         vfs_t           *vfsp;
2523         vnode_t         *vp;

2524         smbnode_t       *np;

2525         smbnode_t       *dnp;
2526         smbmntinfo_t    *smi;
2527         struct vattr    vattr;
2528         struct smbfattr fattr;
2529         struct smb_cred scred;
2530         const char *name = (const char *)nm;
2531         int             nmlen = strlen(nm);
2532         uint32_t        disp;
2533         uint16_t        fid;
2534         int             xattr;
2535 
2536         vfsp = dvp->v_vfsp;
2537         smi = VFTOSMI(vfsp);
2538         dnp = VTOSMB(dvp);
2539         vp = NULL;
2540 
2541         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2542                 return (EPERM);
2543 
2544         if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
2545                 return (EIO);
2546 
2547         /*
2548          * Note: this may break mknod(2) calls to create a directory,
2549          * but that's obscure use.  Some other filesystems do this.
2550          * Todo: redirect VDIR type here to _mkdir.
2551          */
2552         if (va->va_type != VREG)
2553                 return (EINVAL);
2554 
2555         /*
2556          * If the pathname is "", just use dvp, no checks.
2557          * Do this outside of the rwlock (like zfs).
2558          */
2559         if (nmlen == 0) {
2560                 VN_HOLD(dvp);
2561                 *vpp = dvp;
2562                 return (0);
2563         }
2564 
2565         /* Don't allow "." or ".." through here. */
2566         if ((nmlen == 1 && name[0] == '.') ||
2567             (nmlen == 2 && name[0] == '.' && name[1] == '.'))
2568                 return (EISDIR);
2569 
2570         /*


2595                  * The file already exists.  Error?
2596                  * NB: have a hold from smbfslookup
2597                  */
2598                 if (exclusive == EXCL) {
2599                         error = EEXIST;
2600                         VN_RELE(vp);
2601                         goto out;
2602                 }
2603                 /*
2604                  * Verify requested access.
2605                  */
2606                 error = smbfs_access(vp, mode, 0, cr, ct);
2607                 if (error) {
2608                         VN_RELE(vp);
2609                         goto out;
2610                 }
2611 
2612                 /*
2613                  * Truncate (if requested).
2614                  */
2615                 if ((vattr.va_mask & AT_SIZE) && vp->v_type == VREG) {
2616                         np = VTOSMB(vp);
2617                         /*
2618                          * Check here for large file truncation by
2619                          * LF-unaware process, like ufs_create().
2620                          */
2621                         if (!(lfaware & FOFFMAX)) {
2622                                 mutex_enter(&np->r_statelock);
2623                                 if (np->r_size > MAXOFF32_T)
2624                                         error = EOVERFLOW;
2625                                 mutex_exit(&np->r_statelock);
2626                         }
2627                         if (error) {
2628                                 VN_RELE(vp);
2629                                 goto out;
2630                         }
2631                         vattr.va_mask = AT_SIZE;
2632                         error = smbfssetattr(vp, &vattr, 0, cr);
2633                         if (error) {
2634                                 VN_RELE(vp);
2635                                 goto out;
2636                         }
2637 #ifdef  SMBFS_VNEVENT
2638                         /* Existing file was truncated */

2639                         vnevent_create(vp, ct);
2640 #endif
2641                         /* invalidate pages done in smbfssetattr() */
2642                 }
2643                 /* Success! */
2644                 *vpp = vp;
2645                 goto out;
2646         }
2647 
2648         /*
2649          * The file did not exist.  Need VWRITE in the directory.
2650          */
2651         error = smbfs_access(dvp, VWRITE, 0, cr, ct);
2652         if (error)
2653                 goto out;
2654 
2655         /*
2656          * Now things get tricky.  We also need to check the
2657          * requested open mode against the file we may create.
2658          * See comments at smbfs_access_rwx
2659          */
2660         error = smbfs_access_rwx(vfsp, VREG, mode, cr);
2661         if (error)
2662                 goto out;
2663 


2672 
2673         if (exclusive == EXCL)
2674                 disp = NTCREATEX_DISP_CREATE;
2675         else {
2676                 /* Truncate regular files if requested. */
2677                 if ((va->va_type == VREG) &&
2678                     (va->va_mask & AT_SIZE) &&
2679                     (va->va_size == 0))
2680                         disp = NTCREATEX_DISP_OVERWRITE_IF;
2681                 else
2682                         disp = NTCREATEX_DISP_OPEN_IF;
2683         }
2684         xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
2685         error = smbfs_smb_create(dnp,
2686             name, nmlen, xattr,
2687             disp, &scred, &fid);
2688         if (error)
2689                 goto out;
2690 
2691         /*






























2692          * Should use the fid to get/set the size
2693          * while we have it opened here.  See above.
2694          */
2695 
2696         cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
2697         if (cerror)
2698                 SMBVDEBUG("error %d closing %s\\%s\n",
2699                     cerror, dnp->n_rpath, name);
2700 
2701         /*
2702          * In the open case, the name may differ a little
2703          * from what we passed to create (case, etc.)
2704          * so call lookup to get the (opened) name.
2705          *
2706          * XXX: Could avoid this extra lookup if the
2707          * "createact" result from NT_CREATE says we
2708          * created the object.
2709          */
2710         error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2711         if (error)
2712                 goto out;
2713 
2714         /* update attr and directory cache */
2715         smbfs_attr_touchdir(dnp);
2716 
2717         error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2718         if (error)
2719                 goto out;
2720 


2721         /* Success! */
2722         *vpp = vp;
2723         error = 0;
2724 
2725 out:
2726         smb_credrele(&scred);
2727         smbfs_rw_exit(&dnp->r_rwlock);
2728         if (name != nm)
2729                 smbfs_name_free(name, nmlen);
2730         return (error);
2731 }
2732 
2733 /*
2734  * XXX
2735  * This op should support the new FIGNORECASE flag for case-insensitive
2736  * lookups, per PSARC 2007/244.
2737  */
2738 /* ARGSUSED */
2739 static int
2740 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,


2806     int flags)
2807 {
2808         smbnode_t       *dnp = VTOSMB(dvp);
2809         smbnode_t       *np = VTOSMB(vp);
2810         char            *tmpname = NULL;
2811         int             tnlen;
2812         int             error;
2813         unsigned short  fid;
2814         boolean_t       have_fid = B_FALSE;
2815         boolean_t       renamed = B_FALSE;
2816 
2817         /*
2818          * The dvp RWlock must be held as writer.
2819          */
2820         ASSERT(dnp->r_rwlock.owner == curthread);
2821 
2822         /* Never allow link/unlink directories on SMB. */
2823         if (vp->v_type == VDIR)
2824                 return (EPERM);
2825 
2826         /*
2827          * We need to flush any dirty pages which happen to
2828          * be hanging around before removing the file.  This
2829          * shouldn't happen very often and mostly on file
2830          * systems mounted "nocto".
2831          */
2832         if (vn_has_cached_data(vp) &&
2833             ((np->r_flags & RDIRTY) || np->r_count > 0)) {
2834                 error = smbfs_putpage(vp, (offset_t)0, 0, 0,
2835                     scred->scr_cred, NULL);
2836                 if (error && (error == ENOSPC || error == EDQUOT)) {
2837                         mutex_enter(&np->r_statelock);
2838                         if (!np->r_error)
2839                                 np->r_error = error;
2840                         mutex_exit(&np->r_statelock);
2841                 }
2842         }
2843 
2844         /* Shared lock for n_fid use in smbfs_smb_setdisp etc. */
2845         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
2846                 return (EINTR);
2847 



2848         /*
2849          * Get a file handle with delete access.
2850          * Close this FID before return.
2851          */
2852         error = smbfs_smb_tmpopen(np, STD_RIGHT_DELETE_ACCESS,
2853             scred, &fid);
2854         if (error) {
2855                 SMBVDEBUG("error %d opening %s\n",
2856                     error, np->n_rpath);
2857                 goto out;
2858         }
2859         have_fid = B_TRUE;
2860 
2861         /*
2862          * If we have the file open, try to rename it to a temporary name.
2863          * If we can't rename, continue on and try setting DoC anyway.
2864          */
2865         if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
2866                 tmpname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
2867                 tnlen = smbfs_newname(tmpname, MAXNAMELEN);


2890                  * the separator ('/' or ':')
2891                  */
2892                 if (renamed) {
2893                         char *oldname;
2894                         int oldnlen;
2895                         int err2;
2896 
2897                         oldname = np->n_rpath + (dnp->n_rplen + 1);
2898                         oldnlen = np->n_rplen - (dnp->n_rplen + 1);
2899                         err2 = smbfs_smb_t2rename(np, oldname, oldnlen,
2900                             scred, fid, 0);
2901                         SMBVDEBUG("error %d un-renaming %s -> %s\n",
2902                             err2, tmpname, np->n_rpath);
2903                 }
2904                 error = EBUSY;
2905                 goto out;
2906         }
2907         /* Done! */
2908         smbfs_attrcache_prune(np);
2909 
2910 #ifdef  SMBFS_VNEVENT
2911         vnevent_remove(vp, dvp, nm, ct);
2912 #endif
2913 
2914 out:
2915         if (tmpname != NULL)
2916                 kmem_free(tmpname, MAXNAMELEN);
2917 
2918         if (have_fid)
2919                 (void) smbfs_smb_tmpclose(np, fid, scred);
2920         smbfs_rw_exit(&np->r_lkserlock);
2921 
2922         if (error == 0) {
2923                 /* Keep lookup from finding this node anymore. */
2924                 smbfs_rmhash(np);
2925         }
2926 
2927         return (error);
2928 }
2929 
2930 
2931 /* ARGSUSED */
2932 static int
2933 smbfs_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr,
2934         caller_context_t *ct, int flags)
2935 {
2936         /* Not yet... */
2937         return (ENOSYS);
2938 }
2939 
2940 
2941 /*
2942  * XXX
2943  * This op should support the new FIGNORECASE flag for case-insensitive
2944  * lookups, per PSARC 2007/244.
2945  */
2946 /* ARGSUSED */
2947 static int
2948 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2949         caller_context_t *ct, int flags)
2950 {
2951         struct smb_cred scred;
2952         smbnode_t       *odnp = VTOSMB(odvp);
2953         smbnode_t       *ndnp = VTOSMB(ndvp);
2954         vnode_t         *ovp;
2955         int error;
2956 
2957         if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone ||
2958             curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone)
2959                 return (EPERM);
2960 


3113                  */
3114                 if (nvp->v_type == VDIR) {
3115                         error = EEXIST;
3116                         goto out;
3117                 }
3118                 error = smbfsremove(ndvp, nvp, scred, flags);
3119                 if (error != 0)
3120                         goto out;
3121 
3122                 /*
3123                  * OK, removed the target file.  Continue as if
3124                  * lookup target had failed (nvp == NULL).
3125                  */
3126                 vn_vfsunlock(nvp);
3127                 nvp_locked = 0;
3128                 VN_RELE(nvp);
3129                 nvp = NULL;
3130         } /* nvp */
3131 
3132         smbfs_attrcache_remove(onp);

3133         error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), scred);
3134 
3135         /*
3136          * If the old name should no longer exist,
3137          * discard any cached attributes under it.
3138          */
3139         if (error == 0) {
3140                 smbfs_attrcache_prune(onp);
3141                 /* SMBFS_VNEVENT... */
3142         }
3143 
3144 out:
3145         if (nvp) {
3146                 if (nvp_locked)
3147                         vn_vfsunlock(nvp);
3148                 VN_RELE(nvp);
3149         }
3150 
3151         return (error);
3152 }
3153 
3154 /*
3155  * XXX
3156  * vsecattr_t is new to build 77, and we need to eventually support
3157  * it in order to create an ACL when an object is created.
3158  *
3159  * This op should support the new FIGNORECASE flag for case-insensitive
3160  * lookups, per PSARC 2007/244.
3161  */
3162 /* ARGSUSED */


3175 
3176         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3177                 return (EPERM);
3178 
3179         if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3180                 return (EIO);
3181 
3182         if ((nmlen == 1 && name[0] == '.') ||
3183             (nmlen == 2 && name[0] == '.' && name[1] == '.'))
3184                 return (EEXIST);
3185 
3186         /* Only plain files are allowed in V_XATTRDIR. */
3187         if (dvp->v_flag & V_XATTRDIR)
3188                 return (EINVAL);
3189 
3190         if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
3191                 return (EINTR);
3192         smb_credinit(&scred, cr);
3193 
3194         /*





3195          * Require write access in the containing directory.
3196          */
3197         error = smbfs_access(dvp, VWRITE, 0, cr, ct);
3198         if (error)
3199                 goto out;
3200 
3201         error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
3202         if (error)
3203                 goto out;
3204 
3205         error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
3206         if (error)
3207                 goto out;
3208 
3209         smbfs_attr_touchdir(dnp);
3210 
3211         error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
3212         if (error)
3213                 goto out;
3214 


3317         dnp->n_flag |= NMODIFIED;
3318         mutex_exit(&np->r_statelock);
3319         smbfs_attr_touchdir(dnp);
3320         smbfs_rmhash(np);
3321 
3322 out:
3323         if (vp) {
3324                 if (vp_locked)
3325                         vn_vfsunlock(vp);
3326                 VN_RELE(vp);
3327         }
3328         smb_credrele(&scred);
3329         smbfs_rw_exit(&dnp->r_rwlock);
3330 
3331         return (error);
3332 }
3333 
3334 
3335 /* ARGSUSED */
3336 static int
3337 smbfs_symlink(vnode_t *dvp, char *lnm, struct vattr *tva, char *tnm, cred_t *cr,
3338         caller_context_t *ct, int flags)
3339 {
3340         /* Not yet... */
3341         return (ENOSYS);
3342 }
3343 
3344 
3345 /* ARGSUSED */
3346 static int
3347 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
3348         caller_context_t *ct, int flags)
3349 {
3350         struct smbnode  *np = VTOSMB(vp);
3351         int             error = 0;
3352         smbmntinfo_t    *smi;
3353 
3354         smi = VTOSMI(vp);
3355 
3356         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3357                 return (EIO);
3358 
3359         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3360                 return (EIO);
3361 
3362         /*
3363          * Require read access in the directory.
3364          */
3365         error = smbfs_access(vp, VREAD, 0, cr, ct);
3366         if (error)
3367                 return (error);
3368 
3369         ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
3370 
3371         /*
3372          * Todo readdir cache here

3373          *
3374          * I am serializing the entire readdir opreation
3375          * now since we have not yet implemented readdir
3376          * cache. This fix needs to be revisited once
3377          * we implement readdir cache.
3378          */
3379         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
3380                 return (EINTR);
3381 
3382         error = smbfs_readvdir(vp, uiop, cr, eofp, ct);
3383 
3384         smbfs_rw_exit(&np->r_lkserlock);
3385 
3386         return (error);
3387 }
3388 
3389 /* ARGSUSED */
3390 static int
3391 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
3392         caller_context_t *ct)


3586         }
3587         /*
3588          * If we encountered an error (i.e. "access denied")
3589          * from the FindFirst call, we will have copied out
3590          * the "." and ".." entries leaving offset == 2.
3591          * In that case, restore the original offset/resid
3592          * so the caller gets no data with the error.
3593          */
3594         if (error != 0 && offset == FIRST_DIROFS) {
3595                 uio->uio_loffset = save_offset;
3596                 uio->uio_resid = save_resid;
3597         }
3598         SMBVDEBUG("out: offset=%d, resid=%d\n",
3599             (int)uio->uio_offset, (int)uio->uio_resid);
3600 
3601         kmem_free(dp, dbufsiz);
3602         smb_credrele(&scred);
3603         return (error);
3604 }
3605 
3606 /*
3607  * Here NFS has: nfs3_bio
3608  * See smbfs_bio above.
3609  */
3610 
3611 /* ARGSUSED */
3612 static int
3613 smbfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
3614 {
3615         return (ENOSYS);
3616 }
3617 
3618 
3619 /*
3620  * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK
3621  * are optional functions that are called by:
3622  *    getdents, before/after VOP_READDIR
3623  *    pread, before/after ... VOP_READ
3624  *    pwrite, before/after ... VOP_WRITE
3625  *    (other places)
3626  *
3627  * Careful here: None of the above check for any
3628  * error returns from VOP_RWLOCK / VOP_RWUNLOCK!
3629  * In fact, the return value from _rwlock is NOT
3630  * an error code, but V_WRITELOCK_TRUE / _FALSE.
3631  *
3632  * Therefore, it's up to _this_ code to make sure
3633  * the lock state remains balanced, which means
3634  * we can't "bail out" on interrupts, etc.
3635  */
3636 
3637 /* ARGSUSED2 */
3638 static int


3672                 return (EPERM);
3673 
3674         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3675                 return (EIO);
3676 
3677         /*
3678          * Because we stuff the readdir cookie into the offset field
3679          * someone may attempt to do an lseek with the cookie which
3680          * we want to succeed.
3681          */
3682         if (vp->v_type == VDIR)
3683                 return (0);
3684 
3685         /* Like NFS3, just check for 63-bit overflow. */
3686         if (*noffp < 0)
3687                 return (EINVAL);
3688 
3689         return (0);
3690 }
3691 
3692 /* mmap support ******************************************************** */
3693 
3694 #ifdef DEBUG
3695 static int smbfs_lostpage = 0;  /* number of times we lost original page */
3696 #endif
3697 
3698 /*
3699  * Return all the pages from [off..off+len) in file
3700  * Like nfs3_getpage
3701  */
3702 /* ARGSUSED */
3703 static int
3704 smbfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
3705         page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
3706         enum seg_rw rw, cred_t *cr, caller_context_t *ct)
3707 {
3708         smbnode_t       *np;
3709         smbmntinfo_t    *smi;
3710         int             error;
3711 
3712         np = VTOSMB(vp);
3713         smi = VTOSMI(vp);
3714 
3715         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3716                 return (EIO);
3717 
3718         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3719                 return (EIO);
3720 
3721         if (vp->v_flag & VNOMAP)
3722                 return (ENOSYS);
3723 
3724         if (protp != NULL)
3725                 *protp = PROT_ALL;
3726 
3727         /*
3728          * Now valididate that the caches are up to date.
3729          */
3730         error = smbfs_validate_caches(vp, cr);
3731         if (error)
3732                 return (error);
3733 
3734 retry:
3735         mutex_enter(&np->r_statelock);
3736 
3737         /*
3738          * Don't create dirty pages faster than they
3739          * can be cleaned ... (etc. see nfs)
3740          *
3741          * Here NFS also tests:
3742          *  (mi->mi_max_threads != 0 &&
3743          *  rp->r_awcount > 2 * mi->mi_max_threads)
3744          */
3745         if (rw == S_CREATE) {
3746                 while (np->r_gcount > 0)
3747                         cv_wait(&np->r_cv, &np->r_statelock);
3748         }
3749 
3750         /*
3751          * If we are getting called as a side effect of a write
3752          * operation the local file size might not be extended yet.
3753          * In this case we want to be able to return pages of zeroes.
3754          */
3755         if (off + len > np->r_size + PAGEOFFSET && seg != segkmap) {
3756                 mutex_exit(&np->r_statelock);
3757                 return (EFAULT);                /* beyond EOF */
3758         }
3759 
3760         mutex_exit(&np->r_statelock);
3761 
3762         error = pvn_getpages(smbfs_getapage, vp, off, len, protp,
3763             pl, plsz, seg, addr, rw, cr);
3764 
3765         switch (error) {
3766         case SMBFS_EOF:
3767                 smbfs_purge_caches(vp, cr);
3768                 goto retry;
3769         case ESTALE:
3770                 /*
3771                  * Here NFS has: PURGE_STALE_FH(error, vp, cr);
3772                  * In-line here as we only use it once.
3773                  */
3774                 mutex_enter(&np->r_statelock);
3775                 np->r_flags |= RSTALE;
3776                 if (!np->r_error)
3777                         np->r_error = (error);
3778                 mutex_exit(&np->r_statelock);
3779                 if (vn_has_cached_data(vp))
3780                         smbfs_invalidate_pages(vp, (u_offset_t)0, cr);
3781                 smbfs_purge_caches(vp, cr);
3782                 break;
3783         default:
3784                 break;
3785         }
3786 
3787         return (error);
3788 }
3789 
3790 /*
3791  * Called from pvn_getpages to get a particular page.
3792  * Like nfs3_getapage
3793  */
3794 /* ARGSUSED */
3795 static int
3796 smbfs_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp,
3797         page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
3798         enum seg_rw rw, cred_t *cr)
3799 {
3800         smbnode_t       *np;
3801         smbmntinfo_t   *smi;
3802 
3803         uint_t          bsize;
3804         struct buf      *bp;
3805         page_t          *pp;
3806         u_offset_t      lbn;
3807         u_offset_t      io_off;
3808         u_offset_t      blkoff;
3809         size_t          io_len;
3810         uint_t blksize;
3811         int error;
3812         /* int readahead; */
3813         int readahead_issued = 0;
3814         /* int ra_window; * readahead window */
3815         page_t *pagefound;
3816 
3817         np = VTOSMB(vp);
3818         smi = VTOSMI(vp);
3819 
3820         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3821                 return (EIO);
3822 
3823         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3824                 return (EIO);
3825 
3826         bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
3827 
3828 reread:
3829         bp = NULL;
3830         pp = NULL;
3831         pagefound = NULL;
3832 
3833         if (pl != NULL)
3834                 pl[0] = NULL;
3835 
3836         error = 0;
3837         lbn = off / bsize;
3838         blkoff = lbn * bsize;
3839 
3840         /*
3841          * NFS queues up readahead work here.
3842          */
3843 
3844 again:
3845         if ((pagefound = page_exists(vp, off)) == NULL) {
3846                 if (pl == NULL) {
3847                         (void) 0; /* Todo: smbfs_async_readahead(); */
3848                 } else if (rw == S_CREATE) {
3849                         /*
3850                          * Block for this page is not allocated, or the offset
3851                          * is beyond the current allocation size, or we're
3852                          * allocating a swap slot and the page was not found,
3853                          * so allocate it and return a zero page.
3854                          */
3855                         if ((pp = page_create_va(vp, off,
3856                             PAGESIZE, PG_WAIT, seg, addr)) == NULL)
3857                                 cmn_err(CE_PANIC, "smbfs_getapage: page_create");
3858                         io_len = PAGESIZE;
3859                         mutex_enter(&np->r_statelock);
3860                         np->r_nextr = off + PAGESIZE;
3861                         mutex_exit(&np->r_statelock);
3862                 } else {
3863                         /*
3864                          * Need to go to server to get a BLOCK, exception to
3865                          * that being while reading at offset = 0 or doing
3866                          * random i/o, in that case read only a PAGE.
3867                          */
3868                         mutex_enter(&np->r_statelock);
3869                         if (blkoff < np->r_size &&
3870                             blkoff + bsize >= np->r_size) {
3871                                 /*
3872                                  * If only a block or less is left in
3873                                  * the file, read all that is remaining.
3874                                  */
3875                                 if (np->r_size <= off) {
3876                                         /*
3877                                          * Trying to access beyond EOF,
3878                                          * set up to get at least one page.
3879                                          */
3880                                         blksize = off + PAGESIZE - blkoff;
3881                                 } else
3882                                         blksize = np->r_size - blkoff;
3883                         } else if ((off == 0) ||
3884                             (off != np->r_nextr && !readahead_issued)) {
3885                                 blksize = PAGESIZE;
3886                                 blkoff = off; /* block = page here */
3887                         } else
3888                                 blksize = bsize;
3889                         mutex_exit(&np->r_statelock);
3890 
3891                         pp = pvn_read_kluster(vp, off, seg, addr, &io_off,
3892                             &io_len, blkoff, blksize, 0);
3893 
3894                         /*
3895                          * Some other thread has entered the page,
3896                          * so just use it.
3897                          */
3898                         if (pp == NULL)
3899                                 goto again;
3900 
3901                         /*
3902                          * Now round the request size up to page boundaries.
3903                          * This ensures that the entire page will be
3904                          * initialized to zeroes if EOF is encountered.
3905                          */
3906                         io_len = ptob(btopr(io_len));
3907 
3908                         bp = pageio_setup(pp, io_len, vp, B_READ);
3909                         ASSERT(bp != NULL);
3910 
3911                         /*
3912                          * pageio_setup should have set b_addr to 0.  This
3913                          * is correct since we want to do I/O on a page
3914                          * boundary.  bp_mapin will use this addr to calculate
3915                          * an offset, and then set b_addr to the kernel virtual
3916                          * address it allocated for us.
3917                          */
3918                         ASSERT(bp->b_un.b_addr == 0);
3919 
3920                         bp->b_edev = 0;
3921                         bp->b_dev = 0;
3922                         bp->b_lblkno = lbtodb(io_off);
3923                         bp->b_file = vp;
3924                         bp->b_offset = (offset_t)off;
3925                         bp_mapin(bp);
3926 
3927                         /*
3928                          * If doing a write beyond what we believe is EOF,
3929                          * don't bother trying to read the pages from the
3930                          * server, we'll just zero the pages here.  We
3931                          * don't check that the rw flag is S_WRITE here
3932                          * because some implementations may attempt a
3933                          * read access to the buffer before copying data.
3934                          */
3935                         mutex_enter(&np->r_statelock);
3936                         if (io_off >= np->r_size && seg == segkmap) {
3937                                 mutex_exit(&np->r_statelock);
3938                                 bzero(bp->b_un.b_addr, io_len);
3939                         } else {
3940                                 mutex_exit(&np->r_statelock);
3941                                 error = smbfs_bio(bp, 0, cr);
3942                         }
3943 
3944                         /*
3945                          * Unmap the buffer before freeing it.
3946                          */
3947                         bp_mapout(bp);
3948                         pageio_done(bp);
3949 
3950                         /* Here NFS3 updates all pp->p_fsdata */
3951 
3952                         if (error == SMBFS_EOF) {
3953                                 /*
3954                                  * If doing a write system call just return
3955                                  * zeroed pages, else user tried to get pages
3956                                  * beyond EOF, return error.  We don't check
3957                                  * that the rw flag is S_WRITE here because
3958                                  * some implementations may attempt a read
3959                                  * access to the buffer before copying data.
3960                                  */
3961                                 if (seg == segkmap)
3962                                         error = 0;
3963                                 else
3964                                         error = EFAULT;
3965                         }
3966 
3967                         if (!readahead_issued && !error) {
3968                                 mutex_enter(&np->r_statelock);
3969                                 np->r_nextr = io_off + io_len;
3970                                 mutex_exit(&np->r_statelock);
3971                         }
3972                 }
3973         }
3974 
3975         if (pl == NULL)
3976                 return (error);
3977 
3978         if (error) {
3979                 if (pp != NULL)
3980                         pvn_read_done(pp, B_ERROR);
3981                 return (error);
3982         }
3983 
3984         if (pagefound) {
3985                 se_t se = (rw == S_CREATE ? SE_EXCL : SE_SHARED);
3986 
3987                 /*
3988                  * Page exists in the cache, acquire the appropriate lock.
3989                  * If this fails, start all over again.
3990                  */
3991                 if ((pp = page_lookup(vp, off, se)) == NULL) {
3992 #ifdef DEBUG
3993                         smbfs_lostpage++;
3994 #endif
3995                         goto reread;
3996                 }
3997                 pl[0] = pp;
3998                 pl[1] = NULL;
3999                 return (0);
4000         }
4001 
4002         if (pp != NULL)
4003                 pvn_plist_init(pp, pl, plsz, off, io_len, rw);
4004 
4005         return (error);
4006 }
4007 
4008 /*
4009  * Here NFS has: nfs3_readahead
4010  * No read-ahead in smbfs yet.
4011  */
4012 
4013 /*
4014  * Flags are composed of {B_INVAL, B_FREE, B_DONTNEED, B_FORCE}
4015  * If len == 0, do from off to EOF.
4016  *
4017  * The normal cases should be len == 0 && off == 0 (entire vp list),
4018  * len == MAXBSIZE (from segmap_release actions), and len == PAGESIZE
4019  * (from pageout).
4020  *
4021  * Like nfs3_putpage + nfs_putpages
4022  */
4023 /* ARGSUSED */
4024 static int
4025 smbfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
4026         caller_context_t *ct)
4027 {
4028         smbnode_t *np;
4029         smbmntinfo_t *smi;
4030         page_t *pp;
4031         u_offset_t eoff;
4032         u_offset_t io_off;
4033         size_t io_len;
4034         int error;
4035         int rdirty;
4036         int err;
4037 
4038         np = VTOSMB(vp);
4039         smi = VTOSMI(vp);
4040 
4041         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
4042                 return (EIO);
4043 
4044         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
4045                 return (EIO);
4046 
4047         if (vp->v_flag & VNOMAP)
4048                 return (ENOSYS);
4049 
4050         /* Here NFS does rp->r_count (++/--) stuff. */
4051 
4052         /* Beginning of code from nfs_putpages. */
4053 
4054         if (!vn_has_cached_data(vp))
4055                 return (0);
4056 
4057         /*
4058          * If ROUTOFSPACE is set, then all writes turn into B_INVAL
4059          * writes.  B_FORCE is set to force the VM system to actually
4060          * invalidate the pages, even if the i/o failed.  The pages
4061          * need to get invalidated because they can't be written out
4062          * because there isn't any space left on either the server's
4063          * file system or in the user's disk quota.  The B_FREE bit
4064          * is cleared to avoid confusion as to whether this is a
4065          * request to place the page on the freelist or to destroy
4066          * it.
4067          */
4068         if ((np->r_flags & ROUTOFSPACE) ||
4069             (vp->v_vfsp->vfs_flag & VFS_UNMOUNTED))
4070                 flags = (flags & ~B_FREE) | B_INVAL | B_FORCE;
4071 
4072         if (len == 0) {
4073                 /*
4074                  * If doing a full file synchronous operation, then clear
4075                  * the RDIRTY bit.  If a page gets dirtied while the flush
4076                  * is happening, then RDIRTY will get set again.  The
4077                  * RDIRTY bit must get cleared before the flush so that
4078                  * we don't lose this information.
4079                  *
4080                  * NFS has B_ASYNC vs sync stuff here.
4081                  */
4082                 if (off == (u_offset_t)0 &&
4083                     (np->r_flags & RDIRTY)) {
4084                         mutex_enter(&np->r_statelock);
4085                         rdirty = (np->r_flags & RDIRTY);
4086                         np->r_flags &= ~RDIRTY;
4087                         mutex_exit(&np->r_statelock);
4088                 } else
4089                         rdirty = 0;
4090 
4091                 /*
4092                  * Search the entire vp list for pages >= off, and flush
4093                  * the dirty pages.
4094                  */
4095                 error = pvn_vplist_dirty(vp, off, smbfs_putapage,
4096                     flags, cr);
4097 
4098                 /*
4099                  * If an error occurred and the file was marked as dirty
4100                  * before and we aren't forcibly invalidating pages, then
4101                  * reset the RDIRTY flag.
4102                  */
4103                 if (error && rdirty &&
4104                     (flags & (B_INVAL | B_FORCE)) != (B_INVAL | B_FORCE)) {
4105                         mutex_enter(&np->r_statelock);
4106                         np->r_flags |= RDIRTY;
4107                         mutex_exit(&np->r_statelock);
4108                 }
4109         } else {
4110                 /*
4111                  * Do a range from [off...off + len) looking for pages
4112                  * to deal with.
4113                  */
4114                 error = 0;
4115                 io_len = 1; /* quiet warnings */
4116                 eoff = off + len;
4117 
4118                 for (io_off = off; io_off < eoff; io_off += io_len) {
4119                         mutex_enter(&np->r_statelock);
4120                         if (io_off >= np->r_size) {
4121                                 mutex_exit(&np->r_statelock);
4122                                 break;
4123                         }
4124                         mutex_exit(&np->r_statelock);
4125                         /*
4126                          * If we are not invalidating, synchronously
4127                          * freeing or writing pages use the routine
4128                          * page_lookup_nowait() to prevent reclaiming
4129                          * them from the free list.
4130                          */
4131                         if ((flags & B_INVAL) || !(flags & B_ASYNC)) {
4132                                 pp = page_lookup(vp, io_off,
4133                                     (flags & (B_INVAL | B_FREE)) ?
4134                                     SE_EXCL : SE_SHARED);
4135                         } else {
4136                                 pp = page_lookup_nowait(vp, io_off,
4137                                     (flags & B_FREE) ? SE_EXCL : SE_SHARED);
4138                         }
4139 
4140                         if (pp == NULL || !pvn_getdirty(pp, flags))
4141                                 io_len = PAGESIZE;
4142                         else {
4143                                 err = smbfs_putapage(vp, pp, &io_off,
4144                                     &io_len, flags, cr);
4145                                 if (!error)
4146                                         error = err;
4147                                 /*
4148                                  * "io_off" and "io_len" are returned as
4149                                  * the range of pages we actually wrote.
4150                                  * This allows us to skip ahead more quickly
4151                                  * since several pages may've been dealt
4152                                  * with by this iteration of the loop.
4153                                  */
4154                         }
4155                 }
4156         }
4157 
4158         return (error);
4159 }
4160 
4161 /*
4162  * Write out a single page, possibly klustering adjacent dirty pages.
4163  *
4164  * Like nfs3_putapage / nfs3_sync_putapage
4165  */
4166 static int
4167 smbfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
4168         int flags, cred_t *cr)
4169 {
4170         smbnode_t *np;
4171         u_offset_t io_off;
4172         u_offset_t lbn_off;
4173         u_offset_t lbn;
4174         size_t io_len;
4175         uint_t bsize;
4176         int error;
4177 
4178         np = VTOSMB(vp);
4179 
4180         ASSERT(!vn_is_readonly(vp));
4181 
4182         bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
4183         lbn = pp->p_offset / bsize;
4184         lbn_off = lbn * bsize;
4185 
4186         /*
4187          * Find a kluster that fits in one block, or in
4188          * one page if pages are bigger than blocks.  If
4189          * there is less file space allocated than a whole
4190          * page, we'll shorten the i/o request below.
4191          */
4192         pp = pvn_write_kluster(vp, pp, &io_off, &io_len, lbn_off,
4193             roundup(bsize, PAGESIZE), flags);
4194 
4195         /*
4196          * pvn_write_kluster shouldn't have returned a page with offset
4197          * behind the original page we were given.  Verify that.
4198          */
4199         ASSERT((pp->p_offset / bsize) >= lbn);
4200 
4201         /*
4202          * Now pp will have the list of kept dirty pages marked for
4203          * write back.  It will also handle invalidation and freeing
4204          * of pages that are not dirty.  Check for page length rounding
4205          * problems.
4206          */
4207         if (io_off + io_len > lbn_off + bsize) {
4208                 ASSERT((io_off + io_len) - (lbn_off + bsize) < PAGESIZE);
4209                 io_len = lbn_off + bsize - io_off;
4210         }
4211         /*
4212          * The RMODINPROGRESS flag makes sure that smbfs_bio() sees a
4213          * consistent value of r_size. RMODINPROGRESS is set in writerp().
4214          * When RMODINPROGRESS is set it indicates that a uiomove() is in
4215          * progress and the r_size has not been made consistent with the
4216          * new size of the file. When the uiomove() completes the r_size is
4217          * updated and the RMODINPROGRESS flag is cleared.
4218          *
4219          * The RMODINPROGRESS flag makes sure that smbfs_bio() sees a
4220          * consistent value of r_size. Without this handshaking, it is
4221          * possible that smbfs_bio() picks  up the old value of r_size
4222          * before the uiomove() in writerp() completes. This will result
4223          * in the write through smbfs_bio() being dropped.
4224          *
4225          * More precisely, there is a window between the time the uiomove()
4226          * completes and the time the r_size is updated. If a VOP_PUTPAGE()
4227          * operation intervenes in this window, the page will be picked up,
4228          * because it is dirty (it will be unlocked, unless it was
4229          * pagecreate'd). When the page is picked up as dirty, the dirty
4230          * bit is reset (pvn_getdirty()). In smbfs_write(), r_size is
4231          * checked. This will still be the old size. Therefore the page will
4232          * not be written out. When segmap_release() calls VOP_PUTPAGE(),
4233          * the page will be found to be clean and the write will be dropped.
4234          */
4235         if (np->r_flags & RMODINPROGRESS) {
4236                 mutex_enter(&np->r_statelock);
4237                 if ((np->r_flags & RMODINPROGRESS) &&
4238                     np->r_modaddr + MAXBSIZE > io_off &&
4239                     np->r_modaddr < io_off + io_len) {
4240                         page_t *plist;
4241                         /*
4242                          * A write is in progress for this region of the file.
4243                          * If we did not detect RMODINPROGRESS here then this
4244                          * path through smbfs_putapage() would eventually go to
4245                          * smbfs_bio() and may not write out all of the data
4246                          * in the pages. We end up losing data. So we decide
4247                          * to set the modified bit on each page in the page
4248                          * list and mark the rnode with RDIRTY. This write
4249                          * will be restarted at some later time.
4250                          */
4251                         plist = pp;
4252                         while (plist != NULL) {
4253                                 pp = plist;
4254                                 page_sub(&plist, pp);
4255                                 hat_setmod(pp);
4256                                 page_io_unlock(pp);
4257                                 page_unlock(pp);
4258                         }
4259                         np->r_flags |= RDIRTY;
4260                         mutex_exit(&np->r_statelock);
4261                         if (offp)
4262                                 *offp = io_off;
4263                         if (lenp)
4264                                 *lenp = io_len;
4265                         return (0);
4266                 }
4267                 mutex_exit(&np->r_statelock);
4268         }
4269 
4270         /*
4271          * NFS handles (flags & B_ASYNC) here...
4272          * (See nfs_async_putapage())
4273          *
4274          * This code section from: nfs3_sync_putapage()
4275          */
4276 
4277         flags |= B_WRITE;
4278 
4279         error = smbfs_rdwrlbn(vp, pp, io_off, io_len, flags, cr);
4280 
4281         if ((error == ENOSPC || error == EDQUOT || error == EFBIG ||
4282             error == EACCES) &&
4283             (flags & (B_INVAL|B_FORCE)) != (B_INVAL|B_FORCE)) {
4284                 if (!(np->r_flags & ROUTOFSPACE)) {
4285                         mutex_enter(&np->r_statelock);
4286                         np->r_flags |= ROUTOFSPACE;
4287                         mutex_exit(&np->r_statelock);
4288                 }
4289                 flags |= B_ERROR;
4290                 pvn_write_done(pp, flags);
4291                 /*
4292                  * If this was not an async thread, then try again to
4293                  * write out the pages, but this time, also destroy
4294                  * them whether or not the write is successful.  This
4295                  * will prevent memory from filling up with these
4296                  * pages and destroying them is the only alternative
4297                  * if they can't be written out.
4298                  *
4299                  * Don't do this if this is an async thread because
4300                  * when the pages are unlocked in pvn_write_done,
4301                  * some other thread could have come along, locked
4302                  * them, and queued for an async thread.  It would be
4303                  * possible for all of the async threads to be tied
4304                  * up waiting to lock the pages again and they would
4305                  * all already be locked and waiting for an async
4306                  * thread to handle them.  Deadlock.
4307                  */
4308                 if (!(flags & B_ASYNC)) {
4309                         error = smbfs_putpage(vp, io_off, io_len,
4310                             B_INVAL | B_FORCE, cr, NULL);
4311                 }
4312         } else {
4313                 if (error)
4314                         flags |= B_ERROR;
4315                 else if (np->r_flags & ROUTOFSPACE) {
4316                         mutex_enter(&np->r_statelock);
4317                         np->r_flags &= ~ROUTOFSPACE;
4318                         mutex_exit(&np->r_statelock);
4319                 }
4320                 pvn_write_done(pp, flags);
4321         }
4322 
4323         /* Now more code from: nfs3_putapage */
4324 
4325         if (offp)
4326                 *offp = io_off;
4327         if (lenp)
4328                 *lenp = io_len;
4329 
4330         return (error);
4331 }
4332 
4333 /*
4334  * NFS has this in nfs_client.c (shared by v2,v3,...)
4335  * We have it here so smbfs_putapage can be file scope.
4336  */
4337 void
4338 smbfs_invalidate_pages(vnode_t *vp, u_offset_t off, cred_t *cr)
4339 {
4340         smbnode_t *np;
4341 
4342         np = VTOSMB(vp);
4343 
4344         mutex_enter(&np->r_statelock);
4345         while (np->r_flags & RTRUNCATE)
4346                 cv_wait(&np->r_cv, &np->r_statelock);
4347         np->r_flags |= RTRUNCATE;
4348 
4349         if (off == (u_offset_t)0) {
4350                 np->r_flags &= ~RDIRTY;
4351                 if (!(np->r_flags & RSTALE))
4352                         np->r_error = 0;
4353         }
4354         /* Here NFSv3 has np->r_truncaddr = off; */
4355         mutex_exit(&np->r_statelock);
4356 
4357         (void) pvn_vplist_dirty(vp, off, smbfs_putapage,
4358             B_INVAL | B_TRUNC, cr);
4359 
4360         mutex_enter(&np->r_statelock);
4361         np->r_flags &= ~RTRUNCATE;
4362         cv_broadcast(&np->r_cv);
4363         mutex_exit(&np->r_statelock);
4364 }
4365 
4366 /* Like nfs3_map */
4367 
4368 /* ARGSUSED */
4369 static int
4370 smbfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
4371         size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
4372         cred_t *cr, caller_context_t *ct)
4373 {
4374         segvn_crargs_t  vn_a;
4375         struct vattr    va;
4376         smbnode_t       *np;
4377         smbmntinfo_t    *smi;
4378         int             error;
4379 
4380         np = VTOSMB(vp);
4381         smi = VTOSMI(vp);
4382 
4383         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
4384                 return (EIO);
4385 
4386         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
4387                 return (EIO);
4388 
4389         if (vp->v_flag & VNOMAP)
4390                 return (ENOSYS);
4391 
4392         if (off < 0 || off + (ssize_t)len < 0)
4393                 return (ENXIO);
4394 
4395         if (vp->v_type != VREG)
4396                 return (ENODEV);
4397 
4398         /*
4399          * NFS does close-to-open consistency stuff here.
4400          * Just get (possibly cached) attributes.
4401          */
4402         va.va_mask = AT_ALL;
4403         if ((error = smbfsgetattr(vp, &va, cr)) != 0)
4404                 return (error);
4405 
4406         /*
4407          * Check to see if the vnode is currently marked as not cachable.
4408          * This means portions of the file are locked (through VOP_FRLOCK).
4409          * In this case the map request must be refused.  We use
4410          * rp->r_lkserlock to avoid a race with concurrent lock requests.
4411          */
4412         /*
4413          * Atomically increment r_inmap after acquiring r_rwlock. The
4414          * idea here is to acquire r_rwlock to block read/write and
4415          * not to protect r_inmap. r_inmap will inform smbfs_read/write()
4416          * that we are in smbfs_map(). Now, r_rwlock is acquired in order
4417          * and we can prevent the deadlock that would have occurred
4418          * when smbfs_addmap() would have acquired it out of order.
4419          *
4420          * Since we are not protecting r_inmap by any lock, we do not
4421          * hold any lock when we decrement it. We atomically decrement
4422          * r_inmap after we release r_lkserlock.  Note that rwlock is
4423          * re-entered as writer in smbfs_addmap (called via as_map).
4424          */
4425 
4426         if (smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, SMBINTR(vp)))
4427                 return (EINTR);
4428         atomic_inc_uint(&np->r_inmap);
4429         smbfs_rw_exit(&np->r_rwlock);
4430 
4431         if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) {
4432                 atomic_dec_uint(&np->r_inmap);
4433                 return (EINTR);
4434         }
4435 
4436         if (vp->v_flag & VNOCACHE) {
4437                 error = EAGAIN;
4438                 goto done;
4439         }
4440 
4441         /*
4442          * Don't allow concurrent locks and mapping if mandatory locking is
4443          * enabled.
4444          */
4445         if ((flk_has_remote_locks(vp) || smbfs_lm_has_sleep(vp)) &&
4446             MANDLOCK(vp, va.va_mode)) {
4447                 error = EAGAIN;
4448                 goto done;
4449         }
4450 
4451         as_rangelock(as);
4452         error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
4453         if (error != 0) {
4454                 as_rangeunlock(as);
4455                 goto done;
4456         }
4457 
4458         vn_a.vp = vp;
4459         vn_a.offset = off;
4460         vn_a.type = (flags & MAP_TYPE);
4461         vn_a.prot = (uchar_t)prot;
4462         vn_a.maxprot = (uchar_t)maxprot;
4463         vn_a.flags = (flags & ~MAP_TYPE);
4464         vn_a.cred = cr;
4465         vn_a.amp = NULL;
4466         vn_a.szc = 0;
4467         vn_a.lgrp_mem_policy_flags = 0;
4468 
4469         error = as_map(as, *addrp, len, segvn_create, &vn_a);
4470         as_rangeunlock(as);
4471 
4472 done:
4473         smbfs_rw_exit(&np->r_lkserlock);
4474         atomic_dec_uint(&np->r_inmap);
4475         return (error);
4476 }
4477 
4478 /* ARGSUSED */
4479 static int
4480 smbfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
4481         size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
4482         cred_t *cr, caller_context_t *ct)
4483 {
4484         smbnode_t *np = VTOSMB(vp);
4485         boolean_t inc_fidrefs = B_FALSE;
4486 
4487         /*
4488          * When r_mapcnt goes from zero to non-zero,
4489          * increment n_fidrefs
4490          */
4491         mutex_enter(&np->r_statelock);
4492         if (np->r_mapcnt == 0)
4493                 inc_fidrefs = B_TRUE;
4494         np->r_mapcnt += btopr(len);
4495         mutex_exit(&np->r_statelock);
4496 
4497         if (inc_fidrefs) {
4498                 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
4499                 np->n_fidrefs++;
4500                 smbfs_rw_exit(&np->r_lkserlock);
4501         }
4502 
4503         return (0);
4504 }
4505 
4506 /*
4507  * Use an address space callback to flush pages dirty pages after unmap,
4508  * which we can't do directly in smbfs_delmap due to locking issues.
4509  */
4510 typedef struct smbfs_delmap_args {
4511         vnode_t                 *vp;
4512         cred_t                  *cr;
4513         offset_t                off;
4514         caddr_t                 addr;
4515         size_t                  len;
4516         uint_t                  prot;
4517         uint_t                  maxprot;
4518         uint_t                  flags;
4519         boolean_t               dec_fidrefs;
4520 } smbfs_delmap_args_t;
4521 
4522 /* ARGSUSED */
4523 static int
4524 smbfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
4525         size_t len, uint_t prot, uint_t maxprot, uint_t flags,
4526         cred_t *cr, caller_context_t *ct)
4527 {
4528         smbnode_t *np = VTOSMB(vp);
4529         smbfs_delmap_args_t     *dmapp;
4530         int error;
4531 
4532         dmapp = kmem_zalloc(sizeof (*dmapp), KM_SLEEP);
4533 
4534         dmapp->vp = vp;
4535         dmapp->off = off;
4536         dmapp->addr = addr;
4537         dmapp->len = len;
4538         dmapp->prot = prot;
4539         dmapp->maxprot = maxprot;
4540         dmapp->flags = flags;
4541         dmapp->cr = cr;
4542         dmapp->dec_fidrefs = B_FALSE;
4543 
4544         /*
4545          * When r_mapcnt returns to zero, arrange for the
4546          * callback to decrement n_fidrefs
4547          */
4548         mutex_enter(&np->r_statelock);
4549         np->r_mapcnt -= btopr(len);
4550         ASSERT(np->r_mapcnt >= 0);
4551         if (np->r_mapcnt == 0)
4552                 dmapp->dec_fidrefs = B_TRUE;
4553         mutex_exit(&np->r_statelock);
4554 
4555         error = as_add_callback(as, smbfs_delmap_callback, dmapp,
4556             AS_UNMAP_EVENT, addr, len, KM_SLEEP);
4557         if (error != 0) {
4558                 /*
4559                  * So sad, no callback is coming. Can't flush pages
4560                  * in delmap (as locks).  Just handle n_fidrefs.
4561                  */
4562                 cmn_err(CE_NOTE, "smbfs_delmap(%p) "
4563                     "as_add_callback err=%d",
4564                     (void *)vp, error);
4565 
4566                 if (dmapp->dec_fidrefs) {
4567                         struct smb_cred scred;
4568 
4569                         (void) smbfs_rw_enter_sig(&np->r_lkserlock,
4570                             RW_WRITER, 0);
4571                         smb_credinit(&scred, dmapp->cr);
4572 
4573                         smbfs_rele_fid(np, &scred);
4574 
4575                         smb_credrele(&scred);
4576                         smbfs_rw_exit(&np->r_lkserlock);
4577                 }
4578                 kmem_free(dmapp, sizeof (*dmapp));
4579         }
4580 
4581         return (0);
4582 }
4583 
4584 /*
4585  * Remove some pages from an mmap'd vnode.  Flush any
4586  * dirty pages in the unmapped range.
4587  */
4588 /* ARGSUSED */
4589 static void
4590 smbfs_delmap_callback(struct as *as, void *arg, uint_t event)
4591 {
4592         vnode_t                 *vp;
4593         smbnode_t               *np;
4594         smbmntinfo_t            *smi;
4595         smbfs_delmap_args_t     *dmapp = arg;
4596 
4597         vp = dmapp->vp;
4598         np = VTOSMB(vp);
4599         smi = VTOSMI(vp);
4600 
4601         /* Decremented r_mapcnt in smbfs_delmap */
4602 
4603         /*
4604          * Initiate a page flush and potential commit if there are
4605          * pages, the file system was not mounted readonly, the segment
4606          * was mapped shared, and the pages themselves were writeable.
4607          *
4608          * mark RDIRTY here, will be used to check if a file is dirty when
4609          * unmount smbfs
4610          */
4611         if (vn_has_cached_data(vp) && !vn_is_readonly(vp) &&
4612             dmapp->flags == MAP_SHARED && (dmapp->maxprot & PROT_WRITE)) {
4613                 mutex_enter(&np->r_statelock);
4614                 np->r_flags |= RDIRTY;
4615                 mutex_exit(&np->r_statelock);
4616 
4617                 /*
4618                  * Need to finish the putpage before we
4619                  * close the OtW FID needed for I/O.
4620                  */
4621                 (void) smbfs_putpage(vp, dmapp->off, dmapp->len, 0,
4622                     dmapp->cr, NULL);
4623         }
4624 
4625         if ((np->r_flags & RDIRECTIO) || (smi->smi_flags & SMI_DIRECTIO))
4626                 (void) smbfs_putpage(vp, dmapp->off, dmapp->len,
4627                     B_INVAL, dmapp->cr, NULL);
4628 
4629         /*
4630          * If r_mapcnt went to zero, drop our FID ref now.
4631          * On the last fidref, this does an OtW close.
4632          */
4633         if (dmapp->dec_fidrefs) {
4634                 struct smb_cred scred;
4635 
4636                 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
4637                 smb_credinit(&scred, dmapp->cr);
4638 
4639                 smbfs_rele_fid(np, &scred);
4640 
4641                 smb_credrele(&scred);
4642                 smbfs_rw_exit(&np->r_lkserlock);
4643         }
4644 
4645         (void) as_delete_callback(as, arg);
4646         kmem_free(dmapp, sizeof (*dmapp));
4647 }
4648 
4649 /* No smbfs_pageio() or smbfs_dispose() ops. */
4650 
4651 /* misc. ******************************************************** */
4652 
4653 
4654 /*
4655  * XXX
4656  * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service.
4657  */
4658 static int
4659 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
4660         offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
4661         caller_context_t *ct)
4662 {
4663         if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
4664                 return (EIO);
4665 
4666         if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
4667                 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
4668         else
4669                 return (ENOSYS);
4670 }
4671 
4672 /*
4673  * Free storage space associated with the specified vnode.  The portion
4674  * to be freed is specified by bfp->l_start and bfp->l_len (already


4704          */
4705 
4706         error = convoff(vp, bfp, 0, offset);
4707         if (!error) {
4708                 ASSERT(bfp->l_start >= 0);
4709                 if (bfp->l_len == 0) {
4710                         struct vattr va;
4711 
4712                         /*
4713                          * ftruncate should not change the ctime and
4714                          * mtime if we truncate the file to its
4715                          * previous size.
4716                          */
4717                         va.va_mask = AT_SIZE;
4718                         error = smbfsgetattr(vp, &va, cr);
4719                         if (error || va.va_size == bfp->l_start)
4720                                 return (error);
4721                         va.va_mask = AT_SIZE;
4722                         va.va_size = bfp->l_start;
4723                         error = smbfssetattr(vp, &va, 0, cr);
4724                         /* SMBFS_VNEVENT... */
4725                 } else
4726                         error = EINVAL;
4727         }
4728 
4729         return (error);
4730 }
4731 
4732 
4733 /* ARGSUSED */
4734 static int
4735 smbfs_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
4736 {
4737 
4738         return (ENOSYS);
4739 }
4740 
4741 
4742 /* ARGSUSED */
4743 static int
4744 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
4745         caller_context_t *ct)
4746 {
4747         vfs_t *vfs;
4748         smbmntinfo_t *smi;
4749         struct smb_share *ssp;
4750 
4751         vfs = vp->v_vfsp;
4752         smi = VFTOSMI(vfs);
4753 
4754         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
4755                 return (EIO);
4756 
4757         if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
4758                 return (EIO);
4759 
4760         switch (cmd) {
4761         case _PC_FILESIZEBITS:
4762                 ssp = smi->smi_share;
4763                 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)


4898         return (error);
4899 }
4900 
4901 
4902 /*
4903  * XXX
4904  * This op should eventually support PSARC 2007/268.
4905  */
4906 static int
4907 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
4908         caller_context_t *ct)
4909 {
4910         if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
4911                 return (EIO);
4912 
4913         if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
4914                 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
4915         else
4916                 return (ENOSYS);
4917 }
4918 
4919 
4920 /*
4921  * Most unimplemented ops will return ENOSYS because of fs_nosys().
4922  * The only ops where that won't work are ACCESS (due to open(2)
4923  * failures) and ... (anything else left?)
4924  */
4925 const fs_operation_def_t smbfs_vnodeops_template[] = {
4926         VOPNAME_OPEN,           { .vop_open = smbfs_open },
4927         VOPNAME_CLOSE,          { .vop_close = smbfs_close },
4928         VOPNAME_READ,           { .vop_read = smbfs_read },
4929         VOPNAME_WRITE,          { .vop_write = smbfs_write },
4930         VOPNAME_IOCTL,          { .vop_ioctl = smbfs_ioctl },
4931         VOPNAME_GETATTR,        { .vop_getattr = smbfs_getattr },
4932         VOPNAME_SETATTR,        { .vop_setattr = smbfs_setattr },
4933         VOPNAME_ACCESS,         { .vop_access = smbfs_access },
4934         VOPNAME_LOOKUP,         { .vop_lookup = smbfs_lookup },
4935         VOPNAME_CREATE,         { .vop_create = smbfs_create },
4936         VOPNAME_REMOVE,         { .vop_remove = smbfs_remove },
4937         VOPNAME_LINK,           { .vop_link = smbfs_link },
4938         VOPNAME_RENAME,         { .vop_rename = smbfs_rename },
4939         VOPNAME_MKDIR,          { .vop_mkdir = smbfs_mkdir },
4940         VOPNAME_RMDIR,          { .vop_rmdir = smbfs_rmdir },
4941         VOPNAME_READDIR,        { .vop_readdir = smbfs_readdir },
4942         VOPNAME_SYMLINK,        { .vop_symlink = smbfs_symlink },
4943         VOPNAME_READLINK,       { .vop_readlink = smbfs_readlink },
4944         VOPNAME_FSYNC,          { .vop_fsync = smbfs_fsync },
4945         VOPNAME_INACTIVE,       { .vop_inactive = smbfs_inactive },
4946         VOPNAME_FID,            { .vop_fid = smbfs_fid },
4947         VOPNAME_RWLOCK,         { .vop_rwlock = smbfs_rwlock },
4948         VOPNAME_RWUNLOCK,       { .vop_rwunlock = smbfs_rwunlock },
4949         VOPNAME_SEEK,           { .vop_seek = smbfs_seek },
4950         VOPNAME_FRLOCK,         { .vop_frlock = smbfs_frlock },
4951         VOPNAME_SPACE,          { .vop_space = smbfs_space },
4952         VOPNAME_REALVP,         { .vop_realvp = smbfs_realvp },
4953         VOPNAME_GETPAGE,        { .vop_getpage = smbfs_getpage },
4954         VOPNAME_PUTPAGE,        { .vop_putpage = smbfs_putpage },
4955         VOPNAME_MAP,            { .vop_map = smbfs_map },
4956         VOPNAME_ADDMAP,         { .vop_addmap = smbfs_addmap },
4957         VOPNAME_DELMAP,         { .vop_delmap = smbfs_delmap },
4958         VOPNAME_DUMP,           { .error = fs_nosys }, /* smbfs_dump, */
4959         VOPNAME_PATHCONF,       { .vop_pathconf = smbfs_pathconf },
4960         VOPNAME_PAGEIO,         { .error = fs_nosys }, /* smbfs_pageio, */
4961         VOPNAME_SETSECATTR,     { .vop_setsecattr = smbfs_setsecattr },
4962         VOPNAME_GETSECATTR,     { .vop_getsecattr = smbfs_getsecattr },
4963         VOPNAME_SHRLOCK,        { .vop_shrlock = smbfs_shrlock },
4964 #ifdef  SMBFS_VNEVENT
4965         VOPNAME_VNEVENT,        { .vop_vnevent = fs_vnevent_support },
4966 #endif
4967         { NULL, NULL }
4968 };