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.
158 static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
159 caller_context_t *, int);
160 static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
161 caller_context_t *, int);
162 static int smbfs_rwlock(vnode_t *, int, caller_context_t *);
163 static void smbfs_rwunlock(vnode_t *, int, caller_context_t *);
164 static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
165 static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
166 struct flk_callback *, cred_t *, caller_context_t *);
167 static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
168 cred_t *, caller_context_t *);
169 static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
170 caller_context_t *);
171 static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
172 caller_context_t *);
173 static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
174 caller_context_t *);
175 static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
176 caller_context_t *);
177
178 /* Dummy function to use until correct function is ported in */
179 int noop_vnodeop() {
180 return (0);
181 }
182
183 struct vnodeops *smbfs_vnodeops = NULL;
184
185 /*
186 * Most unimplemented ops will return ENOSYS because of fs_nosys().
187 * The only ops where that won't work are ACCESS (due to open(2)
188 * failures) and ... (anything else left?)
189 */
190 const fs_operation_def_t smbfs_vnodeops_template[] = {
191 { VOPNAME_OPEN, { .vop_open = smbfs_open } },
192 { VOPNAME_CLOSE, { .vop_close = smbfs_close } },
193 { VOPNAME_READ, { .vop_read = smbfs_read } },
194 { VOPNAME_WRITE, { .vop_write = smbfs_write } },
195 { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } },
196 { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } },
197 { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } },
198 { VOPNAME_ACCESS, { .vop_access = smbfs_access } },
199 { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } },
200 { VOPNAME_CREATE, { .vop_create = smbfs_create } },
201 { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } },
202 { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */
203 { VOPNAME_RENAME, { .vop_rename = smbfs_rename } },
204 { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } },
205 { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } },
206 { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } },
207 { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */
208 { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */
209 { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } },
210 { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } },
211 { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */
212 { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } },
213 { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } },
214 { VOPNAME_SEEK, { .vop_seek = smbfs_seek } },
215 { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } },
216 { VOPNAME_SPACE, { .vop_space = smbfs_space } },
217 { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */
218 { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */
219 { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */
220 { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */
221 { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */
222 { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */
223 { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */
224 { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } },
225 { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */
226 { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } },
227 { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } },
228 { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } },
229 { NULL, NULL }
230 };
231
232 /*
233 * XXX
234 * When new and relevant functionality is enabled, we should be
235 * calling vfs_set_feature() to inform callers that pieces of
236 * functionality are available, per PSARC 2007/227.
237 */
238 /* ARGSUSED */
239 static int
240 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
241 {
242 smbnode_t *np;
469 }
470
471 /*
472 * This (passed in) count is the ref. count from the
473 * user's file_t before the closef call (fio.c).
474 * We only care when the reference goes away.
475 */
476 if (count > 1)
477 return (0);
478
479 /*
480 * Decrement the reference count for the FID
481 * and possibly do the OtW close.
482 *
483 * Exclusive lock for modifying n_fid stuff.
484 * Don't want this one ever interruptible.
485 */
486 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
487 smb_credinit(&scred, cr);
488
489 smbfs_rele_fid(np, &scred);
490
491 smb_credrele(&scred);
492 smbfs_rw_exit(&np->r_lkserlock);
493
494 return (0);
495 }
496
497 /*
498 * Helper for smbfs_close. Decrement the reference count
499 * for an SMB-level file or directory ID, and when the last
500 * reference for the fid goes away, do the OtW close.
501 * Also called in smbfs_inactive (defensive cleanup).
502 */
503 static void
504 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
505 {
506 smb_share_t *ssp;
507 cred_t *oldcr;
508 struct smbfs_fctx *fctx;
509 int error;
558 }
559
560 /* Allow next open to use any v_type. */
561 np->n_ovtype = VNON;
562
563 /*
564 * Other "last close" stuff.
565 */
566 mutex_enter(&np->r_statelock);
567 if (np->n_flag & NATTRCHANGED)
568 smbfs_attrcache_rm_locked(np);
569 oldcr = np->r_cred;
570 np->r_cred = NULL;
571 mutex_exit(&np->r_statelock);
572 if (oldcr != NULL)
573 crfree(oldcr);
574 }
575
576 /* ARGSUSED */
577 static int
578 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
579 caller_context_t *ct)
580 {
581 struct smb_cred scred;
582 struct vattr va;
583 smbnode_t *np;
584 smbmntinfo_t *smi;
585 smb_share_t *ssp;
586 offset_t endoff;
587 ssize_t past_eof;
588 int error;
589
590 np = VTOSMB(vp);
591 smi = VTOSMI(vp);
592 ssp = smi->smi_share;
593
594 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
595 return (EIO);
596
597 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
598 return (EIO);
599
600 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
601
602 if (vp->v_type != VREG)
603 return (EISDIR);
604
605 if (uiop->uio_resid == 0)
606 return (0);
607
608 /*
609 * Like NFS3, just check for 63-bit overflow.
610 * Our SMB layer takes care to return EFBIG
611 * when it has to fallback to a 32-bit call.
612 */
613 endoff = uiop->uio_loffset + uiop->uio_resid;
614 if (uiop->uio_loffset < 0 || endoff < 0)
615 return (EINVAL);
616
617 /* get vnode attributes from server */
618 va.va_mask = AT_SIZE | AT_MTIME;
619 if (error = smbfsgetattr(vp, &va, cr))
620 return (error);
621
622 /* Update mtime with mtime from server here? */
623
624 /* if offset is beyond EOF, read nothing */
625 if (uiop->uio_loffset >= va.va_size)
626 return (0);
627
628 /*
629 * Limit the read to the remaining file size.
630 * Do this by temporarily reducing uio_resid
631 * by the amount the lies beyoned the EOF.
632 */
633 if (endoff > va.va_size) {
634 past_eof = (ssize_t)(endoff - va.va_size);
635 uiop->uio_resid -= past_eof;
636 } else
637 past_eof = 0;
638
639 /* Shared lock for n_fid use in smb_rwuio */
640 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
641 return (EINTR);
642 smb_credinit(&scred, cr);
643
644 /* After reconnect, n_fid is invalid */
645 if (np->n_vcgenid != ssp->ss_vcgenid)
646 error = ESTALE;
647 else
648 error = smb_rwuio(ssp, np->n_fid, UIO_READ,
649 uiop, &scred, smb_timo_read);
650
651 smb_credrele(&scred);
652 smbfs_rw_exit(&np->r_lkserlock);
653
654 /* undo adjustment of resid */
655 uiop->uio_resid += past_eof;
656
657 return (error);
658 }
659
660
661 /* ARGSUSED */
662 static int
663 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
664 caller_context_t *ct)
665 {
666 struct smb_cred scred;
667 struct vattr va;
668 smbnode_t *np;
669 smbmntinfo_t *smi;
670 smb_share_t *ssp;
671 offset_t endoff, limit;
672 ssize_t past_limit;
673 int error, timo;
674
675 np = VTOSMB(vp);
676 smi = VTOSMI(vp);
677 ssp = smi->smi_share;
678
679 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
680 return (EIO);
681
682 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
683 return (EIO);
684
685 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
686
687 if (vp->v_type != VREG)
688 return (EISDIR);
689
690 if (uiop->uio_resid == 0)
691 return (0);
692
693 /*
694 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
695 */
696 if (ioflag & (FAPPEND | FSYNC)) {
697 if (np->n_flag & NMODIFIED) {
698 smbfs_attrcache_remove(np);
699 /* XXX: smbfs_vinvalbuf? */
700 }
701 }
702 if (ioflag & FAPPEND) {
703 /*
704 * File size can be changed by another client
705 */
706 va.va_mask = AT_SIZE;
707 if (error = smbfsgetattr(vp, &va, cr))
708 return (error);
709 uiop->uio_loffset = va.va_size;
710 }
711
712 /*
713 * Like NFS3, just check for 63-bit overflow.
714 */
715 endoff = uiop->uio_loffset + uiop->uio_resid;
716 if (uiop->uio_loffset < 0 || endoff < 0)
717 return (EINVAL);
718
719 /*
720 * Check to make sure that the process will not exceed
721 * its limit on file size. It is okay to write up to
722 * the limit, but not beyond. Thus, the write which
723 * reaches the limit will be short and the next write
724 * will return an error.
725 *
726 * So if we're starting at or beyond the limit, EFBIG.
727 * Otherwise, temporarily reduce resid to the amount
728 * the falls after the limit.
729 */
730 limit = uiop->uio_llimit;
731 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
732 limit = MAXOFFSET_T;
733 if (uiop->uio_loffset >= limit)
734 return (EFBIG);
735 if (endoff > limit) {
736 past_limit = (ssize_t)(endoff - limit);
737 uiop->uio_resid -= past_limit;
738 } else
739 past_limit = 0;
740
741 /* Timeout: longer for append. */
742 timo = smb_timo_write;
743 if (endoff > np->r_size)
744 timo = smb_timo_append;
745
746 /* Shared lock for n_fid use in smb_rwuio */
747 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
748 return (EINTR);
749 smb_credinit(&scred, cr);
750
751 /* After reconnect, n_fid is invalid */
752 if (np->n_vcgenid != ssp->ss_vcgenid)
753 error = ESTALE;
754 else
755 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
756 uiop, &scred, timo);
757
758 if (error == 0) {
759 mutex_enter(&np->r_statelock);
760 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
761 if (uiop->uio_loffset > (offset_t)np->r_size)
762 np->r_size = (len_t)uiop->uio_loffset;
763 mutex_exit(&np->r_statelock);
764 if (ioflag & (FSYNC|FDSYNC)) {
765 /* Don't error the I/O if this fails. */
766 (void) smbfs_smb_flush(np, &scred);
767 }
768 }
769
770 smb_credrele(&scred);
771 smbfs_rw_exit(&np->r_lkserlock);
772
773 /* undo adjustment of resid */
774 uiop->uio_resid += past_limit;
775
776 return (error);
777 }
778
779
780 /* ARGSUSED */
781 static int
782 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
783 cred_t *cr, int *rvalp, caller_context_t *ct)
784 {
785 int error;
786 smbmntinfo_t *smi;
787
788 smi = VTOSMI(vp);
789
790 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
791 return (EIO);
792
793 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
794 return (EIO);
795
796 switch (cmd) {
797 /* First three from ZFS. XXX - need these? */
798
1348 switch (np->n_ovtype) {
1349 case VNON:
1350 /* not open (OK) */
1351 break;
1352
1353 case VDIR:
1354 if (np->n_dirrefs == 0)
1355 break;
1356 SMBVDEBUG("open dir: refs %d path %s\n",
1357 np->n_dirrefs, np->n_rpath);
1358 /* Force last close. */
1359 np->n_dirrefs = 1;
1360 smbfs_rele_fid(np, &scred);
1361 break;
1362
1363 case VREG:
1364 if (np->n_fidrefs == 0)
1365 break;
1366 SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
1367 np->n_fidrefs, np->n_fid, np->n_rpath);
1368 /* Force last close. */
1369 np->n_fidrefs = 1;
1370 smbfs_rele_fid(np, &scred);
1371 break;
1372
1373 default:
1374 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
1375 np->n_ovtype = VNON;
1376 break;
1377 }
1378
1379 smb_credrele(&scred);
1380 smbfs_rw_exit(&np->r_lkserlock);
1381
1382 smbfs_addfree(np);
1383 }
1384
1385 /*
1386 * Remote file system operations having to do with directory manipulation.
1387 */
3093 return (error);
3094 }
3095
3096
3097 /*
3098 * XXX
3099 * This op should eventually support PSARC 2007/268.
3100 */
3101 static int
3102 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
3103 caller_context_t *ct)
3104 {
3105 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3106 return (EIO);
3107
3108 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3109 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3110 else
3111 return (ENOSYS);
3112 }
|
34
35 /*
36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37 */
38
39 #include <sys/systm.h>
40 #include <sys/cred.h>
41 #include <sys/vnode.h>
42 #include <sys/vfs.h>
43 #include <sys/filio.h>
44 #include <sys/uio.h>
45 #include <sys/dirent.h>
46 #include <sys/errno.h>
47 #include <sys/sunddi.h>
48 #include <sys/sysmacros.h>
49 #include <sys/kmem.h>
50 #include <sys/cmn_err.h>
51 #include <sys/vfs_opreg.h>
52 #include <sys/policy.h>
53
54 #include <sys/param.h>
55 #include <sys/vm.h>
56 #include <vm/seg_vn.h>
57 #include <vm/pvn.h>
58 #include <vm/as.h>
59 #include <vm/hat.h>
60 #include <vm/page.h>
61 #include <vm/seg.h>
62 #include <vm/seg_map.h>
63 #include <vm/seg_kmem.h>
64 #include <vm/seg_kpm.h>
65
66 #include <netsmb/smb_osdep.h>
67 #include <netsmb/smb.h>
68 #include <netsmb/smb_conn.h>
69 #include <netsmb/smb_subr.h>
70
71 #include <smbfs/smbfs.h>
72 #include <smbfs/smbfs_node.h>
73 #include <smbfs/smbfs_subr.h>
74
75 #include <sys/fs/smbfs_ioctl.h>
76 #include <fs/fs_subr.h>
77
78 /*
79 * We assign directory offsets like the NFS client, where the
80 * offset increments by _one_ after each directory entry.
81 * Further, the entries "." and ".." are always at offsets
82 * zero and one (respectively) and the "real" entries from
83 * the server appear at offsets starting with two. This
84 * macro is used to initialize the n_dirofs field after
85 * setting n_dirseq with a _findopen call.
170 static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
171 caller_context_t *, int);
172 static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
173 caller_context_t *, int);
174 static int smbfs_rwlock(vnode_t *, int, caller_context_t *);
175 static void smbfs_rwunlock(vnode_t *, int, caller_context_t *);
176 static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
177 static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
178 struct flk_callback *, cred_t *, caller_context_t *);
179 static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
180 cred_t *, caller_context_t *);
181 static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
182 caller_context_t *);
183 static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
184 caller_context_t *);
185 static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
186 caller_context_t *);
187 static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
188 caller_context_t *);
189
190 static int uio_page_mapin(uio_t *uiop, page_t *pp);
191
192 static void uio_page_mapout(uio_t *uiop, page_t *pp);
193
194 static int smbfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
195 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr,
196 caller_context_t *ct);
197
198 static int smbfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
199 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr,
200 caller_context_t *ct);
201
202 static int smbfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
203 size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr,
204 caller_context_t *ct);
205
206 static int smbfs_putpage(vnode_t *vp, offset_t off, size_t len, int flags,
207 cred_t *cr, caller_context_t *ct);
208
209 static int smbfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
210 int flags, cred_t *cr);
211
212 static int smbfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
213 page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
214 enum seg_rw rw, cred_t *cr, caller_context_t *ct);
215
216 static int smbfs_getapage(vnode_t *vp, u_offset_t off, size_t len,
217 uint_t *protp, page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
218 enum seg_rw rw, cred_t *cr);
219
220 static int writenp(smbnode_t *np, caddr_t base, int tcount, struct uio *uiop, int pgcreated);
221
222 /* Dummy function to use until correct function is ported in */
223 int noop_vnodeop() {
224 return (0);
225 }
226
227 struct vnodeops *smbfs_vnodeops = NULL;
228
229 /*
230 * Most unimplemented ops will return ENOSYS because of fs_nosys().
231 * The only ops where that won't work are ACCESS (due to open(2)
232 * failures) and ... (anything else left?)
233 */
234 const fs_operation_def_t smbfs_vnodeops_template[] = {
235 { VOPNAME_OPEN, { .vop_open = smbfs_open } },
236 { VOPNAME_CLOSE, { .vop_close = smbfs_close } },
237 { VOPNAME_READ, { .vop_read = smbfs_read } },
238 { VOPNAME_WRITE, { .vop_write = smbfs_write } },
239 { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } },
240 { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } },
241 { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } },
242 { VOPNAME_ACCESS, { .vop_access = smbfs_access } },
243 { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } },
244 { VOPNAME_CREATE, { .vop_create = smbfs_create } },
245 { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } },
246 { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */
247 { VOPNAME_RENAME, { .vop_rename = smbfs_rename } },
248 { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } },
249 { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } },
250 { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } },
251 { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */
252 { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */
253 { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } },
254 { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } },
255 { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */
256 { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } },
257 { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } },
258 { VOPNAME_SEEK, { .vop_seek = smbfs_seek } },
259 { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } },
260 { VOPNAME_SPACE, { .vop_space = smbfs_space } },
261 { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */
262 { VOPNAME_GETPAGE, { .vop_getpage = smbfs_getpage } }, /* smbfs_getpage, */
263 { VOPNAME_PUTPAGE, { .vop_putpage = smbfs_putpage } }, /* smbfs_putpage, */
264 { VOPNAME_MAP, { .vop_map = smbfs_map } }, /* smbfs_map, */
265 { VOPNAME_ADDMAP, { .vop_addmap = smbfs_addmap } }, /* smbfs_addmap, */
266 { VOPNAME_DELMAP, { .vop_delmap = smbfs_delmap } }, /* smbfs_delmap, */
267 { VOPNAME_DISPOSE, { .vop_dispose = fs_dispose}},
268 { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */
269 { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } },
270 { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */
271 { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } },
272 { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } },
273 { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } },
274 { NULL, NULL }
275 };
276
277 /*
278 * XXX
279 * When new and relevant functionality is enabled, we should be
280 * calling vfs_set_feature() to inform callers that pieces of
281 * functionality are available, per PSARC 2007/227.
282 */
283 /* ARGSUSED */
284 static int
285 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
286 {
287 smbnode_t *np;
514 }
515
516 /*
517 * This (passed in) count is the ref. count from the
518 * user's file_t before the closef call (fio.c).
519 * We only care when the reference goes away.
520 */
521 if (count > 1)
522 return (0);
523
524 /*
525 * Decrement the reference count for the FID
526 * and possibly do the OtW close.
527 *
528 * Exclusive lock for modifying n_fid stuff.
529 * Don't want this one ever interruptible.
530 */
531 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
532 smb_credinit(&scred, cr);
533
534 /*
535 * If FID ref. count is 1 and count of mmaped pages isn't 0,
536 * we won't call smbfs_rele_fid(), because it will result in the otW close.
537 * The count of mapped pages isn't 0, which means the mapped pages
538 * possibly will be accessed after close(), we should keep the FID valid,
539 * i.e., dont do the otW close.
540 * Dont worry that FID will be leaked, because when the
541 * vnode's count becomes 0, smbfs_inactive() will
542 * help us release FID and eventually do the otW close.
543 */
544 if (np->n_fidrefs > 1) {
545 smbfs_rele_fid(np, &scred);
546 } else if (np->r_mapcnt == 0) {
547 /*
548 * Before otW close, make sure dirty pages written back.
549 */
550 if ((flag & FWRITE) && vn_has_cached_data(vp)) {
551 /* smbfs_putapage() will acquire shared lock, so release
552 * exclusive lock temporally.
553 */
554 smbfs_rw_exit(&np->r_lkserlock);
555
556 (void) smbfs_putpage(vp, (offset_t) 0, 0, B_INVAL | B_ASYNC, cr, ct);
557
558 /* acquire exclusive lock again. */
559 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
560 }
561 smbfs_rele_fid(np, &scred);
562 }
563
564 smb_credrele(&scred);
565 smbfs_rw_exit(&np->r_lkserlock);
566
567 return (0);
568 }
569
570 /*
571 * Helper for smbfs_close. Decrement the reference count
572 * for an SMB-level file or directory ID, and when the last
573 * reference for the fid goes away, do the OtW close.
574 * Also called in smbfs_inactive (defensive cleanup).
575 */
576 static void
577 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
578 {
579 smb_share_t *ssp;
580 cred_t *oldcr;
581 struct smbfs_fctx *fctx;
582 int error;
631 }
632
633 /* Allow next open to use any v_type. */
634 np->n_ovtype = VNON;
635
636 /*
637 * Other "last close" stuff.
638 */
639 mutex_enter(&np->r_statelock);
640 if (np->n_flag & NATTRCHANGED)
641 smbfs_attrcache_rm_locked(np);
642 oldcr = np->r_cred;
643 np->r_cred = NULL;
644 mutex_exit(&np->r_statelock);
645 if (oldcr != NULL)
646 crfree(oldcr);
647 }
648
649 /* ARGSUSED */
650 static int
651 smbfs_read(vnode_t * vp, struct uio * uiop, int ioflag, cred_t * cr,
652 caller_context_t * ct)
653 {
654 struct smb_cred scred;
655 struct vattr va;
656 smbnode_t *np;
657 smbmntinfo_t *smi;
658 smb_share_t *ssp;
659 offset_t endoff;
660 ssize_t past_eof;
661 int error;
662
663 caddr_t base;
664 u_offset_t blk;
665 u_offset_t boff;
666 size_t blen;
667 uint_t flags;
668
669 np = VTOSMB(vp);
670 smi = VTOSMI(vp);
671 ssp = smi->smi_share;
672
673 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
674 return (EIO);
675
676 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
677 return (EIO);
678
679 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
680
681 if (vp->v_type != VREG)
682 return (EISDIR);
683
684 if (uiop->uio_resid == 0)
685 return (0);
686
687 /*
688 * Like NFS3, just check for 63-bit overflow. Our SMB layer takes
689 * care to return EFBIG when it has to fallback to a 32-bit call.
690 */
691 endoff = uiop->uio_loffset + uiop->uio_resid;
692 if (uiop->uio_loffset < 0 || endoff < 0)
693 return (EINVAL);
694
695 /* get vnode attributes from server */
696 va.va_mask = AT_SIZE | AT_MTIME;
697 if (error = smbfsgetattr(vp, &va, cr))
698 return (error);
699
700 /* Update mtime with mtime from server here? */
701
702 /* if offset is beyond EOF, read nothing */
703 if (uiop->uio_loffset >= va.va_size)
704 return (0);
705
706 /*
707 * Limit the read to the remaining file size. Do this by temporarily
708 * reducing uio_resid by the amount the lies beyoned the EOF.
709 */
710 if (endoff > va.va_size) {
711 past_eof = (ssize_t) (endoff - va.va_size);
712 uiop->uio_resid -= past_eof;
713 } else
714 past_eof = 0;
715
716 /* Bypass the VM if vnode is non-cacheable. */
717 if ((vp->v_flag & VNOCACHE) ||
718 ((np->r_flags & RDIRECTIO) &&
719 np->r_mapcnt == 0 &&
720 !(vn_has_cached_data(vp)))) {
721
722 /* Shared lock for n_fid use in smb_rwuio */
723 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
724 return (EINTR);
725 smb_credinit(&scred, cr);
726
727 /* After reconnect, n_fid is invalid */
728 if (np->n_vcgenid != ssp->ss_vcgenid)
729 error = ESTALE;
730 else
731 error = smb_rwuio(ssp, np->n_fid, UIO_READ,
732 uiop, &scred, smb_timo_read);
733
734 smb_credrele(&scred);
735 smbfs_rw_exit(&np->r_lkserlock);
736
737 } else {
738
739 /* Do I/O through segmap. */
740 do {
741 blk = uiop->uio_loffset & MAXBMASK;
742 boff = uiop->uio_loffset & MAXBOFFSET;
743 blen = MIN(MAXBSIZE - boff, uiop->uio_resid);
744
745 if (vpm_enable) {
746
747 error = vpm_data_copy(vp, blk + boff, blen, uiop, 1, NULL, 0, S_READ);
748
749 } else {
750
751 base = segmap_getmapflt(segkmap, vp, blk + boff, blen, 1, S_READ);
752
753 error = uiomove(base + boff, blen, UIO_READ, uiop);
754 }
755
756 if (!error) {
757 mutex_enter(&np->r_statelock);
758 if ((blen + boff == MAXBSIZE) || (uiop->uio_loffset == np->r_size)) {
759 flags = SM_DONTNEED;
760 } else {
761 flags = 0;
762 }
763 mutex_exit(&np->r_statelock);
764 } else {
765 flags = 0;
766 }
767 if (vpm_enable) {
768 (void) vpm_sync_pages(vp, blk + boff, blen, flags);
769 } else {
770 (void) segmap_release(segkmap, base, flags);
771 }
772 } while (!error && uiop->uio_resid > 0);
773 }
774
775 /* undo adjustment of resid */
776 uiop->uio_resid += past_eof;
777
778 return (error);
779 }
780
781 /* ARGSUSED */
782 static int
783 smbfs_write(vnode_t * vp, struct uio * uiop, int ioflag, cred_t * cr,
784 caller_context_t * ct)
785 {
786 struct smb_cred scred;
787 struct vattr va;
788 smbnode_t *np;
789 smbmntinfo_t *smi;
790 smb_share_t *ssp;
791 offset_t endoff, limit;
792 ssize_t past_limit;
793 int error, timo;
794
795 caddr_t base;
796 u_offset_t blk;
797 u_offset_t boff;
798 size_t blen;
799 uint_t flags;
800
801 u_offset_t last_off;
802 size_t last_resid;
803
804 np = VTOSMB(vp);
805 smi = VTOSMI(vp);
806 ssp = smi->smi_share;
807
808 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
809 return (EIO);
810
811 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
812 return (EIO);
813
814 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
815
816 if (vp->v_type != VREG)
817 return (EISDIR);
818
819 if (uiop->uio_resid == 0)
820 return (0);
821
822 /*
823 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
824 */
825 if (ioflag & (FAPPEND | FSYNC)) {
826 if (np->n_flag & NMODIFIED) {
827 smbfs_attrcache_remove(np);
828 /* XXX: smbfs_vinvalbuf? */
829 }
830 }
831 if (ioflag & FAPPEND) {
832 /*
833 * File size can be changed by another client
834 */
835 va.va_mask = AT_SIZE;
836 if (error = smbfsgetattr(vp, &va, cr))
837 return (error);
838 uiop->uio_loffset = va.va_size;
839 }
840 /*
841 * Like NFS3, just check for 63-bit overflow.
842 */
843 endoff = uiop->uio_loffset + uiop->uio_resid;
844 if (uiop->uio_loffset < 0 || endoff < 0)
845 return (EINVAL);
846
847 /*
848 * Check to make sure that the process will not exceed its limit on
849 * file size. It is okay to write up to the limit, but not beyond.
850 * Thus, the write which reaches the limit will be short and the next
851 * write will return an error.
852 *
853 * So if we're starting at or beyond the limit, EFBIG. Otherwise,
854 * temporarily reduce resid to the amount the falls after the limit.
855 */
856 limit = uiop->uio_llimit;
857 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
858 limit = MAXOFFSET_T;
859 if (uiop->uio_loffset >= limit)
860 return (EFBIG);
861 if (endoff > limit) {
862 past_limit = (ssize_t) (endoff - limit);
863 uiop->uio_resid -= past_limit;
864 } else
865 past_limit = 0;
866
867 /* Bypass the VM if vnode is non-cacheable. */
868 if ((vp->v_flag & VNOCACHE) ||
869 ((np->r_flags & RDIRECTIO) &&
870 np->r_mapcnt == 0 &&
871 !(vn_has_cached_data(vp)))) {
872
873 /* Timeout: longer for append. */
874 timo = smb_timo_write;
875 if (endoff > np->r_size)
876 timo = smb_timo_append;
877
878 /* Shared lock for n_fid use in smb_rwuio */
879 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
880 return (EINTR);
881 smb_credinit(&scred, cr);
882
883 /* After reconnect, n_fid is invalid */
884 if (np->n_vcgenid != ssp->ss_vcgenid)
885 error = ESTALE;
886 else
887 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
888 uiop, &scred, timo);
889
890 if (error == 0) {
891 mutex_enter(&np->r_statelock);
892 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
893 if (uiop->uio_loffset > (offset_t) np->r_size)
894 np->r_size = (len_t) uiop->uio_loffset;
895 mutex_exit(&np->r_statelock);
896 if (ioflag & (FSYNC | FDSYNC)) {
897 /* Don't error the I/O if this fails. */
898 (void) smbfs_smb_flush(np, &scred);
899 }
900 }
901 smb_credrele(&scred);
902 smbfs_rw_exit(&np->r_lkserlock);
903
904 } else {
905
906 /* Do I/O through segmap. */
907 size_t bsize = vp->v_vfsp->vfs_bsize;
908
909 do {
910 blk = uiop->uio_loffset & MAXBMASK;
911 boff = uiop->uio_loffset & MAXBOFFSET;
912 blen = MIN(MAXBSIZE - boff, uiop->uio_resid);
913
914 last_off = uiop->uio_loffset;
915 last_resid = uiop->uio_resid;
916
917 uio_prefaultpages((ssize_t) blen, uiop);
918
919 if (vpm_enable) {
920
921 error = writenp(np, NULL, blen, uiop, 0);
922
923 } else {
924
925 if (segmap_kpm) {
926 u_offset_t poff = uiop->uio_loffset & PAGEOFFSET;
927 size_t plen = MIN(PAGESIZE - poff, uiop->uio_resid);
928
929 int pagecreate;
930
931 mutex_enter(&np->r_statelock);
932 pagecreate = (poff == 0) &&
933 ((plen == PAGESIZE) ||
934 (uiop->uio_loffset + plen >= np->r_size));
935 mutex_exit(&np->r_statelock);
936
937 base = segmap_getmapflt(segkmap, vp, blk + boff, plen, !pagecreate, S_WRITE);
938 error = writenp(np, base + poff, blen, uiop, pagecreate);
939
940 } else {
941 base = segmap_getmapflt(segkmap, vp, blk + boff, blen, 0, S_READ);
942 error = writenp(np, base + boff, blen, uiop, 0);
943 }
944 }
945
946 if (!error) {
947 if (uiop->uio_loffset % bsize == 0) {
948 flags = SM_WRITE | SM_DONTNEED;
949 } else {
950 flags = 0;
951 }
952
953 if (ioflag & (FSYNC | FDSYNC)) {
954 flags &= ~SM_ASYNC;
955 flags |= SM_WRITE;
956 }
957 if (vpm_enable) {
958 error = vpm_sync_pages(vp, blk, blen, flags);
959 } else {
960 error = segmap_release(segkmap, base, flags);
961 }
962 } else {
963 if (vpm_enable) {
964 (void) vpm_sync_pages(vp, blk, blen, 0);
965 } else {
966 (void) segmap_release(segkmap, base, 0);
967 }
968 }
969 } while (!error && uiop->uio_resid > 0);
970 }
971
972 /* undo adjustment of resid */
973 if (error) {
974 uiop->uio_resid = last_resid + past_limit;
975 uiop->uio_loffset = last_off;
976 } else {
977 uiop->uio_resid += past_limit;
978 }
979
980 return (error);
981 }
982
983 /* correspond to writerp() in nfs_client.c */
984 static int
985 writenp(smbnode_t * np, caddr_t base, int tcount, struct uio * uiop, int pgcreated)
986 {
987 int pagecreate;
988 int n;
989 int saved_n;
990 caddr_t saved_base;
991 u_offset_t offset;
992 int error;
993 int sm_error;
994
995 vnode_t *vp = SMBTOV(np);
996
997 ASSERT(tcount <= MAXBSIZE && tcount <= uiop->uio_resid);
998 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
999 if (!vpm_enable) {
1000 ASSERT(((uintptr_t) base & MAXBOFFSET) + tcount <= MAXBSIZE);
1001 }
1002 /*
1003 * Move bytes in at most PAGESIZE chunks. We must avoid spanning
1004 * pages in uiomove() because page faults may cause the cache to be
1005 * invalidated out from under us. The r_size is not updated until
1006 * after the uiomove. If we push the last page of a file before
1007 * r_size is correct, we will lose the data written past the current
1008 * (and invalid) r_size.
1009 */
1010 do {
1011 offset = uiop->uio_loffset;
1012 pagecreate = 0;
1013
1014 /*
1015 * n is the number of bytes required to satisfy the request
1016 * or the number of bytes to fill out the page.
1017 */
1018 n = (int) MIN((PAGESIZE - (offset & PAGEOFFSET)), tcount);
1019
1020 /*
1021 * Check to see if we can skip reading in the page and just
1022 * allocate the memory. We can do this if we are going to
1023 * rewrite the entire mapping or if we are going to write to
1024 * or beyond the current end of file from the beginning of
1025 * the mapping.
1026 *
1027 * The read of r_size is now protected by r_statelock.
1028 */
1029 mutex_enter(&np->r_statelock);
1030 /*
1031 * When pgcreated is nonzero the caller has already done a
1032 * segmap_getmapflt with forcefault 0 and S_WRITE. With
1033 * segkpm this means we already have at least one page
1034 * created and mapped at base.
1035 */
1036 pagecreate = pgcreated ||
1037 ((offset & PAGEOFFSET) == 0 &&
1038 (n == PAGESIZE || ((offset + n) >= np->r_size)));
1039
1040 mutex_exit(&np->r_statelock);
1041
1042 if (!vpm_enable && pagecreate) {
1043 /*
1044 * The last argument tells segmap_pagecreate() to
1045 * always lock the page, as opposed to sometimes
1046 * returning with the page locked. This way we avoid
1047 * a fault on the ensuing uiomove(), but also more
1048 * importantly (to fix bug 1094402) we can call
1049 * segmap_fault() to unlock the page in all cases. An
1050 * alternative would be to modify segmap_pagecreate()
1051 * to tell us when it is locking a page, but that's a
1052 * fairly major interface change.
1053 */
1054 if (pgcreated == 0)
1055 (void) segmap_pagecreate(segkmap, base,
1056 (uint_t) n, 1);
1057 saved_base = base;
1058 saved_n = n;
1059 }
1060 /*
1061 * The number of bytes of data in the last page can not be
1062 * accurately be determined while page is being uiomove'd to
1063 * and the size of the file being updated. Thus, inform
1064 * threads which need to know accurately how much data is in
1065 * the last page of the file. They will not do the i/o
1066 * immediately, but will arrange for the i/o to happen later
1067 * when this modify operation will have finished.
1068 */
1069 ASSERT(!(np->r_flags & RMODINPROGRESS));
1070 mutex_enter(&np->r_statelock);
1071 np->r_flags |= RMODINPROGRESS;
1072 np->r_modaddr = (offset & MAXBMASK);
1073 mutex_exit(&np->r_statelock);
1074
1075 if (vpm_enable) {
1076 /*
1077 * Copy data. If new pages are created, part of the
1078 * page that is not written will be initizliazed with
1079 * zeros.
1080 */
1081 error = vpm_data_copy(vp, offset, n, uiop,
1082 !pagecreate, NULL, 0, S_WRITE);
1083 } else {
1084 error = uiomove(base, n, UIO_WRITE, uiop);
1085 }
1086
1087 /*
1088 * r_size is the maximum number of bytes known to be in the
1089 * file. Make sure it is at least as high as the first
1090 * unwritten byte pointed to by uio_loffset.
1091 */
1092 mutex_enter(&np->r_statelock);
1093 if (np->r_size < uiop->uio_loffset)
1094 np->r_size = uiop->uio_loffset;
1095 np->r_flags &= ~RMODINPROGRESS;
1096 np->r_flags |= RDIRTY;
1097 mutex_exit(&np->r_statelock);
1098
1099 /* n = # of bytes written */
1100 n = (int) (uiop->uio_loffset - offset);
1101
1102 if (!vpm_enable) {
1103 base += n;
1104 }
1105 tcount -= n;
1106 /*
1107 * If we created pages w/o initializing them completely, we
1108 * need to zero the part that wasn't set up. This happens on
1109 * a most EOF write cases and if we had some sort of error
1110 * during the uiomove.
1111 */
1112 if (!vpm_enable && pagecreate) {
1113 if ((uiop->uio_loffset & PAGEOFFSET) || n == 0)
1114 (void) kzero(base, PAGESIZE - n);
1115
1116 if (pgcreated) {
1117 /*
1118 * Caller is responsible for this page, it
1119 * was not created in this loop.
1120 */
1121 pgcreated = 0;
1122 } else {
1123 /*
1124 * For bug 1094402: segmap_pagecreate locks
1125 * page. Unlock it. This also unlocks the
1126 * pages allocated by page_create_va() in
1127 * segmap_pagecreate().
1128 */
1129 sm_error = segmap_fault(kas.a_hat, segkmap,
1130 saved_base, saved_n,
1131 F_SOFTUNLOCK, S_WRITE);
1132 if (error == 0)
1133 error = sm_error;
1134 }
1135 }
1136 } while (tcount > 0 && error == 0);
1137
1138 return (error);
1139 }
1140
1141 /* ARGSUSED */
1142 static int
1143 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
1144 cred_t *cr, int *rvalp, caller_context_t *ct)
1145 {
1146 int error;
1147 smbmntinfo_t *smi;
1148
1149 smi = VTOSMI(vp);
1150
1151 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1152 return (EIO);
1153
1154 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1155 return (EIO);
1156
1157 switch (cmd) {
1158 /* First three from ZFS. XXX - need these? */
1159
1709 switch (np->n_ovtype) {
1710 case VNON:
1711 /* not open (OK) */
1712 break;
1713
1714 case VDIR:
1715 if (np->n_dirrefs == 0)
1716 break;
1717 SMBVDEBUG("open dir: refs %d path %s\n",
1718 np->n_dirrefs, np->n_rpath);
1719 /* Force last close. */
1720 np->n_dirrefs = 1;
1721 smbfs_rele_fid(np, &scred);
1722 break;
1723
1724 case VREG:
1725 if (np->n_fidrefs == 0)
1726 break;
1727 SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
1728 np->n_fidrefs, np->n_fid, np->n_rpath);
1729 /*
1730 * Before otW close, make sure dirty pages written back.
1731 */
1732 if (vn_has_cached_data(vp)) {
1733 /* smbfs_putapage() will acquire shared lock, so release
1734 * exclusive lock temporally.
1735 */
1736 smbfs_rw_exit(&np->r_lkserlock);
1737
1738 (void) smbfs_putpage(vp, (offset_t) 0, 0, B_INVAL | B_ASYNC, cr, ct);
1739
1740 /* acquire exclusive lock again. */
1741 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1742 }
1743 /* Force last close. */
1744 np->n_fidrefs = 1;
1745 smbfs_rele_fid(np, &scred);
1746 break;
1747
1748 default:
1749 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
1750 np->n_ovtype = VNON;
1751 break;
1752 }
1753
1754 smb_credrele(&scred);
1755 smbfs_rw_exit(&np->r_lkserlock);
1756
1757 smbfs_addfree(np);
1758 }
1759
1760 /*
1761 * Remote file system operations having to do with directory manipulation.
1762 */
3468 return (error);
3469 }
3470
3471
3472 /*
3473 * XXX
3474 * This op should eventually support PSARC 2007/268.
3475 */
3476 static int
3477 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
3478 caller_context_t *ct)
3479 {
3480 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3481 return (EIO);
3482
3483 if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3484 return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3485 else
3486 return (ENOSYS);
3487 }
3488
3489 /* correspond to bp_mapin() in bp_map.c */
3490 static int
3491 uio_page_mapin(uio_t * uiop, page_t * pp)
3492 {
3493 u_offset_t off;
3494 size_t size;
3495 pgcnt_t npages;
3496 caddr_t kaddr;
3497 pfn_t pfnum;
3498
3499 off = (uintptr_t) uiop->uio_loffset & PAGEOFFSET;
3500 size = P2ROUNDUP(uiop->uio_resid + off, PAGESIZE);
3501 npages = btop(size);
3502
3503 ASSERT(pp != NULL);
3504
3505 if (npages == 1 && kpm_enable) {
3506 kaddr = hat_kpm_mapin(pp, NULL);
3507 if (kaddr == NULL)
3508 return (EFAULT);
3509
3510 uiop->uio_iov->iov_base = kaddr + off;
3511 uiop->uio_iov->iov_len = PAGESIZE - off;
3512
3513 } else {
3514 kaddr = vmem_xalloc(heap_arena, size, PAGESIZE, 0, 0, NULL, NULL, VM_SLEEP);
3515 if (kaddr == NULL)
3516 return (EFAULT);
3517
3518 uiop->uio_iov->iov_base = kaddr + off;
3519 uiop->uio_iov->iov_len = size - off;
3520
3521 /* map pages into kaddr */
3522 uint_t attr = PROT_READ | PROT_WRITE | HAT_NOSYNC;
3523 while (npages-- > 0) {
3524 pfnum = pp->p_pagenum;
3525 pp = pp->p_next;
3526
3527 hat_devload(kas.a_hat, kaddr, PAGESIZE, pfnum, attr, HAT_LOAD_LOCK);
3528 kaddr += PAGESIZE;
3529 }
3530 }
3531 return (0);
3532 }
3533
3534 /* correspond to bp_mapout() in bp_map.c */
3535 static void
3536 uio_page_mapout(uio_t * uiop, page_t * pp)
3537 {
3538 u_offset_t off;
3539 size_t size;
3540 pgcnt_t npages;
3541 caddr_t kaddr;
3542
3543 kaddr = uiop->uio_iov->iov_base;
3544 off = (uintptr_t) kaddr & PAGEOFFSET;
3545 size = P2ROUNDUP(uiop->uio_iov->iov_len + off, PAGESIZE);
3546 npages = btop(size);
3547
3548 ASSERT(pp != NULL);
3549
3550 kaddr = (caddr_t) ((uintptr_t) kaddr & MMU_PAGEMASK);
3551
3552 if (npages == 1 && kpm_enable) {
3553 hat_kpm_mapout(pp, NULL, kaddr);
3554
3555 } else {
3556 hat_unload(kas.a_hat, (void *) kaddr, size,
3557 HAT_UNLOAD_NOSYNC | HAT_UNLOAD_UNLOCK);
3558 vmem_free(heap_arena, (void *) kaddr, size);
3559 }
3560 uiop->uio_iov->iov_base = 0;
3561 uiop->uio_iov->iov_len = 0;
3562 }
3563
3564 static int
3565 smbfs_map(vnode_t * vp, offset_t off, struct as * as, caddr_t * addrp,
3566 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t * cr,
3567 caller_context_t * ct)
3568 {
3569 smbnode_t *np;
3570 smbmntinfo_t *smi;
3571 struct vattr va;
3572 segvn_crargs_t vn_a;
3573 int error;
3574
3575 np = VTOSMB(vp);
3576 smi = VTOSMI(vp);
3577
3578 if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3579 return (EIO);
3580
3581 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3582 return (EIO);
3583
3584 if (vp->v_flag & VNOMAP || vp->v_flag & VNOCACHE)
3585 return (EAGAIN);
3586
3587 if (vp->v_type != VREG)
3588 return (ENODEV);
3589
3590 va.va_mask = AT_ALL;
3591 if (error = smbfsgetattr(vp, &va, cr))
3592 return (error);
3593
3594 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
3595 return (EINTR);
3596
3597 if (MANDLOCK(vp, va.va_mode)) {
3598 error = EAGAIN;
3599 goto out;
3600 }
3601 as_rangelock(as);
3602 error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
3603
3604 if (error != 0) {
3605 as_rangeunlock(as);
3606 goto out;
3607 }
3608 vn_a.vp = vp;
3609 vn_a.offset = off;
3610 vn_a.type = flags & MAP_TYPE;
3611 vn_a.prot = prot;
3612 vn_a.maxprot = maxprot;
3613 vn_a.flags = flags & ~MAP_TYPE;
3614 vn_a.cred = cr;
3615 vn_a.amp = NULL;
3616 vn_a.szc = 0;
3617 vn_a.lgrp_mem_policy_flags = 0;
3618
3619 error = as_map(as, *addrp, len, segvn_create, &vn_a);
3620
3621 as_rangeunlock(as);
3622
3623 out:
3624 smbfs_rw_exit(&np->r_lkserlock);
3625
3626 return (error);
3627 }
3628
3629 static int
3630 smbfs_addmap(vnode_t * vp, offset_t off, struct as * as, caddr_t addr,
3631 size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t * cr,
3632 caller_context_t * ct)
3633 {
3634 atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, btopr(len));
3635 return (0);
3636 }
3637
3638 static int
3639 smbfs_delmap(vnode_t * vp, offset_t off, struct as * as, caddr_t addr,
3640 size_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t * cr,
3641 caller_context_t * ct)
3642 {
3643
3644 smbnode_t *np;
3645
3646 atomic_add_long((ulong_t *) & VTOSMB(vp)->r_mapcnt, -btopr(len));
3647
3648 /*
3649 * mark RDIRTY here, will be used to check if a file is dirty when
3650 * unmount smbfs
3651 */
3652 if (vn_has_cached_data(vp) && !vn_is_readonly(vp) && (maxprot & PROT_WRITE)
3653 && (flags == MAP_SHARED)) {
3654 np = VTOSMB(vp);
3655 mutex_enter(&np->r_statelock);
3656 np->r_flags |= RDIRTY;
3657 mutex_exit(&np->r_statelock);
3658 }
3659 return (0);
3660 }
3661
3662 static int
3663 smbfs_putpage(vnode_t * vp, offset_t off, size_t len, int flags,
3664 cred_t * cr, caller_context_t * ct)
3665 {
3666
3667 smbnode_t *np;
3668 size_t io_len;
3669 u_offset_t io_off;
3670 u_offset_t eoff;
3671 int error = 0;
3672 page_t *pp;
3673 int rdirty;
3674
3675 np = VTOSMB(vp);
3676
3677 if (len == 0) {
3678
3679 /* will flush the whole file, so clear RDIRTY */
3680 if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) {
3681 mutex_enter(&np->r_statelock);
3682 rdirty = np->r_flags & RDIRTY;
3683 np->r_flags &= ~RDIRTY;
3684 mutex_exit(&np->r_statelock);
3685 } else
3686 rdirty = 0;
3687
3688 error = pvn_vplist_dirty(vp, off, smbfs_putapage, flags, cr);
3689
3690 /*
3691 * if failed and the vnode was dirty before and we aren't
3692 * forcibly invalidating pages, then mark RDIRTY again.
3693 */
3694 if (error && rdirty &&
3695 (flags & (B_INVAL | B_FORCE)) != (B_INVAL | B_FORCE)) {
3696 mutex_enter(&np->r_statelock);
3697 np->r_flags |= RDIRTY;
3698 mutex_exit(&np->r_statelock);
3699 }
3700 } else {
3701
3702 eoff = off + len;
3703
3704 mutex_enter(&np->r_statelock);
3705 if (eoff > np->r_size)
3706 eoff = np->r_size;
3707 mutex_exit(&np->r_statelock);
3708
3709 for (io_off = off; io_off < eoff; io_off += io_len) {
3710 if ((flags & B_INVAL) || (flags & B_ASYNC) == 0) {
3711 pp = page_lookup(vp, io_off,
3712 (flags & (B_INVAL | B_FREE) ? SE_EXCL : SE_SHARED));
3713 } else {
3714 pp = page_lookup_nowait(vp, io_off,
3715 (flags & B_FREE) ? SE_EXCL : SE_SHARED);
3716 }
3717
3718 if (pp == NULL || !pvn_getdirty(pp, flags))
3719 io_len = PAGESIZE;
3720 else {
3721 error = smbfs_putapage(vp, pp, &io_off, &io_len, flags, cr);
3722 }
3723 }
3724
3725 }
3726
3727 return (error);
3728 }
3729
3730 static int
3731 smbfs_putapage(vnode_t * vp, page_t * pp, u_offset_t * offp, size_t * lenp,
3732 int flags, cred_t * cr)
3733 {
3734
3735 struct smb_cred scred;
3736 smbnode_t *np;
3737 smbmntinfo_t *smi;
3738 smb_share_t *ssp;
3739 uio_t uio;
3740 iovec_t uiov, uiov_bak;
3741
3742 size_t io_len;
3743 u_offset_t io_off;
3744 size_t limit;
3745 size_t bsize;
3746 size_t blksize;
3747 u_offset_t blkoff;
3748 int error;
3749
3750 np = VTOSMB(vp);
3751 smi = VTOSMI(vp);
3752 ssp = smi->smi_share;
3753
3754 /* do block io, get a kluster of dirty pages in a block. */
3755 bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
3756 blkoff = pp->p_offset / bsize;
3757 blkoff *= bsize;
3758 blksize = roundup(bsize, PAGESIZE);
3759
3760 pp = pvn_write_kluster(vp, pp, &io_off, &io_len, blkoff, blksize, flags);
3761
3762 ASSERT(pp->p_offset >= blkoff);
3763
3764 if (io_off + io_len > blkoff + blksize) {
3765 ASSERT((io_off + io_len) - (blkoff + blksize) < PAGESIZE);
3766 }
3767
3768 /* Don't allow put pages beyond EOF */
3769 mutex_enter(&np->r_statelock);
3770 limit=MIN(np->r_size, blkoff + blksize);
3771 mutex_exit(&np->r_statelock);
3772
3773 if (io_off >= limit) {
3774 error = 0;
3775 goto out;
3776 } else if (io_off + io_len > limit) {
3777 int npages = btopr(limit - io_off);
3778 page_t *trunc;
3779 page_list_break(&pp, &trunc, npages);
3780 if (trunc)
3781 pvn_write_done(trunc, flags);
3782 io_len = limit - io_off;
3783 }
3784
3785 /*
3786 * Taken from NFS4. The RMODINPROGRESS flag makes sure that
3787 * smbfs_putapage() sees a consistent value of r_size. RMODINPROGRESS
3788 * is set in writenp(). When RMODINPROGRESS is set it indicates that
3789 * a uiomove() is in progress and the r_size has not been made
3790 * consistent with the new size of the file. When the uiomove()
3791 * completes the r_size is updated and the RMODINPROGRESS flag is
3792 * cleared.
3793 *
3794 * The RMODINPROGRESS flag makes sure that smbfs_putapage() sees a
3795 * consistent value of r_size. Without this handshaking, it is
3796 * possible that smbfs_putapage() picks up the old value of r_size
3797 * before the uiomove() in writenp() completes. This will result in
3798 * the write through smbfs_putapage() being dropped.
3799 *
3800 * More precisely, there is a window between the time the uiomove()
3801 * completes and the time the r_size is updated. If a VOP_PUTPAGE()
3802 * operation intervenes in this window, the page will be picked up,
3803 * because it is dirty (it will be unlocked, unless it was
3804 * pagecreate'd). When the page is picked up as dirty, the dirty bit
3805 * is reset (pvn_getdirty()). In smbfs_putapage(), r_size is checked.
3806 * This will still be the old size. Therefore the page will not be
3807 * written out. When segmap_release() calls VOP_PUTPAGE(), the page
3808 * will be found to be clean and the write will be dropped.
3809 */
3810 if (np->r_flags & RMODINPROGRESS) {
3811
3812 mutex_enter(&np->r_statelock);
3813 if ((np->r_flags & RMODINPROGRESS) &&
3814 np->r_modaddr + MAXBSIZE > io_off &&
3815 np->r_modaddr < io_off + io_len) {
3816 page_t *plist;
3817 /*
3818 * A write is in progress for this region of the
3819 * file. If we did not detect RMODINPROGRESS here,
3820 * the data beyond the file size won't be write out.
3821 * We end up losing data. So we decide to set the
3822 * modified bit on each page in the page list and
3823 * mark the smbnode with RDIRTY. This write will be
3824 * restarted at some later time.
3825 */
3826 plist = pp;
3827 while (plist != NULL) {
3828 pp = plist;
3829 page_sub(&plist, pp);
3830 hat_setmod(pp);
3831 page_io_unlock(pp);
3832 page_unlock(pp);
3833 }
3834 np->r_flags |= RDIRTY;
3835 mutex_exit(&np->r_statelock);
3836 if (offp)
3837 *offp = io_off;
3838 if (lenp)
3839 *lenp = io_len;
3840 return (0);
3841 }
3842 mutex_exit(&np->r_statelock);
3843 }
3844
3845 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
3846 return (EINTR);
3847 smb_credinit(&scred, cr);
3848
3849 if (np->n_vcgenid != ssp->ss_vcgenid)
3850 error = ESTALE;
3851 else {
3852 /* just use uio instead of buf, since smb_rwuio need uio. */
3853 uiov.iov_base = 0;
3854 uiov.iov_len = 0;
3855 uio.uio_iov = &uiov;
3856 uio.uio_iovcnt = 1;
3857 uio.uio_loffset = io_off;
3858 uio.uio_resid = io_len;
3859 uio.uio_segflg = UIO_SYSSPACE;
3860 uio.uio_llimit = MAXOFFSET_T;
3861 /* map pages into kernel address space, and setup uio. */
3862 error = uio_page_mapin(&uio, pp);
3863 if (error == 0) {
3864 uiov_bak.iov_base = uiov.iov_base;
3865 uiov_bak.iov_len = uiov.iov_len;
3866 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE, &uio, &scred, smb_timo_write);
3867 if (error == 0) {
3868 mutex_enter(&np->r_statelock);
3869 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
3870 mutex_exit(&np->r_statelock);
3871 (void) smbfs_smb_flush(np, &scred);
3872 }
3873 /* unmap pages from kernel address space. */
3874 uio.uio_iov = &uiov_bak;
3875 uio_page_mapout(&uio, pp);
3876 }
3877 }
3878
3879 smb_credrele(&scred);
3880 smbfs_rw_exit(&np->r_lkserlock);
3881
3882 out:
3883 pvn_write_done(pp, ((error) ? B_ERROR : 0) | B_WRITE | flags);
3884
3885 if (offp)
3886 *offp = io_off;
3887 if (lenp)
3888 *lenp = io_len;
3889
3890 return (error);
3891 }
3892
3893 static int
3894 smbfs_getpage(vnode_t * vp, offset_t off, size_t len, uint_t * protp,
3895 page_t * pl[], size_t plsz, struct seg * seg, caddr_t addr,
3896 enum seg_rw rw, cred_t * cr, caller_context_t * ct)
3897 {
3898
3899 smbnode_t *np;
3900 int error;
3901
3902 /* these pages have all protections. */
3903 if (protp)
3904 *protp = PROT_ALL;
3905
3906 np = VTOSMB(vp);
3907
3908 /* Don't allow get pages beyond EOF, unless it's segkmap. */
3909 mutex_enter(&np->r_statelock);
3910 if (off + len > np->r_size + PAGESIZE && seg != segkmap){
3911 mutex_exit(&np->r_statelock);
3912 return (EFAULT);
3913 }
3914 mutex_exit(&np->r_statelock);
3915
3916 if (len <= PAGESIZE) {
3917 error = smbfs_getapage(vp, off, len, protp, pl, plsz, seg, addr, rw,
3918 cr);
3919 } else {
3920 error = pvn_getpages(smbfs_getapage, vp, off, len, protp, pl, plsz, seg,
3921 addr, rw, cr);
3922 }
3923
3924 return (error);
3925 }
3926
3927 static int
3928 smbfs_getapage(vnode_t * vp, u_offset_t off, size_t len,
3929 uint_t * protp, page_t * pl[], size_t plsz, struct seg * seg, caddr_t addr,
3930 enum seg_rw rw, cred_t * cr)
3931 {
3932
3933 smbnode_t *np;
3934 smbmntinfo_t *smi;
3935 smb_share_t *ssp;
3936 smb_cred_t scred;
3937
3938 page_t *pp;
3939 uio_t uio;
3940 iovec_t uiov, uiov_bak;
3941
3942 u_offset_t blkoff;
3943 size_t bsize;
3944 size_t blksize;
3945
3946 u_offset_t io_off;
3947 size_t io_len;
3948 size_t pages_len;
3949
3950 int error = 0;
3951
3952 np = VTOSMB(vp);
3953 smi = VTOSMI(vp);
3954 ssp = smi->smi_share;
3955
3956 /* if pl is null,it's meaningless */
3957 if (pl == NULL)
3958 return (EFAULT);
3959
3960 again:
3961 if (page_exists(vp, off) == NULL) {
3962 if (rw == S_CREATE) {
3963 /* just return a empty page if asked to create. */
3964 if ((pp = page_create_va(vp, off, PAGESIZE, PG_WAIT | PG_EXCL, seg, addr)) == NULL)
3965 goto again;
3966 pages_len = PAGESIZE;
3967 } else {
3968
3969 /*
3970 * do block io, get a kluster of non-exist pages in a
3971 * block.
3972 */
3973 bsize = MAX(vp->v_vfsp->vfs_bsize, PAGESIZE);
3974 blkoff = off / bsize;
3975 blkoff *= bsize;
3976 blksize = roundup(bsize, PAGESIZE);
3977
3978 pp = pvn_read_kluster(vp, off, seg, addr, &io_off, &io_len, blkoff, blksize, 0);
3979
3980 if (pp == NULL)
3981 goto again;
3982
3983 pages_len = io_len;
3984
3985 /* Don't need to get pages from server if it's segkmap
3986 * that reads beyond EOF. */
3987 mutex_enter(&np->r_statelock);
3988 if (io_off >= np->r_size && seg == segkmap) {
3989 mutex_exit(&np->r_statelock);
3990 error = 0;
3991 goto out;
3992 } else if (io_off + io_len > np->r_size) {
3993 int npages = btopr(np->r_size - io_off);
3994 page_t *trunc;
3995
3996 page_list_break(&pp, &trunc, npages);
3997 if (trunc)
3998 pvn_read_done(trunc, 0);
3999 io_len = np->r_size - io_off;
4000 }
4001 mutex_exit(&np->r_statelock);
4002
4003 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
4004 return EINTR;
4005 smb_credinit(&scred, cr);
4006
4007 /*
4008 * just use uio instead of buf, since smb_rwuio need
4009 * uio.
4010 */
4011 uiov.iov_base = 0;
4012 uiov.iov_len = 0;
4013 uio.uio_iov = &uiov;
4014 uio.uio_iovcnt = 1;
4015 uio.uio_loffset = io_off;
4016 uio.uio_resid = io_len;
4017 uio.uio_segflg = UIO_SYSSPACE;
4018 uio.uio_llimit = MAXOFFSET_T;
4019
4020 /*
4021 * map pages into kernel address space, and setup
4022 * uio.
4023 */
4024 error = uio_page_mapin(&uio, pp);
4025 if (error == 0) {
4026 uiov_bak.iov_base = uiov.iov_base;
4027 uiov_bak.iov_len = uiov.iov_len;
4028 error = smb_rwuio(ssp, np->n_fid, UIO_READ, &uio, &scred, smb_timo_read);
4029 /* unmap pages from kernel address space. */
4030 uio.uio_iov = &uiov_bak;
4031 uio_page_mapout(&uio, pp);
4032 }
4033 smb_credrele(&scred);
4034 smbfs_rw_exit(&np->r_lkserlock);
4035 }
4036 } else {
4037 se_t se = rw == S_CREATE ? SE_EXCL : SE_SHARED;
4038 if ((pp = page_lookup(vp, off, se)) == NULL) {
4039 goto again;
4040 }
4041 }
4042
4043 out:
4044 if (pp) {
4045 if (error) {
4046 pvn_read_done(pp, B_ERROR);
4047 } else {
4048 /* init page list, unlock pages. */
4049 pvn_plist_init(pp, pl, plsz, off, pages_len, rw);
4050 }
4051 }
4052 return (error);
4053 }
4054
4055 /* correspond to nfs_invalidate_pages() in nfs_client.c */
4056 void
4057 smbfs_invalidate_pages(vnode_t * vp, u_offset_t off, cred_t * cr)
4058 {
4059
4060 smbnode_t *np;
4061
4062 np = VTOSMB(vp);
4063 /* will flush the whole file, so clear RDIRTY */
4064 if (off == (u_offset_t) 0 && (np->r_flags & RDIRTY)) {
4065 mutex_enter(&np->r_statelock);
4066 np->r_flags &= ~RDIRTY;
4067 mutex_exit(&np->r_statelock);
4068 }
4069 (void) pvn_vplist_dirty(vp, off, smbfs_putapage, B_INVAL | B_TRUNC, cr);
4070 }
|