35 #include <sys/cdefs.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
43 #include <sys/event.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
47 #include <sys/lockf.h>
48 #include <sys/malloc.h>
49 #include <sys/mount.h>
50 #include <sys/mutex.h>
51 #include <sys/namei.h>
52 #include <sys/fcntl.h>
53 #include <sys/unistd.h>
54 #include <sys/vnode.h>
55 #include <sys/dirent.h>
58 #include <security/mac/mac_framework.h>
61 #include <vm/vm_object.h>
62 #include <vm/vm_extern.h>
64 #include <vm/vm_map.h>
65 #include <vm/vm_page.h>
66 #include <vm/vm_pager.h>
67 #include <vm/vnode_pager.h>
73 char *dirbuf,
int dirbuflen, off_t *off,
74 char **cpos,
int *len,
int *eofflag,
76 static int dirent_exists(
struct vnode *vp,
const char *dirname,
79 #define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
101 .vop_bypass = VOP_EOPNOTSUPP,
111 .vop_close = VOP_NULL,
112 .vop_fsync = VOP_NULL,
115 .vop_inactive = VOP_NULL,
116 .vop_ioctl = VOP_ENOTTY,
121 .vop_open = VOP_NULL,
122 .vop_pathconf = VOP_EINVAL,
125 .vop_readlink = VOP_EINVAL,
127 .vop_revoke = VOP_PANIC,
199 panic(
"filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name);
216 struct vop_lookup_args
256 printf(
"No strategy for buffer at %p\n", ap->a_bp);
257 vprint(
"vnode", ap->a_vp);
258 ap->a_bp->b_ioflags |= BIO_ERROR;
259 ap->a_bp->b_error = EOPNOTSUPP;
266 int dirbuflen, off_t *off,
char **cpos,
int *len,
267 int *eofflag,
struct thread *td)
274 KASSERT(VOP_ISLOCKED(vp), (
"vp %p is not locked", vp));
275 KASSERT(vp->v_type == VDIR, (
"vp %p is not a directory", vp));
278 iov.iov_base = dirbuf;
279 iov.iov_len = dirbuflen;
283 uio.uio_offset = *off;
284 uio.uio_resid = dirbuflen;
285 uio.uio_segflg = UIO_SYSSPACE;
286 uio.uio_rw = UIO_READ;
292 error = mac_vnode_check_readdir(td->td_ucred, vp);
295 error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag,
300 *off = uio.uio_offset;
303 *len = (dirbuflen - uio.uio_resid);
309 dp = (
struct dirent *)(*cpos);
310 reclen = dp->d_reclen;
330 int error, eofflag, dirbuflen, len, found;
335 KASSERT(VOP_ISLOCKED(vp), (
"vp %p is not locked", vp));
336 KASSERT(vp->v_type == VDIR, (
"vp %p is not a directory", vp));
340 error = VOP_GETATTR(vp, &va, td->td_ucred);
344 dirbuflen = DEV_BSIZE;
345 if (dirbuflen < va.va_blocksize)
346 dirbuflen = va.va_blocksize;
347 dirbuf = (
char *)
malloc(dirbuflen, M_TEMP, M_WAITOK);
353 &cpos, &len, &eofflag, td);
357 if ((dp->d_type != DT_WHT) &&
358 !strcmp(dp->d_name, dirname)) {
362 }
while (len > 0 || !eofflag);
365 free(dirbuf, M_TEMP);
373 KASSERT((ap->a_accmode & ~(VEXEC | VWRITE | VREAD | VADMIN |
374 VAPPEND)) == 0, (
"invalid bit in accmode"));
376 return (VOP_ACCESSX(ap->a_vp, ap->a_accmode, ap->a_cred, ap->a_td));
383 accmode_t
accmode = ap->a_accmode;
392 return (VOP_ACCESS(ap->a_vp, accmode, ap->a_cred, ap->a_td));
406 if (ap->a_fl->l_whence == SEEK_END) {
413 vn_lock(vp, LK_SHARED | LK_RETRY);
414 error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
421 return (
lf_advlock(ap, &(vp->v_lockf), vattr.va_size));
432 if (ap->a_fl->l_whence == SEEK_END) {
434 vn_lock(vp, LK_SHARED | LK_RETRY);
435 error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
465 struct vop_pathconf_args
472 switch (ap->a_name) {
474 *ap->a_retval = NAME_MAX;
477 *ap->a_retval = PATH_MAX;
480 *ap->a_retval = LINK_MAX;
483 *ap->a_retval = MAX_CANON;
486 *ap->a_retval = MAX_INPUT;
489 *ap->a_retval = PIPE_BUF;
491 case _PC_CHOWN_RESTRICTED:
495 *ap->a_retval = _POSIX_VDISABLE;
508 struct vop_lock1_args
515 struct vnode *vp = ap->a_vp;
517 return (_lockmgr_args(vp->v_vnlock, ap->a_flags, VI_MTX(vp),
518 LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap->a_file,
525 struct vop_unlock_args
530 struct vnode *vp = ap->a_vp;
532 return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, VI_MTX(vp)));
538 struct vop_islocked_args
574 if (ap->a_events & ~POLLSTANDARD)
576 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
584 struct vop_getwritemount_args
598 mp = ap->a_vp->v_mount;
601 if (mp != ap->a_vp->v_mount) {
623 if (ap->a_bop != NULL)
624 *ap->a_bop = &ap->a_vp->v_bufobj;
625 if (ap->a_bnp != NULL)
626 *ap->a_bnp = ap->a_bn * btodb(ap->a_vp->v_mount->mnt_stat.f_iosize);
627 if (ap->a_runp != NULL)
629 if (ap->a_runb != NULL)
636 struct vop_fsync_args
643 struct vnode *vp = ap->a_vp;
656 TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) {
657 bp->b_vflags &= ~BV_SCANNED;
665 TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
666 if ((bp->b_vflags & BV_SCANNED) != 0)
668 bp->b_vflags |= BV_SCANNED;
669 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
670 if (ap->a_waitfor != MNT_WAIT)
673 LK_EXCLUSIVE | LK_INTERLOCK | LK_SLEEPFAIL,
681 KASSERT(bp->b_bufobj == bo,
682 (
"bp %p wrong b_bufobj %p should be %p",
683 bp, bp->b_bufobj, bo));
684 if ((bp->b_flags & B_DELWRI) == 0)
685 panic(
"fsync: not dirty");
686 if ((vp->v_object != NULL) && (bp->b_flags & B_CLUSTEROK)) {
702 if (ap->a_waitfor == MNT_WAIT) {
704 if (bo->bo_dirty.bv_cnt > 0) {
710 TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs)
711 if ((error = bp->b_error) == 0)
713 if (error == 0 && --maxretry >= 0)
720 vprint(
"fsync: giving up on dirty", vp);
728 struct vop_getpages_args
737 return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
738 ap->a_count, ap->a_reqpage);
750 struct vop_putpages_args
760 return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
761 ap->a_sync, ap->a_rtvals);
773 struct vnode *vp = ap->a_vp;
774 struct vnode **dvp = ap->a_vpp;
775 struct ucred *cred = ap->a_cred;
776 char *
buf = ap->a_buf;
777 int *buflen = ap->a_buflen;
779 int i, error, eofflag, dirbuflen, flags, locked, len, covered;
793 if (vp->v_type != VDIR)
796 error = VOP_GETATTR(vp, &va, cred);
801 locked = VOP_ISLOCKED(vp);
803 NDINIT_ATVP(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
806 error =
vn_open_cred(&nd, &flags, 0, VN_OPEN_NOAUDIT, cred, NULL);
808 vn_lock(vp, locked | LK_RETRY);
811 NDFREE(&nd, NDF_ONLY_PNBUF);
813 mvp = *dvp = nd.ni_vp;
815 if (vp->v_mount != (*dvp)->v_mount &&
816 ((*dvp)->v_vflag & VV_ROOT) &&
817 ((*dvp)->v_mount->mnt_flag & MNT_UNION)) {
818 *dvp = (*dvp)->v_mount->mnt_vnodecovered;
823 vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
827 fileno = va.va_fileid;
829 dirbuflen = DEV_BSIZE;
830 if (dirbuflen < va.va_blocksize)
831 dirbuflen = va.va_blocksize;
832 dirbuf = (
char *)
malloc(dirbuflen, M_TEMP, M_WAITOK);
834 if ((*dvp)->v_type != VDIR) {
844 &cpos, &len, &eofflag, td);
848 if ((dp->d_type != DT_WHT) &&
849 (dp->d_fileno == fileno)) {
852 vn_lock(mvp, LK_EXCLUSIVE | LK_RETRY);
856 vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
860 vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
868 if (dp->d_namlen == 1 && dp->d_name[0] ==
'.') {
871 bcopy(dp->d_name, buf + i, dp->d_namlen);
876 }
while (len > 0 || !eofflag);
880 free(dirbuf, M_TEMP);
892 vn_lock(vp, locked | LK_RETRY);
903 struct vattr vattr, *vap;
905 off_t fsize, len, cur, offset;
918 offset = *ap->a_offset;
920 error = VOP_GETATTR(vp, vap, td->td_ucred);
923 fsize = vap->va_size;
924 iosize = vap->va_blocksize;
926 iosize = BLKDEV_IOSIZE;
927 if (iosize > MAXPHYS)
929 buf =
malloc(iosize, M_TEMP, M_WAITOK);
936 error = VFS_STATFS(vp->v_mount, &sfs, td);
939 if (sfs.f_maxfilesize) {
940 if (offset > sfs.f_maxfilesize || len > sfs.f_maxfilesize ||
941 offset + len > sfs.f_maxfilesize) {
947 if (offset + len > vap->va_size) {
952 vap->va_size = offset + len;
953 error = VOP_SETATTR(vp, vap, td->td_ucred);
957 vap->va_size = fsize;
958 error = VOP_SETATTR(vp, vap, td->td_ucred);
970 if ((offset % iosize) != 0)
971 cur -= (offset % iosize);
974 if (offset < fsize) {
977 auio.uio_iov = &aiov;
979 auio.uio_offset = offset;
980 auio.uio_resid = cur;
981 auio.uio_segflg = UIO_SYSSPACE;
982 auio.uio_rw = UIO_READ;
984 error = VOP_READ(vp, &auio, 0, td->td_ucred);
987 if (auio.uio_resid > 0) {
988 bzero(buf + cur - auio.uio_resid,
997 auio.uio_iov = &aiov;
999 auio.uio_offset = offset;
1000 auio.uio_resid = cur;
1001 auio.uio_segflg = UIO_SYSSPACE;
1002 auio.uio_rw = UIO_WRITE;
1005 error = VOP_WRITE(vp, &auio, 0, td->td_ucred);
1019 *ap->a_offset = offset;
1029 int error, vfslocked;
1032 switch (ap->a_advice) {
1033 case POSIX_FADV_WILLNEED:
1041 case POSIX_FADV_DONTNEED:
1050 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1051 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1052 if (vp->v_iflag & VI_DOOMED) {
1054 VFS_UNLOCK_GIANT(vfslocked);
1058 if (vp->v_object != NULL) {
1059 start = trunc_page(ap->a_start);
1060 end = round_page(ap->a_end);
1061 VM_OBJECT_LOCK(vp->v_object);
1062 vm_object_page_cache(vp->v_object, OFF_TO_IDX(start),
1064 VM_OBJECT_UNLOCK(vp->v_object);
1067 VFS_UNLOCK_GIANT(vfslocked);
1080 ap->a_vp->v_socket = ap->a_socket;
1088 *ap->a_socket = ap->a_vp->v_socket;
1096 ap->a_vp->v_socket = NULL;
1104 return ((ap->a_vp->v_vflag & VV_TEXT) != 0);
1111 ap->a_vp->v_vflag |= VV_TEXT;
1119 ap->a_vp->v_vflag &= ~VV_TEXT;
1127 *ap->a_writecount = ap->a_vp->v_writecount;
1135 ap->a_vp->v_writecount += ap->a_inc;
1150 return (EOPNOTSUPP);
1159 return (EOPNOTSUPP);
1170 return (EOPNOTSUPP);
1178 struct vnode *vp, *mvp;
1180 int error, lockreq, allerror = 0;
1183 lockreq = LK_EXCLUSIVE | LK_INTERLOCK;
1184 if (waitfor != MNT_WAIT)
1185 lockreq |= LK_NOWAIT;
1190 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1191 if (vp->v_bufobj.bo_dirty.bv_cnt == 0) {
1195 if ((error =
vget(vp, lockreq, td)) != 0) {
1196 if (error == ENOENT) {
1197 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1202 error = VOP_FSYNC(vp, waitfor, td);
1227 return (EOPNOTSUPP);
1238 return (EOPNOTSUPP);
1261 struct vnode *filename_vp;
1263 const
char *attrname;
1266 if (filename_vp != NULL)
1267 VOP_UNLOCK(filename_vp, 0);
1268 return (EOPNOTSUPP);
1275 struct sysctl_req *req;
1278 return (EOPNOTSUPP);
int vop_stdfsync(struct vop_fsync_args *ap)
int lockstatus(struct lock *lk)
int vop_panic(struct vop_generic_args *ap)
int lf_advlock(struct vop_advlock_args *ap, struct lockf **statep, u_quad_t size)
int vop_stdadvlock(struct vop_advlock_args *ap)
int vinvalbuf(struct vnode *vp, int flags, int slpflag, int slptimeo)
int lf_advlockasync(struct vop_advlockasync_args *ap, struct lockf **statep, u_quad_t size)
int bufobj_wwait(struct bufobj *bo, int slpflag, int timeo)
void NDFREE(struct nameidata *ndp, const u_int flags)
int vop_stdunp_detach(struct vop_unp_detach_args *ap)
void vfs_rel(struct mount *mp)
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
int vfs_bio_awrite(struct buf *bp)
int vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid, void *arg)
int vop_stdgetpages(struct vop_getpages_args *ap)
static int vop_nostrategy(struct vop_strategy_args *)
void panic(const char *fmt,...)
int vget(struct vnode *vp, int flags, struct thread *td)
void bufdone(struct buf *bp)
int vfs_stdroot(struct mount *mp, int flags, struct vnode **vpp)
int vop_stdaccess(struct vop_access_args *ap)
int vfs_stdvget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
int vop_stdadvlockasync(struct vop_advlockasync_args *ap)
int vfs_kqfilter(struct vop_kqfilter_args *ap)
static int vop_stdget_writecount(struct vop_get_writecount_args *ap)
int vop_stdislocked(struct vop_islocked_args *ap)
void vop_rename_fail(struct vop_rename_args *ap)
int vop_stdallocate(struct vop_allocate_args *ap)
int vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *filename_vp, int attrnamespace, const char *attrname)
struct vfsconfhead vfsconf
int vop_null(struct vop_generic_args *ap)
struct vop_vector default_vnodeops
int vop_stdvptocnp(struct vop_vptocnp_args *ap)
int vop_stdaccessx(struct vop_accessx_args *ap)
void vref(struct vnode *vp)
int vfs_stdnosync(struct mount *mp, int waitfor)
int vop_stdpoll(struct vop_poll_args *ap)
void vput(struct vnode *vp)
int vop_stdgetwritemount(struct vop_getwritemount_args *ap)
static int vop_norename(struct vop_rename_args *)
int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags, struct ucred *cred, struct file *fp)
int vfs_stdinit(struct vfsconf *vfsp)
void vfs_ref(struct mount *mp)
static int vop_stdunset_text(struct vop_unset_text_args *ap)
int vop_stdputpages(struct vop_putpages_args *ap)
int vfs_unixify_accmode(accmode_t *accmode)
int vop_stdpathconf(struct vop_pathconf_args *ap)
static int get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, int dirbuflen, off_t *off, char **cpos, int *len, int *eofflag, struct thread *td)
int vfs_stduninit(struct vfsconf *vfsp)
int vop_enoent(struct vop_generic_args *ap)
int vop_stdadvlockpurge(struct vop_advlockpurge_args *ap)
int poll_no_poll(int events)
int vop_stdvptofh(struct vop_vptofh_args *ap)
static int vop_stdadd_writecount(struct vop_add_writecount_args *ap)
int vfs_stdsync(struct mount *mp, int waitfor)
static int vop_stdset_text(struct vop_set_text_args *ap)
int vn_pollrecord(struct vnode *vp, struct thread *td, int events)
int vop_ebadf(struct vop_generic_args *ap)
int vop_stdlock(struct vop_lock1_args *ap)
void bawrite(struct buf *bp)
void free(void *addr, struct malloc_type *mtp)
int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td)
int printf(const char *fmt,...)
int vop_stdunlock(struct vop_unlock_args *ap)
int vop_enotty(struct vop_generic_args *ap)
static int vop_nolookup(struct vop_lookup_args *)
int vfs_stdfhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp)
int vop_stdkqfilter(struct vop_kqfilter_args *ap)
int vfs_stdsysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
void vrele(struct vnode *vp)
void lf_purgelocks(struct vnode *vp, struct lockf **statep)
int vop_stdunp_connect(struct vop_unp_connect_args *ap)
static int dirent_exists(struct vnode *vp, const char *dirname, struct thread *td)
static int vop_stdis_text(struct vop_is_text_args *ap)
int vop_nopoll(struct vop_poll_args *ap)
void bremfree(struct buf *bp)
int vop_eopnotsupp(struct vop_generic_args *ap)
int vfs_stdstatfs(struct mount *mp, struct statfs *sbp)
int vop_stdunp_bind(struct vop_unp_bind_args *ap)
int vop_stdbmap(struct vop_bmap_args *ap)
int vop_stdadvise(struct vop_advise_args *ap)
int vop_einval(struct vop_generic_args *ap)