Module Name: src Committed By: tls Date: Sun Aug 10 06:56:06 UTC 2014
Modified Files: src/sys/miscfs/deadfs [tls-earlyentropy]: dead_vnops.c src/sys/miscfs/fdesc [tls-earlyentropy]: fdesc.h fdesc_vfsops.c fdesc_vnops.c src/sys/miscfs/fifofs [tls-earlyentropy]: fifo_vnops.c src/sys/miscfs/genfs [tls-earlyentropy]: layer.h layer_extern.h layer_subr.c layer_vfsops.c layer_vnops.c src/sys/miscfs/kernfs [tls-earlyentropy]: files.kernfs kernfs.h kernfs_vfsops.c kernfs_vnops.c src/sys/miscfs/nullfs [tls-earlyentropy]: null_vfsops.c src/sys/miscfs/overlay [tls-earlyentropy]: overlay_vfsops.c src/sys/miscfs/procfs [tls-earlyentropy]: procfs.h procfs_linux.c procfs_subr.c procfs_vfsops.c procfs_vnops.c src/sys/miscfs/specfs [tls-earlyentropy]: spec_vnops.c specdev.h src/sys/miscfs/umapfs [tls-earlyentropy]: umap_vfsops.c Removed Files: src/sys/miscfs/kernfs [tls-earlyentropy]: kernfs_subr.c Log Message: Rebase. To generate a diff of this commit: cvs rdiff -u -r1.56 -r1.56.2.1 src/sys/miscfs/deadfs/dead_vnops.c cvs rdiff -u -r1.21 -r1.21.26.1 src/sys/miscfs/fdesc/fdesc.h cvs rdiff -u -r1.88 -r1.88.2.1 src/sys/miscfs/fdesc/fdesc_vfsops.c cvs rdiff -u -r1.119 -r1.119.2.1 src/sys/miscfs/fdesc/fdesc_vnops.c cvs rdiff -u -r1.74 -r1.74.2.1 src/sys/miscfs/fifofs/fifo_vnops.c cvs rdiff -u -r1.14 -r1.14.32.1 src/sys/miscfs/genfs/layer.h cvs rdiff -u -r1.35 -r1.35.2.1 src/sys/miscfs/genfs/layer_extern.h \ src/sys/miscfs/genfs/layer_subr.c cvs rdiff -u -r1.43 -r1.43.2.1 src/sys/miscfs/genfs/layer_vfsops.c cvs rdiff -u -r1.57 -r1.57.2.1 src/sys/miscfs/genfs/layer_vnops.c cvs rdiff -u -r1.4 -r1.4.34.1 src/sys/miscfs/kernfs/files.kernfs cvs rdiff -u -r1.37 -r1.37.12.1 src/sys/miscfs/kernfs/kernfs.h cvs rdiff -u -r1.26 -r0 src/sys/miscfs/kernfs/kernfs_subr.c cvs rdiff -u -r1.93 -r1.93.2.1 src/sys/miscfs/kernfs/kernfs_vfsops.c cvs rdiff -u -r1.150 -r1.150.2.1 src/sys/miscfs/kernfs/kernfs_vnops.c cvs rdiff -u -r1.87 -r1.87.2.1 src/sys/miscfs/nullfs/null_vfsops.c cvs rdiff -u -r1.60 -r1.60.2.1 src/sys/miscfs/overlay/overlay_vfsops.c cvs rdiff -u -r1.69 -r1.69.2.1 src/sys/miscfs/procfs/procfs.h cvs rdiff -u -r1.67 -r1.67.2.1 src/sys/miscfs/procfs/procfs_linux.c cvs rdiff -u -r1.104 -r1.104.2.1 src/sys/miscfs/procfs/procfs_subr.c cvs rdiff -u -r1.90 -r1.90.2.1 src/sys/miscfs/procfs/procfs_vfsops.c cvs rdiff -u -r1.189 -r1.189.2.1 src/sys/miscfs/procfs/procfs_vnops.c cvs rdiff -u -r1.143 -r1.143.2.1 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.42 -r1.42.2.1 src/sys/miscfs/specfs/specdev.h cvs rdiff -u -r1.91 -r1.91.2.1 src/sys/miscfs/umapfs/umap_vfsops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/miscfs/deadfs/dead_vnops.c diff -u src/sys/miscfs/deadfs/dead_vnops.c:1.56 src/sys/miscfs/deadfs/dead_vnops.c:1.56.2.1 --- src/sys/miscfs/deadfs/dead_vnops.c:1.56 Thu Feb 27 16:51:38 2014 +++ src/sys/miscfs/deadfs/dead_vnops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dead_vnops.c,v 1.56 2014/02/27 16:51:38 hannken Exp $ */ +/* $NetBSD: dead_vnops.c,v 1.56.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1989, 1993 @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dead_vnops.c,v 1.56 2014/02/27 16:51:38 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dead_vnops.c,v 1.56.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -87,6 +87,8 @@ const struct vnodeopv_entry_desc dead_vn { &vop_close_desc, dead_close }, /* close */ { &vop_read_desc, dead_read }, /* read */ { &vop_write_desc, dead_write }, /* write */ + { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ + { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ { &vop_fcntl_desc, dead_fcntl }, /* fcntl */ { &vop_ioctl_desc, dead_ioctl }, /* ioctl */ { &vop_poll_desc, dead_poll }, /* poll */ Index: src/sys/miscfs/fdesc/fdesc.h diff -u src/sys/miscfs/fdesc/fdesc.h:1.21 src/sys/miscfs/fdesc/fdesc.h:1.21.26.1 --- src/sys/miscfs/fdesc/fdesc.h:1.21 Tue Sep 27 01:22:12 2011 +++ src/sys/miscfs/fdesc/fdesc.h Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: fdesc.h,v 1.21 2011/09/27 01:22:12 christos Exp $ */ +/* $NetBSD: fdesc.h,v 1.21.26.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1992, 1993 @@ -56,11 +56,10 @@ typedef enum { } fdntype; struct fdescnode { - LIST_ENTRY(fdescnode) fd_hash; /* Hash list */ struct vnode *fd_vnode; /* Back ptr to vnode */ fdntype fd_type; /* Type of this node */ unsigned fd_fd; /* Fd to be dup'ed */ - char *fd_link; /* Link to fd/n */ + const char *fd_link; /* Link to fd/n */ int fd_ix; /* filesystem index */ }; Index: src/sys/miscfs/fdesc/fdesc_vfsops.c diff -u src/sys/miscfs/fdesc/fdesc_vfsops.c:1.88 src/sys/miscfs/fdesc/fdesc_vfsops.c:1.88.2.1 --- src/sys/miscfs/fdesc/fdesc_vfsops.c:1.88 Sun Mar 23 15:21:16 2014 +++ src/sys/miscfs/fdesc/fdesc_vfsops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: fdesc_vfsops.c,v 1.88 2014/03/23 15:21:16 hannken Exp $ */ +/* $NetBSD: fdesc_vfsops.c,v 1.88.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1992, 1993, 1995 @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.88 2014/03/23 15:21:16 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.88.2.1 2014/08/10 06:56:05 tls Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -78,7 +78,7 @@ int fdesc_mount(struct mount *mp, const char *path, void *data, size_t *data_len) { struct lwp *l = curlwp; - int error = 0; + int error = 0, ix; struct vnode *rvp; if (mp->mnt_flag & MNT_GETARGS) { @@ -91,12 +91,11 @@ fdesc_mount(struct mount *mp, const char if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); - error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp); + ix = FD_ROOT; + error = vcache_get(mp, &ix, sizeof(ix), &rvp); if (error) - return (error); + return error; - rvp->v_type = VDIR; - rvp->v_vflag |= VV_ROOT; mp->mnt_stat.f_namemax = FDESC_MAXNAMLEN; mp->mnt_flag |= MNT_LOCAL; mp->mnt_data = rvp; @@ -104,7 +103,6 @@ fdesc_mount(struct mount *mp, const char error = set_statvfs_info(path, UIO_USERSPACE, "fdesc", UIO_SYSSPACE, mp->mnt_op->vfs_name, mp, l); - VOP_UNLOCK(rvp); return error; } @@ -174,6 +172,66 @@ fdesc_vget(struct mount *mp, ino_t ino, return (EOPNOTSUPP); } +int +fdesc_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) +{ + int ix; + struct fdescnode *fd; + + KASSERT(key_len == sizeof(ix)); + memcpy(&ix, key, key_len); + + fd = kmem_alloc(sizeof(struct fdescnode), KM_SLEEP); + fd->fd_fd = -1; + fd->fd_link = NULL; + fd->fd_ix = ix; + fd->fd_vnode = vp; + vp->v_tag = VT_FDESC; + vp->v_op = fdesc_vnodeop_p; + vp->v_data = fd; + switch (ix) { + case FD_ROOT: + fd->fd_type = Froot; + vp->v_type = VDIR; + vp->v_vflag |= VV_ROOT; + break; + case FD_DEVFD: + fd->fd_type = Fdevfd; + vp->v_type = VDIR; + break; + case FD_CTTY: + fd->fd_type = Fctty; + vp->v_type = VNON; + break; + case FD_STDIN: + fd->fd_type = Flink; + fd->fd_link = "fd/0"; + vp->v_type = VLNK; + break; + case FD_STDOUT: + fd->fd_type = Flink; + fd->fd_link = "fd/1"; + vp->v_type = VLNK; + break; + case FD_STDERR: + fd->fd_type = Flink; + fd->fd_link = "fd/2"; + vp->v_type = VLNK; + break; + default: + KASSERT(ix >= FD_DESC); + fd->fd_type = Fdesc; + fd->fd_fd = ix - FD_DESC; + vp->v_type = VNON; + break; + } + uvm_vnp_setsize(vp, 0); + *new_key = &fd->fd_ix; + + return 0; +} + extern const struct vnodeopv_desc fdesc_vnodeop_opv_desc; const struct vnodeopv_desc * const fdesc_vnodeopv_descs[] = { @@ -192,6 +250,7 @@ struct vfsops fdesc_vfsops = { .vfs_statvfs = genfs_statvfs, .vfs_sync = fdesc_sync, .vfs_vget = fdesc_vget, + .vfs_loadvnode = fdesc_loadvnode, .vfs_fhtovp = (void *)eopnotsupp, .vfs_vptofh = (void *)eopnotsupp, .vfs_init = fdesc_init, Index: src/sys/miscfs/fdesc/fdesc_vnops.c diff -u src/sys/miscfs/fdesc/fdesc_vnops.c:1.119 src/sys/miscfs/fdesc/fdesc_vnops.c:1.119.2.1 --- src/sys/miscfs/fdesc/fdesc_vnops.c:1.119 Thu Mar 20 18:04:05 2014 +++ src/sys/miscfs/fdesc/fdesc_vnops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: fdesc_vnops.c,v 1.119 2014/03/20 18:04:05 christos Exp $ */ +/* $NetBSD: fdesc_vnops.c,v 1.119.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1992, 1993 @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.119 2014/03/20 18:04:05 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.119.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -69,21 +69,12 @@ __KERNEL_RCSID(0, "$NetBSD: fdesc_vnops. #define cttyvp(p) ((p)->p_lflag & PL_CONTROLT ? (p)->p_session->s_ttyvp : NULL) -static kmutex_t fdcache_lock; - dev_t devctty; #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 #endif -#define NFDCACHE 4 - -#define FD_NHASH(ix) \ - (&fdhashtbl[(ix) & fdhash]) -LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl; -u_long fdhash; - int fdesc_lookup(void *); #define fdesc_create genfs_eopnotsupp #define fdesc_mknod genfs_eopnotsupp @@ -139,6 +130,8 @@ const struct vnodeopv_entry_desc fdesc_v { &vop_setattr_desc, fdesc_setattr }, /* setattr */ { &vop_read_desc, fdesc_read }, /* read */ { &vop_write_desc, fdesc_write }, /* write */ + { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ + { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ { &vop_fcntl_desc, fdesc_fcntl }, /* fcntl */ { &vop_poll_desc, fdesc_poll }, /* poll */ @@ -185,76 +178,11 @@ fdesc_init(void) /* locate the major number */ cttymajor = devsw_name2chr("ctty", NULL, 0); devctty = makedev(cttymajor, 0); - mutex_init(&fdcache_lock, MUTEX_DEFAULT, IPL_NONE); - fdhashtbl = hashinit(NFDCACHE, HASH_LIST, true, &fdhash); } -/* - * Free hash table. - */ void fdesc_done(void) { - hashdone(fdhashtbl, HASH_LIST, fdhash); - mutex_destroy(&fdcache_lock); -} - -/* - * Return a locked vnode of the correct type. - */ -int -fdesc_allocvp(fdntype ftype, int ix, struct mount *mp, struct vnode **vpp) -{ - struct fdhashhead *fc; - struct fdescnode *fd; - int error = 0; - - fc = FD_NHASH(ix); -loop: - mutex_enter(&fdcache_lock); - LIST_FOREACH(fd, fc, fd_hash) { - if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { - mutex_enter(fd->fd_vnode->v_interlock); - mutex_exit(&fdcache_lock); - if (vget(fd->fd_vnode, LK_EXCLUSIVE)) - goto loop; - *vpp = fd->fd_vnode; - return 0; - } - } - mutex_exit(&fdcache_lock); - - error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, NULL, vpp); - if (error) - return error; - - mutex_enter(&fdcache_lock); - LIST_FOREACH(fd, fc, fd_hash) { - if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { - /* - * Another thread beat us, push back freshly - * allocated vnode and retry. - */ - mutex_exit(&fdcache_lock); - ungetnewvnode(*vpp); - goto loop; - } - } - - fd = malloc(sizeof(struct fdescnode), M_TEMP, M_WAITOK); - (*vpp)->v_data = fd; - fd->fd_vnode = *vpp; - fd->fd_type = ftype; - fd->fd_fd = -1; - fd->fd_link = 0; - fd->fd_ix = ix; - uvm_vnp_setsize(*vpp, 0); - error = VOP_LOCK(*vpp, LK_EXCLUSIVE); - KASSERT(error == 0); - LIST_INSERT_HEAD(fc, fd, fd_hash); - mutex_exit(&fdcache_lock); - - return 0; } /* @@ -276,9 +204,7 @@ fdesc_lookup(void *v) const char *pname = cnp->cn_nameptr; struct proc *p = l->l_proc; unsigned fd = 0; - int error; - struct vnode *fvp; - const char *ln; + int error, ix = -1; fdtab_t *dt; dt = curlwp->l_fd->fd_dt; @@ -299,11 +225,7 @@ fdesc_lookup(void *v) case Froot: if (cnp->cn_namelen == 2 && memcmp(pname, "fd", 2) == 0) { - error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); - if (error) - goto bad; - *vpp = fvp; - fvp->v_type = VDIR; + ix = FD_DEVFD; goto good; } @@ -313,58 +235,35 @@ fdesc_lookup(void *v) error = ENXIO; goto bad; } - error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); - if (error) - goto bad; - *vpp = fvp; - fvp->v_type = VCHR; + ix = FD_CTTY; goto good; } - ln = 0; switch (cnp->cn_namelen) { case 5: if (memcmp(pname, "stdin", 5) == 0) { - ln = "fd/0"; - fd = FD_STDIN; + ix = FD_STDIN; + goto good; } break; case 6: if (memcmp(pname, "stdout", 6) == 0) { - ln = "fd/1"; - fd = FD_STDOUT; - } else - if (memcmp(pname, "stderr", 6) == 0) { - ln = "fd/2"; - fd = FD_STDERR; + ix = FD_STDOUT; + goto good; + } else if (memcmp(pname, "stderr", 6) == 0) { + ix = FD_STDERR; + goto good; } break; } - if (ln) { - error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); - if (error) - goto bad; - /* XXXUNCONST */ - VTOFDESC(fvp)->fd_link = __UNCONST(ln); - *vpp = fvp; - fvp->v_type = VLNK; - goto good; - } else { - error = ENOENT; - goto bad; - } - - /* FALL THROUGH */ + error = ENOENT; + goto bad; case Fdevfd: if (cnp->cn_namelen == 2 && memcmp(pname, "..", 2) == 0) { - VOP_UNLOCK(dvp); - error = fdesc_root(dvp->v_mount, vpp); - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); - if (error) - goto bad; - return (error); + ix = FD_ROOT; + goto good; } fd = 0; @@ -385,21 +284,18 @@ fdesc_lookup(void *v) goto bad; } - error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); - if (error) - goto bad; - VTOFDESC(fvp)->fd_fd = fd; - *vpp = fvp; + ix = FD_DESC + fd; goto good; } bad: *vpp = NULL; - return (error); + return error; good: - VOP_UNLOCK(*vpp); - return (0); + KASSERT(ix != -1); + error = vcache_get(dvp->v_mount, &ix, sizeof(ix), vpp); + return error; } int @@ -793,8 +689,8 @@ fdesc_readlink(void *v) return (EPERM); if (VTOFDESC(vp)->fd_type == Flink) { - char *ln = VTOFDESC(vp)->fd_link; - error = uiomove(ln, strlen(ln), ap->a_uio); + const char *ln = VTOFDESC(vp)->fd_link; + error = uiomove(__UNCONST(ln), strlen(ln), ap->a_uio); } else { error = EOPNOTSUPP; } @@ -942,13 +838,15 @@ fdesc_inactive(void *v) struct vnode *a_vp; } */ *ap = v; struct vnode *vp = ap->a_vp; + struct fdescnode *fd = VTOFDESC(vp); /* * Clear out the v_type field to avoid - * nasty things happening in vgone(). + * nasty things happening on reclaim. */ + if (fd->fd_type == Fctty || fd->fd_type == Fdesc) + vp->v_type = VNON; VOP_UNLOCK(vp); - vp->v_type = VNON; return (0); } @@ -961,11 +859,9 @@ fdesc_reclaim(void *v) struct vnode *vp = ap->a_vp; struct fdescnode *fd = VTOFDESC(vp); - mutex_enter(&fdcache_lock); - LIST_REMOVE(fd, fd_hash); - free(vp->v_data, M_TEMP); - vp->v_data = 0; - mutex_exit(&fdcache_lock); + vp->v_data = NULL; + vcache_remove(vp->v_mount, &fd->fd_ix, sizeof(fd->fd_ix)); + kmem_free(fd, sizeof(struct fdescnode)); return (0); } Index: src/sys/miscfs/fifofs/fifo_vnops.c diff -u src/sys/miscfs/fifofs/fifo_vnops.c:1.74 src/sys/miscfs/fifofs/fifo_vnops.c:1.74.2.1 --- src/sys/miscfs/fifofs/fifo_vnops.c:1.74 Fri Feb 7 15:29:22 2014 +++ src/sys/miscfs/fifofs/fifo_vnops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: fifo_vnops.c,v 1.74 2014/02/07 15:29:22 hannken Exp $ */ +/* $NetBSD: fifo_vnops.c,v 1.74.2.1 2014/08/10 06:56:05 tls Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.74 2014/02/07 15:29:22 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.74.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -116,7 +116,6 @@ fifo_lookup(void *v) * Open called to set up a new instance of a fifo or * to find an active instance of a fifo. */ -/* ARGSUSED */ static int fifo_open(void *v) { @@ -132,14 +131,13 @@ fifo_open(void *v) int error; vp = ap->a_vp; + KASSERT(VOP_ISLOCKED(vp)); if ((fip = vp->v_fifoinfo) == NULL) { fip = kmem_alloc(sizeof(*fip), KM_SLEEP); - vp->v_fifoinfo = fip; error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL); if (error != 0) { kmem_free(fip, sizeof(*fip)); - vp->v_fifoinfo = NULL; return (error); } fip->fi_readsock = rso; @@ -147,17 +145,15 @@ fifo_open(void *v) if (error != 0) { (void)soclose(rso); kmem_free(fip, sizeof(*fip)); - vp->v_fifoinfo = NULL; return (error); } fip->fi_writesock = wso; solock(wso); - if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0) { + if ((error = unp_connect2(wso, rso)) != 0) { sounlock(wso); (void)soclose(wso); (void)soclose(rso); kmem_free(fip, sizeof(*fip)); - vp->v_fifoinfo = NULL; return (error); } fip->fi_readers = 0; @@ -166,6 +162,7 @@ fifo_open(void *v) rso->so_state |= SS_CANTSENDMORE; cv_init(&fip->fi_rcv, "fiford"); cv_init(&fip->fi_wcv, "fifowr"); + vp->v_fifoinfo = fip; } else { wso = fip->fi_writesock; rso = fip->fi_readsock; @@ -636,6 +633,8 @@ const struct vnodeopv_entry_desc fifo_vn { &vop_setattr_desc, genfs_ebadf }, /* setattr */ { &vop_read_desc, fifo_read }, /* read */ { &vop_write_desc, fifo_write }, /* write */ + { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ + { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ { &vop_poll_desc, fifo_poll }, /* poll */ { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */ Index: src/sys/miscfs/genfs/layer.h diff -u src/sys/miscfs/genfs/layer.h:1.14 src/sys/miscfs/genfs/layer.h:1.14.32.1 --- src/sys/miscfs/genfs/layer.h:1.14 Sun Jun 6 08:01:31 2010 +++ src/sys/miscfs/genfs/layer.h Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: layer.h,v 1.14 2010/06/06 08:01:31 hannken Exp $ */ +/* $NetBSD: layer.h,v 1.14.32.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -78,27 +78,16 @@ struct layer_args { #ifdef _KERNEL -struct layer_node; - -LIST_HEAD(layer_node_hashhead, layer_node); - struct layer_mount { struct mount *layerm_vfs; struct vnode *layerm_rootvp; /* Ref to root layer_node */ u_int layerm_flags; /* mount point layer flags */ u_int layerm_size; /* size of fs's struct node */ - enum vtype layerm_tag; /* vtag of our vnodes */ + enum vtagtype layerm_tag; /* vtag of our vnodes */ int /* bypass routine for this mount */ (*layerm_bypass)(void *); - int (*layerm_alloc) /* alloc a new layer node */ - (struct mount *, struct vnode *, - struct vnode **); int (**layerm_vnodeop_p) /* ops for our nodes */ (void *); - struct layer_node_hashhead /* head of hash list for layer_nodes */ - *layerm_node_hashtbl; - u_long layerm_node_hash; /* hash mask for hash chain */ - kmutex_t layerm_hashlock; /* interlock for hash chain. */ }; #define LAYERFS_MFLAGS 0x00000fff /* reserved layer mount flags */ @@ -108,7 +97,6 @@ struct layer_mount { * A cache of vnode references */ struct layer_node { - LIST_ENTRY(layer_node) layer_hash; /* Hash list */ struct vnode *layer_lowervp; /* VREFed once */ struct vnode *layer_vnode; /* Back pointer */ unsigned int layer_flags; /* locking, etc. */ Index: src/sys/miscfs/genfs/layer_extern.h diff -u src/sys/miscfs/genfs/layer_extern.h:1.35 src/sys/miscfs/genfs/layer_extern.h:1.35.2.1 --- src/sys/miscfs/genfs/layer_extern.h:1.35 Thu Feb 27 16:51:38 2014 +++ src/sys/miscfs/genfs/layer_extern.h Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: layer_extern.h,v 1.35 2014/02/27 16:51:38 hannken Exp $ */ +/* $NetBSD: layer_extern.h,v 1.35.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -76,14 +76,7 @@ /* Routines to manage nodes. */ void layerfs_init(void); void layerfs_done(void); -int layer_node_alloc(struct mount *, struct vnode *, struct vnode **); int layer_node_create(struct mount *, struct vnode *, struct vnode **); -struct vnode *layer_node_find(struct mount *, struct vnode *); - -#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */ -#define LAYER_NHASH(lmp, vp) \ - (&((lmp)->layerm_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & \ - (lmp)->layerm_node_hash])) /* VFS routines */ int layerfs_start(struct mount *, int); @@ -91,6 +84,8 @@ int layerfs_root(struct mount *, struct int layerfs_quotactl(struct mount *, struct quotactl_args *); int layerfs_statvfs(struct mount *, struct statvfs *); int layerfs_sync(struct mount *, int, struct kauth_cred *); +int layerfs_loadvnode(struct mount *, struct vnode *, + const void *, size_t, const void **); int layerfs_vget(struct mount *, ino_t, struct vnode **); int layerfs_fhtovp(struct mount *, struct fid *, struct vnode **); int layerfs_vptofh(struct vnode *, struct fid *, size_t *); Index: src/sys/miscfs/genfs/layer_subr.c diff -u src/sys/miscfs/genfs/layer_subr.c:1.35 src/sys/miscfs/genfs/layer_subr.c:1.35.2.1 --- src/sys/miscfs/genfs/layer_subr.c:1.35 Mon Feb 10 11:23:14 2014 +++ src/sys/miscfs/genfs/layer_subr.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: layer_subr.c,v 1.35 2014/02/10 11:23:14 hannken Exp $ */ +/* $NetBSD: layer_subr.c,v 1.35.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -69,7 +69,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.35 2014/02/10 11:23:14 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.35.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -81,7 +81,6 @@ __KERNEL_RCSID(0, "$NetBSD: layer_subr.c #include <sys/kmem.h> #include <sys/malloc.h> -#include <miscfs/specfs/specdev.h> #include <miscfs/genfs/layer.h> #include <miscfs/genfs/layer_extern.h> @@ -110,156 +109,18 @@ layerfs_done(void) } /* - * layer_node_find: find and return alias for lower vnode or NULL. - * - * => Return alias vnode referenced. if already exists. - * => The layermp's hashlock must be held on entry, we will unlock on success. - */ -struct vnode * -layer_node_find(struct mount *mp, struct vnode *lowervp) -{ - struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp); - struct layer_node_hashhead *hd; - struct layer_node *a; - struct vnode *vp; - int error; - - /* - * Find hash bucket and search the (two-way) linked list looking - * for a layerfs node structure which is referencing the lower vnode. - * If found, the increment the layer_node reference count, but NOT - * the lower vnode's reference counter. - */ - KASSERT(mutex_owned(&lmp->layerm_hashlock)); - hd = LAYER_NHASH(lmp, lowervp); -loop: - LIST_FOREACH(a, hd, layer_hash) { - if (a->layer_lowervp != lowervp) { - continue; - } - vp = LAYERTOV(a); - if (vp->v_mount != mp) { - continue; - } - mutex_enter(vp->v_interlock); - mutex_exit(&lmp->layerm_hashlock); - error = vget(vp, 0); - if (error) { - mutex_enter(&lmp->layerm_hashlock); - goto loop; - } - return vp; - } - return NULL; -} - -/* - * layer_node_alloc: make a new layerfs vnode. - * - * => vp is the alias vnode, lowervp is the lower vnode. - * => We will hold a reference to lowervp. - */ -int -layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) -{ - struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp); - struct layer_node_hashhead *hd; - struct layer_node *xp; - struct vnode *vp, *nvp; - int error; - - /* Get a new vnode and share its interlock with underlying vnode. */ - error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p, - lowervp->v_interlock, &vp); - if (error) { - return error; - } - vp->v_type = lowervp->v_type; - mutex_enter(vp->v_interlock); - vp->v_iflag |= VI_LAYER; - mutex_exit(vp->v_interlock); - - xp = kmem_alloc(lmp->layerm_size, KM_SLEEP); - if (xp == NULL) { - ungetnewvnode(vp); - return ENOMEM; - } - if (vp->v_type == VBLK || vp->v_type == VCHR) { - spec_node_init(vp, lowervp->v_rdev); - } - - /* - * Before inserting the node into the hash, check if other thread - * did not race with us. If so - return that node, destroy ours. - */ - mutex_enter(&lmp->layerm_hashlock); - if ((nvp = layer_node_find(mp, lowervp)) != NULL) { - ungetnewvnode(vp); - kmem_free(xp, lmp->layerm_size); - *vpp = nvp; - return 0; - } - - vp->v_data = xp; - vp->v_vflag = (vp->v_vflag & ~VV_MPSAFE) | - (lowervp->v_vflag & VV_MPSAFE); - xp->layer_vnode = vp; - xp->layer_lowervp = lowervp; - xp->layer_flags = 0; - - /* - * Insert the new node into the hash. - * Add a reference to the lower node. - */ - vref(lowervp); - hd = LAYER_NHASH(lmp, lowervp); - LIST_INSERT_HEAD(hd, xp, layer_hash); - uvm_vnp_setsize(vp, 0); - mutex_exit(&lmp->layerm_hashlock); - - *vpp = vp; - return 0; -} - -/* * layer_node_create: try to find an existing layerfs vnode refering to it, * otherwise make a new vnode which contains a reference to the lower vnode. - * - * => Caller should lock the lower node. */ int layer_node_create(struct mount *mp, struct vnode *lowervp, struct vnode **nvpp) { + int error; struct vnode *aliasvp; - struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp); - mutex_enter(&lmp->layerm_hashlock); - aliasvp = layer_node_find(mp, lowervp); - if (aliasvp != NULL) { - /* - * Note: layer_node_find() has taken another reference to - * the alias vnode and moved the lock holding to aliasvp. - */ -#ifdef LAYERFS_DIAGNOSTIC - if (layerfs_debug) - vprint("layer_node_create: exists", aliasvp); -#endif - } else { - int error; - - mutex_exit(&lmp->layerm_hashlock); - /* - * Get a new vnode. Make it to reference the layer_node. - * Note: aliasvp will be return with the reference held. - */ - error = (lmp->layerm_alloc)(mp, lowervp, &aliasvp); - if (error) - return error; -#ifdef LAYERFS_DIAGNOSTIC - if (layerfs_debug) - printf("layer_node_create: create new alias vnode\n"); -#endif - } + error = vcache_get(mp, &lowervp, sizeof(lowervp), &aliasvp); + if (error) + return error; /* * Now that we acquired a reference on the upper vnode, release one Index: src/sys/miscfs/genfs/layer_vfsops.c diff -u src/sys/miscfs/genfs/layer_vfsops.c:1.43 src/sys/miscfs/genfs/layer_vfsops.c:1.43.2.1 --- src/sys/miscfs/genfs/layer_vfsops.c:1.43 Tue Feb 25 18:30:11 2014 +++ src/sys/miscfs/genfs/layer_vfsops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: layer_vfsops.c,v 1.43 2014/02/25 18:30:11 pooka Exp $ */ +/* $NetBSD: layer_vfsops.c,v 1.43.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -74,7 +74,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.43 2014/02/25 18:30:11 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.43.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/sysctl.h> @@ -86,6 +86,7 @@ __KERNEL_RCSID(0, "$NetBSD: layer_vfsops #include <sys/kauth.h> #include <sys/module.h> +#include <miscfs/specfs/specdev.h> #include <miscfs/genfs/layer.h> #include <miscfs/genfs/layer_extern.h> @@ -204,6 +205,43 @@ layerfs_sync(struct mount *mp, int waitf } int +layerfs_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) +{ + struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp); + struct vnode *lowervp; + struct layer_node *xp; + + KASSERT(key_len == sizeof(struct vnode *)); + memcpy(&lowervp, key, key_len); + + xp = kmem_alloc(lmp->layerm_size, KM_SLEEP); + if (xp == NULL) + return ENOMEM; + + /* Share the interlock with the lower node. */ + mutex_obj_hold(lowervp->v_interlock); + uvm_obj_setlock(&vp->v_uobj, lowervp->v_interlock); + vp->v_iflag |= VI_LAYER | VI_LOCKSHARE; + + vp->v_tag = lmp->layerm_tag; + vp->v_type = lowervp->v_type; + vp->v_op = lmp->layerm_vnodeop_p; + if (vp->v_type == VBLK || vp->v_type == VCHR) + spec_node_init(vp, lowervp->v_rdev); + vp->v_data = xp; + xp->layer_vnode = vp; + xp->layer_lowervp = lowervp; + xp->layer_flags = 0; + uvm_vnp_setsize(vp, 0); + + /* Add a reference to the lower node. */ + vref(lowervp); + *new_key = &xp->layer_lowervp; + return 0; +} + +int layerfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct vnode *vp; Index: src/sys/miscfs/genfs/layer_vnops.c diff -u src/sys/miscfs/genfs/layer_vnops.c:1.57 src/sys/miscfs/genfs/layer_vnops.c:1.57.2.1 --- src/sys/miscfs/genfs/layer_vnops.c:1.57 Mon Mar 24 13:42:40 2014 +++ src/sys/miscfs/genfs/layer_vnops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: layer_vnops.c,v 1.57 2014/03/24 13:42:40 hannken Exp $ */ +/* $NetBSD: layer_vnops.c,v 1.57.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -170,7 +170,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.57 2014/03/24 13:42:40 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.57.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -694,11 +694,9 @@ layer_reclaim(void *v) */ lmp->layerm_rootvp = NULL; } + vcache_remove(vp->v_mount, &lowervp, sizeof(lowervp)); /* After this assignment, this node will not be re-used. */ xp->layer_lowervp = NULL; - mutex_enter(&lmp->layerm_hashlock); - LIST_REMOVE(xp, layer_hash); - mutex_exit(&lmp->layerm_hashlock); kmem_free(vp->v_data, lmp->layerm_size); vp->v_data = NULL; vrele(lowervp); Index: src/sys/miscfs/kernfs/files.kernfs diff -u src/sys/miscfs/kernfs/files.kernfs:1.4 src/sys/miscfs/kernfs/files.kernfs:1.4.34.1 --- src/sys/miscfs/kernfs/files.kernfs:1.4 Wed Mar 3 01:26:01 2010 +++ src/sys/miscfs/kernfs/files.kernfs Sun Aug 10 06:56:05 2014 @@ -1,7 +1,6 @@ -# $NetBSD: files.kernfs,v 1.4 2010/03/03 01:26:01 pooka Exp $ +# $NetBSD: files.kernfs,v 1.4.34.1 2014/08/10 06:56:05 tls Exp $ deffs KERNFS -file miscfs/kernfs/kernfs_subr.c kernfs file miscfs/kernfs/kernfs_vfsops.c kernfs file miscfs/kernfs/kernfs_vnops.c kernfs Index: src/sys/miscfs/kernfs/kernfs.h diff -u src/sys/miscfs/kernfs/kernfs.h:1.37 src/sys/miscfs/kernfs/kernfs.h:1.37.12.1 --- src/sys/miscfs/kernfs/kernfs.h:1.37 Thu Mar 22 20:34:38 2012 +++ src/sys/miscfs/kernfs/kernfs.h Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kernfs.h,v 1.37 2012/03/22 20:34:38 drochner Exp $ */ +/* $NetBSD: kernfs.h,v 1.37.12.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1992, 1993 @@ -39,6 +39,7 @@ #ifdef _KERNEL #include <sys/queue.h> #include <sys/tree.h> +#include <sys/mutex.h> /* * The different types of node in a kernfs filesystem @@ -91,9 +92,8 @@ struct kernfs_node { kfstype kfs_type; /* type of kernfs node */ mode_t kfs_mode; /* mode bits for stat() */ long kfs_fileno; /* unique file id */ - u_int32_t kfs_value; /* SA id or SP id (KFSint) */ const struct kern_target *kfs_kt; - void *kfs_v; /* pointer to secasvar/secpolicy/mbuf */ + void *kfs_v; /* dynamic node private data */ long kfs_cookie; /* fileno cookie */ }; @@ -123,22 +123,10 @@ extern const int static_nkern_targets; extern int (**kernfs_vnodeop_p)(void *); extern struct vfsops kernfs_vfsops; extern dev_t rrootdev; - -struct secasvar; -struct secpolicy; +extern kmutex_t kfs_lock; int kernfs_root(struct mount *, struct vnode **); -void kernfs_hashinit(void); -void kernfs_hashreinit(void); -void kernfs_hashdone(void); -int kernfs_freevp(struct vnode *); -int kernfs_allocvp(struct mount *, struct vnode **, kfstype, - const struct kern_target *, u_int32_t); - -void kernfs_revoke_sa(struct secasvar *); -void kernfs_revoke_sp(struct secpolicy *); - /* * Data types for the kernfs file operations. */ Index: src/sys/miscfs/kernfs/kernfs_vfsops.c diff -u src/sys/miscfs/kernfs/kernfs_vfsops.c:1.93 src/sys/miscfs/kernfs/kernfs_vfsops.c:1.93.2.1 --- src/sys/miscfs/kernfs/kernfs_vfsops.c:1.93 Sun Mar 23 15:21:16 2014 +++ src/sys/miscfs/kernfs/kernfs_vfsops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kernfs_vfsops.c,v 1.93 2014/03/23 15:21:16 hannken Exp $ */ +/* $NetBSD: kernfs_vfsops.c,v 1.93.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1992, 1993, 1995 @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.93 2014/03/23 15:21:16 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kernfs_vfsops.c,v 1.93.2.1 2014/08/10 06:56:05 tls Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -68,6 +68,7 @@ MODULE(MODULE_CLASS_VFS, kernfs, NULL); MALLOC_JUSTDEFINE(M_KERNFSMNT, "kernfs mount", "kernfs mount structures"); dev_t rrootdev = NODEV; +kmutex_t kfs_lock; VFS_PROTOS(kernfs); @@ -80,20 +81,20 @@ kernfs_init(void) { malloc_type_attach(M_KERNFSMNT); - kernfs_hashinit(); + mutex_init(&kfs_lock, MUTEX_DEFAULT, IPL_NONE); } void kernfs_reinit(void) { - kernfs_hashreinit(); + } void kernfs_done(void) { - kernfs_hashdone(); + mutex_destroy(&kfs_lock); malloc_type_detach(M_KERNFSMNT); } @@ -190,9 +191,20 @@ kernfs_unmount(struct mount *mp, int mnt int kernfs_root(struct mount *mp, struct vnode **vpp) { + const struct kern_target *root_target = &kern_targets[0]; + int error; /* setup "." */ - return (kernfs_allocvp(mp, vpp, KFSkern, &kern_targets[0], 0)); + error = vcache_get(mp, &root_target, sizeof(root_target), vpp); + if (error) + return error; + error = vn_lock(*vpp, LK_EXCLUSIVE); + if (error) { + vrele(*vpp); + *vpp = NULL; + return error; + } + return 0; } /*ARGSUSED*/ @@ -216,6 +228,70 @@ kernfs_vget(struct mount *mp, ino_t ino, return (EOPNOTSUPP); } +int +kernfs_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) +{ + const struct kern_target *kt; + struct kernfs_node *kfs, *kfsp; + long *cookie; + + KASSERT(key_len == sizeof(kt)); + memcpy(&kt, key, key_len); + + kfs = kmem_zalloc(sizeof(struct kernfs_node), KM_SLEEP); + cookie = &(VFSTOKERNFS(mp)->fileno_cookie); + mutex_enter(&kfs_lock); +again: + TAILQ_FOREACH(kfsp, &VFSTOKERNFS(mp)->nodelist, kfs_list) { + if (kfsp->kfs_cookie == *cookie) { + (*cookie) ++; + goto again; + } + if (TAILQ_NEXT(kfsp, kfs_list)) { + if (kfsp->kfs_cookie < *cookie && + *cookie < TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie) + break; + if (kfsp->kfs_cookie + 1 < + TAILQ_NEXT(kfsp, kfs_list)->kfs_cookie) { + *cookie = kfsp->kfs_cookie + 1; + break; + } + } + } + + kfs->kfs_cookie = *cookie; + + if (kfsp) + TAILQ_INSERT_AFTER(&VFSTOKERNFS(mp)->nodelist, kfsp, kfs, + kfs_list); + else + TAILQ_INSERT_TAIL(&VFSTOKERNFS(mp)->nodelist, kfs, kfs_list); + + kfs->kfs_type = kt->kt_tag; + kfs->kfs_vnode = vp; + kfs->kfs_fileno = KERNFS_FILENO(kt, kt->kt_tag, kfs->kfs_cookie); + kfs->kfs_kt = kt; + kfs->kfs_mode = kt->kt_mode; + vp->v_tag = VT_KERNFS; + vp->v_op = kernfs_vnodeop_p; + vp->v_data = kfs; + vp->v_type = kt->kt_vtype; + mutex_exit(&kfs_lock); + + if (kt->kt_tag == KFSkern) + vp->v_vflag = VV_ROOT; + + if (kt->kt_tag == KFSdevice) { + spec_node_init(vp, *(dev_t *)kt->kt_data); + } + + uvm_vnp_setsize(vp, 0); + + *new_key = &kfs->kfs_kt; + return 0; +} + extern const struct vnodeopv_desc kernfs_vnodeop_opv_desc; const struct vnodeopv_desc * const kernfs_vnodeopv_descs[] = { @@ -234,6 +310,7 @@ struct vfsops kernfs_vfsops = { .vfs_statvfs = genfs_statvfs, .vfs_sync = kernfs_sync, .vfs_vget = kernfs_vget, + .vfs_loadvnode = kernfs_loadvnode, .vfs_fhtovp = (void *)eopnotsupp, .vfs_vptofh = (void *)eopnotsupp, .vfs_init = kernfs_init, Index: src/sys/miscfs/kernfs/kernfs_vnops.c diff -u src/sys/miscfs/kernfs/kernfs_vnops.c:1.150 src/sys/miscfs/kernfs/kernfs_vnops.c:1.150.2.1 --- src/sys/miscfs/kernfs/kernfs_vnops.c:1.150 Fri Feb 7 15:29:22 2014 +++ src/sys/miscfs/kernfs/kernfs_vnops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kernfs_vnops.c,v 1.150 2014/02/07 15:29:22 hannken Exp $ */ +/* $NetBSD: kernfs_vnops.c,v 1.150.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1992, 1993 @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.150 2014/02/07 15:29:22 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.150.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -59,6 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops #include <miscfs/genfs/genfs.h> #include <miscfs/kernfs/kernfs.h> +#include <miscfs/specfs/specdev.h> #include <uvm/uvm_extern.h> @@ -190,6 +191,8 @@ const struct vnodeopv_entry_desc kernfs_ { &vop_setattr_desc, kernfs_setattr }, /* setattr */ { &vop_read_desc, kernfs_read }, /* read */ { &vop_write_desc, kernfs_write }, /* write */ + { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ + { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */ { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ { &vop_poll_desc, kernfs_poll }, /* poll */ @@ -519,11 +522,8 @@ kernfs_lookup(void *v) break; found: - error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0); - if (error) - return error; - VOP_UNLOCK(*vpp); - return 0; + error = vcache_get(dvp->v_mount, &kt, sizeof(kt), vpp); + return error; case KFSsubdir: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; @@ -653,6 +653,11 @@ kernfs_getattr(void *v) vap->va_bytes = vap->va_size = DEV_BSIZE; break; + case KFSdevice: + vap->va_nlink = 1; + vap->va_rdev = ap->a_vp->v_rdev; + break; + case KFSroot: vap->va_nlink = 1; vap->va_bytes = vap->va_size = DEV_BSIZE; @@ -670,7 +675,6 @@ kernfs_getattr(void *v) case KFSstring: case KFShostname: case KFSavenrun: - case KFSdevice: case KFSmsgbuf: vap->va_nlink = 1; total = 0; @@ -823,28 +827,17 @@ kernfs_ioctl(void *v) static int kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt, - u_int32_t value, struct vop_readdir_args *ap) + struct vop_readdir_args *ap) { struct kernfs_node *kfs; struct vnode *vp; int error; - if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt, - value)) != 0) + if ((error = vcache_get(ap->a_vp->v_mount, &kt, sizeof(kt), &vp)) != 0) return error; - if (kt->kt_tag == KFSdevice) { - struct vattr va; - - error = VOP_GETATTR(vp, &va, ap->a_cred); - if (error != 0) { - return error; - } - d->d_fileno = va.va_fileid; - } else { - kfs = VTOKERN(vp); - d->d_fileno = kfs->kfs_fileno; - } - vput(vp); + kfs = VTOKERN(vp); + d->d_fileno = kfs->kfs_fileno; + vrele(vp); return 0; } @@ -868,7 +861,7 @@ kernfs_setdirentfileno(struct dirent *d, break; } if (ikt != thisdir_kfs->kfs_kt) { - if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0) + if ((error = kernfs_setdirentfileno_kt(d, ikt, ap)) != 0) return error; } else d->d_fileno = thisdir_kfs->kfs_fileno; @@ -1085,8 +1078,17 @@ kernfs_reclaim(void *v) struct vop_reclaim_args /* { struct vnode *a_vp; } */ *ap = v; + struct vnode *vp = ap->a_vp; + struct kernfs_node *kfs = VTOKERN(vp); - return (kernfs_freevp(ap->a_vp)); + vp->v_data = NULL; + vcache_remove(vp->v_mount, &kfs->kfs_kt, sizeof(kfs->kfs_kt)); + mutex_enter(&kfs_lock); + TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list); + mutex_exit(&kfs_lock); + kmem_free(kfs, sizeof(struct kernfs_node)); + + return 0; } /* Index: src/sys/miscfs/nullfs/null_vfsops.c diff -u src/sys/miscfs/nullfs/null_vfsops.c:1.87 src/sys/miscfs/nullfs/null_vfsops.c:1.87.2.1 --- src/sys/miscfs/nullfs/null_vfsops.c:1.87 Sun Mar 23 15:21:16 2014 +++ src/sys/miscfs/nullfs/null_vfsops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: null_vfsops.c,v 1.87 2014/03/23 15:21:16 hannken Exp $ */ +/* $NetBSD: null_vfsops.c,v 1.87.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1999 National Aeronautics & Space Administration @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: null_vfsops.c,v 1.87 2014/03/23 15:21:16 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: null_vfsops.c,v 1.87.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -107,6 +107,8 @@ nullfs_mount(struct mount *mp, const cha struct nameidata nd; int error; + if (args == NULL) + return EINVAL; if (*data_len < sizeof(*args)) return EINVAL; @@ -152,19 +154,13 @@ nullfs_mount(struct mount *mp, const cha nmp->nullm_size = sizeof(struct null_node); nmp->nullm_tag = VT_NULL; nmp->nullm_bypass = layer_bypass; - nmp->nullm_alloc = layer_node_alloc; /* the default alloc is fine */ nmp->nullm_vnodeop_p = null_vnodeop_p; - mutex_init(&nmp->nullm_hashlock, MUTEX_DEFAULT, IPL_NONE); - nmp->nullm_node_hashtbl = hashinit(desiredvnodes, HASH_LIST, true, - &nmp->nullm_node_hash); /* Setup a null node for root vnode. */ VOP_UNLOCK(lowerrootvp); error = layer_node_create(mp, lowerrootvp, &vp); if (error) { vrele(lowerrootvp); - hashdone(nmp->nullm_node_hashtbl, HASH_LIST, - nmp->nullm_node_hash); kmem_free(nmp, sizeof(struct null_mount)); return error; } @@ -203,8 +199,6 @@ nullfs_unmount(struct mount *mp, int mnt vgone(null_rootvp); /* Finally, destroy the mount point structures. */ - hashdone(nmp->nullm_node_hashtbl, HASH_LIST, nmp->nullm_node_hash); - mutex_destroy(&nmp->nullm_hashlock); kmem_free(mp->mnt_data, sizeof(struct null_mount)); mp->mnt_data = NULL; return 0; @@ -227,6 +221,7 @@ struct vfsops nullfs_vfsops = { .vfs_quotactl = layerfs_quotactl, .vfs_statvfs = layerfs_statvfs, .vfs_sync = layerfs_sync, + .vfs_loadvnode = layerfs_loadvnode, .vfs_vget = layerfs_vget, .vfs_fhtovp = layerfs_fhtovp, .vfs_vptofh = layerfs_vptofh, Index: src/sys/miscfs/overlay/overlay_vfsops.c diff -u src/sys/miscfs/overlay/overlay_vfsops.c:1.60 src/sys/miscfs/overlay/overlay_vfsops.c:1.60.2.1 --- src/sys/miscfs/overlay/overlay_vfsops.c:1.60 Sun Mar 23 15:21:16 2014 +++ src/sys/miscfs/overlay/overlay_vfsops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: overlay_vfsops.c,v 1.60 2014/03/23 15:21:16 hannken Exp $ */ +/* $NetBSD: overlay_vfsops.c,v 1.60.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1999, 2000 National Aeronautics & Space Administration @@ -74,7 +74,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: overlay_vfsops.c,v 1.60 2014/03/23 15:21:16 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: overlay_vfsops.c,v 1.60.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -114,6 +114,8 @@ ov_mount(struct mount *mp, const char *p printf("ov_mount(mp = %p)\n", mp); #endif + if (args == NULL) + return EINVAL; if (*data_len < sizeof *args) return EINVAL; @@ -161,11 +163,7 @@ ov_mount(struct mount *mp, const char *p nmp->ovm_size = sizeof (struct overlay_node); nmp->ovm_tag = VT_OVERLAY; nmp->ovm_bypass = layer_bypass; - nmp->ovm_alloc = layer_node_alloc; /* the default alloc is fine */ nmp->ovm_vnodeop_p = overlay_vnodeop_p; - mutex_init(&nmp->ovm_hashlock, MUTEX_DEFAULT, IPL_NONE); - nmp->ovm_node_hashtbl = hashinit(NOVERLAYNODECACHE, HASH_LIST, true, - &nmp->ovm_node_hash); /* * Fix up overlay node for root vnode @@ -177,7 +175,6 @@ ov_mount(struct mount *mp, const char *p */ if (error) { vrele(lowerrootvp); - hashdone(nmp->ovm_node_hashtbl, HASH_LIST, nmp->ovm_node_hash); kmem_free(nmp, sizeof(struct overlay_mount)); return error; } @@ -234,8 +231,6 @@ ov_unmount(struct mount *mp, int mntflag * Finally, throw away the overlay_mount structure */ omp = mp->mnt_data; - mutex_destroy(&omp->ovm_hashlock); - hashdone(omp->ovm_node_hashtbl, HASH_LIST, omp->ovm_node_hash); kmem_free(omp, sizeof(struct overlay_mount)); mp->mnt_data = NULL; return 0; @@ -258,6 +253,7 @@ struct vfsops overlay_vfsops = { .vfs_quotactl = layerfs_quotactl, .vfs_statvfs = layerfs_statvfs, .vfs_sync = layerfs_sync, + .vfs_loadvnode = layerfs_loadvnode, .vfs_vget = layerfs_vget, .vfs_fhtovp = layerfs_fhtovp, .vfs_vptofh = layerfs_vptofh, Index: src/sys/miscfs/procfs/procfs.h diff -u src/sys/miscfs/procfs/procfs.h:1.69 src/sys/miscfs/procfs/procfs.h:1.69.2.1 --- src/sys/miscfs/procfs/procfs.h:1.69 Sat Apr 5 18:42:32 2014 +++ src/sys/miscfs/procfs/procfs.h Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs.h,v 1.69 2014/04/05 18:42:32 christos Exp $ */ +/* $NetBSD: procfs.h,v 1.69.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1993 @@ -118,12 +118,17 @@ typedef enum { /* * control data for the proc file system. */ +struct pfskey { + pfstype pk_type; /* type of procfs node */ + pid_t pk_pid; /* associated process */ + int pk_fd; /* associated fd if not -1 */ +}; struct pfsnode { - LIST_ENTRY(pfsnode) pfs_hash; /* hash chain */ struct vnode *pfs_vnode; /* vnode associated with this pfsnode */ - pfstype pfs_type; /* type of procfs node */ - pid_t pfs_pid; /* associated process */ - int pfs_fd; /* associated fd if not -1 */ + struct pfskey pfs_key; +#define pfs_type pfs_key.pk_type +#define pfs_pid pfs_key.pk_pid +#define pfs_fd pfs_key.pk_fd mode_t pfs_mode; /* mode bits for stat() */ u_long pfs_flags; /* open flags */ u_long pfs_fileno; /* unique file id */ @@ -187,9 +192,7 @@ const vfs_namemap_t *vfs_findname(const int procfs_proc_lock(int, struct proc **, int); void procfs_proc_unlock(struct proc *); -int procfs_freevp(struct vnode *); -int procfs_allocvp(struct mount *, struct vnode **, pid_t, pfstype, int, - struct proc *); +int procfs_allocvp(struct mount *, struct vnode **, pid_t, pfstype, int); int procfs_donote(struct lwp *, struct proc *, struct pfsnode *, struct uio *); int procfs_doregs(struct lwp *, struct lwp *, struct pfsnode *, @@ -232,9 +235,6 @@ int procfs_doversion(struct lwp *, struc struct uio *); void procfs_revoke_vnodes(struct proc *, void *); -void procfs_hashinit(void); -void procfs_hashreinit(void); -void procfs_hashdone(void); int procfs_getfp(struct pfsnode *, struct proc *, struct file **); /* functions to check whether or not files should be displayed */ Index: src/sys/miscfs/procfs/procfs_linux.c diff -u src/sys/miscfs/procfs/procfs_linux.c:1.67 src/sys/miscfs/procfs/procfs_linux.c:1.67.2.1 --- src/sys/miscfs/procfs/procfs_linux.c:1.67 Sat Apr 5 18:42:32 2014 +++ src/sys/miscfs/procfs/procfs_linux.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_linux.c,v 1.67 2014/04/05 18:42:32 christos Exp $ */ +/* $NetBSD: procfs_linux.c,v 1.67.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.67 2014/04/05 18:42:32 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.67.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -400,7 +400,7 @@ out: return error; } -#define USEC_2_TICKS(x) ((x) / 10000) +#define UTIME2TICKS(s,u) (((uint64_t)(s) * 1000000 + (u)) / 10000) /* * Linux compatible /proc/<pid>/stat. Only active when the -o linux @@ -413,12 +413,11 @@ procfs_do_pid_stat(struct lwp *curl, str char *bf; struct proc *p = l->l_proc; int len; - struct tty *tty = p->p_session->s_ttyp; - struct rusage *ru = &p->p_stats->p_ru; struct rusage *cru = &p->p_stats->p_cru; unsigned long stext = 0, etext = 0, sstack = 0; struct timeval rt; struct vmspace *vm; + struct kinfo_proc2 ki; int error = 0; bf = malloc(LBFSZ, M_TEMP, M_WAITOK); @@ -432,65 +431,67 @@ procfs_do_pid_stat(struct lwp *curl, str mutex_enter(proc_lock); mutex_enter(p->p_lock); + fill_kproc2(p, &ki, false); calcru(p, NULL, NULL, NULL, &rt); len = snprintf(bf, LBFSZ, - "%d (%s) %c %d %d %d %lld %d " + "%d (%s) %c %d %d %d %u %d " "%u " - "%lu %lu %lu %lu %lu %lu %lu %lu " - "%d %d %d " - "%lld %lld %lu %lu %" PRIu64 " " + "%"PRIu64" %lu %"PRIu64" %lu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" " + "%d %d %"PRIu64" " + "%lld %"PRIu64" %"PRId64" %lu %"PRIu64" " "%lu %lu %lu " "%u %u " "%u %u %u %u " - "%lu %lu %lu %d %d\n", + "%"PRIu64" %"PRIu64" %"PRIu64" %d %"PRIu64"\n", - p->p_pid, - p->p_comm, - "0IR3SZD"[(p->p_stat > 6) ? 0 : (int)p->p_stat], - (p->p_pptr != NULL) ? p->p_pptr->p_pid : 0, + ki.p_pid, /* 1 pid */ + ki.p_comm, /* 2 tcomm */ + "0RRSTZXR8"[(ki.p_stat > 8) ? 0 : (int)ki.p_stat], /* 3 state */ + ki.p_ppid, /* 4 ppid */ + ki.p__pgid, /* 5 pgrp */ + ki.p_sid, /* 6 sid */ + (ki.p_tdev != (uint32_t)NODEV) ? ki.p_tdev : 0, /* 7 tty_nr */ + ki.p_tpgid, /* 8 tty_pgrp */ - p->p_pgid, - p->p_session->s_sid, - (unsigned long long)(tty ? tty->t_dev : 0), - (tty && tty->t_pgrp) ? tty->t_pgrp->pg_id : 0, + ki.p_flag, /* 9 flags */ - p->p_flag, - - ru->ru_minflt, + ki.p_uru_minflt, /* 10 min_flt */ cru->ru_minflt, - ru->ru_majflt, + ki.p_uru_majflt, /* 12 maj_flt */ cru->ru_majflt, - (long)USEC_2_TICKS(ru->ru_utime.tv_usec), - (long)USEC_2_TICKS(ru->ru_stime.tv_usec), - (long)USEC_2_TICKS(cru->ru_utime.tv_usec), - (long)USEC_2_TICKS(cru->ru_stime.tv_usec), - - l->l_priority, /* XXX: priority */ - p->p_nice - 20, - 0, + UTIME2TICKS(ki.p_uutime_sec, ki.p_uutime_usec), /* 14 utime */ + UTIME2TICKS(ki.p_ustime_sec, ki.p_ustime_usec), /* 15 stime */ + UTIME2TICKS(cru->ru_utime.tv_sec, cru->ru_utime.tv_usec), /* 16 cutime */ + UTIME2TICKS(cru->ru_stime.tv_sec, cru->ru_stime.tv_usec), /* 17 cstime */ + + ki.p_priority, /* XXX: 18 priority */ + ki.p_nice - NZERO, /* 19 nice */ + ki.p_nlwps, /* 20 num_threads */ (long long)rt.tv_sec, - (long long)p->p_stats->p_start.tv_sec, - (unsigned long)(vm->vm_tsize + vm->vm_dsize + vm->vm_ssize), /* size */ - (unsigned long)(vm->vm_rssize), /* resident */ - p->p_rlimit[RLIMIT_RSS].rlim_cur, - - stext, /* start code */ - etext, /* end code */ - sstack, /* mm start stack */ - 0, /* XXX: pc */ - 0, /* XXX: sp */ - p->p_sigpend.sp_set.__bits[0], /* XXX: pending */ - 0, /* XXX: held */ - p->p_sigctx.ps_sigignore.__bits[0], /* ignored */ - p->p_sigctx.ps_sigcatch.__bits[0], /* caught */ - - (unsigned long)(intptr_t)l->l_wchan, - ru->ru_nvcsw, - ru->ru_nivcsw, - p->p_exitsig, - 0); /* XXX: processor */ + UTIME2TICKS(ki.p_ustart_sec, ki.p_ustart_usec), /* 22 start_time */ + ki.p_vm_msize, /* 23 vsize */ + PGTOKB(ki.p_vm_rssize), /* 24 rss */ + p->p_rlimit[RLIMIT_RSS].rlim_cur, /* 25 rsslim */ + + stext, /* 26 start_code */ + etext, /* 27 end_code */ + sstack, /* 28 start_stack */ + + 0, /* XXX: 29 esp */ + 0, /* XXX: 30 eip */ + + ki.p_siglist.__bits[0], /* XXX: 31 pending */ + 0, /* XXX: 32 blocked */ + ki.p_sigignore.__bits[0], /* 33 sigign */ + ki.p_sigcatch.__bits[0], /* 34 sigcatch */ + + ki.p_wchan, /* 35 wchan */ + ki.p_uru_nvcsw, + ki.p_uru_nivcsw, + ki.p_exitsig, /* 38 exit_signal */ + ki.p_cpuid); /* 39 task_cpu */ mutex_exit(p->p_lock); mutex_exit(proc_lock); Index: src/sys/miscfs/procfs/procfs_subr.c diff -u src/sys/miscfs/procfs/procfs_subr.c:1.104 src/sys/miscfs/procfs/procfs_subr.c:1.104.2.1 --- src/sys/miscfs/procfs/procfs_subr.c:1.104 Fri Feb 7 15:29:22 2014 +++ src/sys/miscfs/procfs/procfs_subr.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_subr.c,v 1.104 2014/02/07 15:29:22 hannken Exp $ */ +/* $NetBSD: procfs_subr.c,v 1.104.2.1 2014/08/10 06:56:05 tls Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -102,7 +102,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.104 2014/02/07 15:29:22 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.104.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -118,224 +118,22 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_subr. #include <miscfs/procfs/procfs.h> -void procfs_hashins(struct pfsnode *); -void procfs_hashrem(struct pfsnode *); -struct vnode *procfs_hashget(pid_t, pfstype, int, struct mount *); - -LIST_HEAD(pfs_hashhead, pfsnode) *pfs_hashtbl; -u_long pfs_ihash; /* size of hash table - 1 */ -#define PFSPIDHASH(pid) ((pid) & pfs_ihash) - -kmutex_t pfs_hashlock; -kmutex_t pfs_ihash_lock; - -#define ISSET(t, f) ((t) & (f)) - /* - * allocate a pfsnode/vnode pair. the vnode is - * referenced, and locked. - * - * the pid, pfs_type, and mount point uniquely - * identify a pfsnode. the mount point is needed - * because someone might mount this filesystem - * twice. - * - * all pfsnodes are maintained on a singly-linked - * list. new nodes are only allocated when they cannot - * be found on this list. entries on the list are - * removed when the vfs reclaim entry is called. - * - * a single lock is kept for the entire list. this is - * needed because the getnewvnode() function can block - * waiting for a vnode to become free, in which case there - * may be more than one process trying to get the same - * vnode. this lock is only taken if we are going to - * call getnewvnode, since the kernel itself is single-threaded. - * - * if an entry is found on the list, then call vget() to - * take a reference. this is done because there may be - * zero references to it and so it needs to removed from - * the vnode free list. + * Allocate a pfsnode/vnode pair. The vnode is referenced. + * The pid, type, and file descriptor uniquely identify a pfsnode. */ int procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid, - pfstype pfs_type, int fd, struct proc *p) + pfstype type, int fd) { - struct pfsnode *pfs; - struct vnode *vp; - int error; - - *vpp = procfs_hashget(pid, pfs_type, fd, mp); - if (*vpp != NULL) - return (0); + struct pfskey key; - error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, NULL, &vp); - if (error) { - *vpp = NULL; - return (error); - } - pfs = malloc(sizeof(struct pfsnode), M_TEMP, M_WAITOK); + memset(&key, 0, sizeof(key)); + key.pk_type = type; + key.pk_pid = pid; + key.pk_fd = fd; - mutex_enter(&pfs_hashlock); - if ((*vpp = procfs_hashget(pid, pfs_type, fd, mp)) != NULL) { - mutex_exit(&pfs_hashlock); - ungetnewvnode(vp); - free(pfs, M_TEMP); - return 0; - } - - vp->v_data = pfs; - pfs->pfs_pid = pid; - pfs->pfs_type = pfs_type; - pfs->pfs_vnode = vp; - pfs->pfs_flags = 0; - pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type, fd); - pfs->pfs_fd = fd; - - switch (pfs_type) { - case PFSroot: /* /proc = dr-xr-xr-x */ - vp->v_vflag |= VV_ROOT; - /*FALLTHROUGH*/ - case PFSproc: /* /proc/N = dr-xr-xr-x */ - pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; - vp->v_type = VDIR; - break; - - case PFStask: /* /proc/N/task = dr-xr-xr-x */ - if (fd == -1) { - pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| - S_IROTH|S_IXOTH; - vp->v_type = VDIR; - break; - } - /*FALLTHROUGH*/ - case PFScurproc: /* /proc/curproc = lr-xr-xr-x */ - case PFSself: /* /proc/self = lr-xr-xr-x */ - case PFScwd: /* /proc/N/cwd = lr-xr-xr-x */ - case PFSchroot: /* /proc/N/chroot = lr-xr-xr-x */ - case PFSexe: /* /proc/N/exe = lr-xr-xr-x */ - pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; - vp->v_type = VLNK; - break; - - case PFSfd: - if (fd == -1) { /* /proc/N/fd = dr-x------ */ - pfs->pfs_mode = S_IRUSR|S_IXUSR; - vp->v_type = VDIR; - } else { /* /proc/N/fd/M = [ps-]rw------- */ - file_t *fp; - vnode_t *vxp; - - if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) { - error = EBADF; - goto bad; - } - - pfs->pfs_mode = S_IRUSR|S_IWUSR; - switch (fp->f_type) { - case DTYPE_VNODE: - vxp = fp->f_data; - - /* - * We make symlinks for directories - * to avoid cycles. - */ - if (vxp->v_type == VDIR) - goto symlink; - vp->v_type = vxp->v_type; - break; - case DTYPE_PIPE: - vp->v_type = VFIFO; - break; - case DTYPE_SOCKET: - vp->v_type = VSOCK; - break; - case DTYPE_KQUEUE: - case DTYPE_MISC: - case DTYPE_SEM: - symlink: - pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP| - S_IXGRP|S_IROTH|S_IXOTH; - vp->v_type = VLNK; - break; - default: - error = EOPNOTSUPP; - closef(fp); - goto bad; - } - closef(fp); - } - break; - - case PFSfile: /* /proc/N/file = -rw------- */ - case PFSmem: /* /proc/N/mem = -rw------- */ - case PFSregs: /* /proc/N/regs = -rw------- */ - case PFSfpregs: /* /proc/N/fpregs = -rw------- */ - pfs->pfs_mode = S_IRUSR|S_IWUSR; - vp->v_type = VREG; - break; - - case PFSctl: /* /proc/N/ctl = --w------ */ - case PFSnote: /* /proc/N/note = --w------ */ - case PFSnotepg: /* /proc/N/notepg = --w------ */ - pfs->pfs_mode = S_IWUSR; - vp->v_type = VREG; - break; - - case PFSmap: /* /proc/N/map = -r--r--r-- */ - case PFSmaps: /* /proc/N/maps = -r--r--r-- */ - case PFSstatus: /* /proc/N/status = -r--r--r-- */ - case PFSstat: /* /proc/N/stat = -r--r--r-- */ - case PFScmdline: /* /proc/N/cmdline = -r--r--r-- */ - case PFSemul: /* /proc/N/emul = -r--r--r-- */ - case PFSmeminfo: /* /proc/meminfo = -r--r--r-- */ - case PFScpustat: /* /proc/stat = -r--r--r-- */ - case PFSdevices: /* /proc/devices = -r--r--r-- */ - case PFScpuinfo: /* /proc/cpuinfo = -r--r--r-- */ - case PFSuptime: /* /proc/uptime = -r--r--r-- */ - case PFSmounts: /* /proc/mounts = -r--r--r-- */ - case PFSloadavg: /* /proc/loadavg = -r--r--r-- */ - case PFSstatm: /* /proc/N/statm = -r--r--r-- */ - case PFSversion: /* /proc/version = -r--r--r-- */ - pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH; - vp->v_type = VREG; - break; - -#ifdef __HAVE_PROCFS_MACHDEP - PROCFS_MACHDEP_NODETYPE_CASES - procfs_machdep_allocvp(vp); - break; -#endif - - default: - panic("procfs_allocvp"); - } - - procfs_hashins(pfs); - uvm_vnp_setsize(vp, 0); - mutex_exit(&pfs_hashlock); - - *vpp = vp; - return (0); - - bad: - mutex_exit(&pfs_hashlock); - free(pfs, M_TEMP); - vp->v_data = NULL; - ungetnewvnode(vp); - return (error); -} - -int -procfs_freevp(struct vnode *vp) -{ - struct pfsnode *pfs = VTOPFS(vp); - - procfs_hashrem(pfs); - - free(vp->v_data, M_TEMP); - vp->v_data = NULL; - return (0); + return vcache_get(mp, &key, sizeof(key), vpp); } int @@ -550,132 +348,34 @@ vfs_findname(const vfs_namemap_t *nm, co return (0); } -/* - * Initialize pfsnode hash table. - */ -void -procfs_hashinit(void) -{ - mutex_init(&pfs_hashlock, MUTEX_DEFAULT, IPL_NONE); - mutex_init(&pfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE); - pfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, true, &pfs_ihash); -} - -void -procfs_hashreinit(void) -{ - struct pfsnode *pp; - struct pfs_hashhead *oldhash, *hash; - u_long i, oldmask, mask, val; - - hash = hashinit(desiredvnodes / 4, HASH_LIST, true, &mask); - - mutex_enter(&pfs_ihash_lock); - oldhash = pfs_hashtbl; - oldmask = pfs_ihash; - pfs_hashtbl = hash; - pfs_ihash = mask; - for (i = 0; i <= oldmask; i++) { - while ((pp = LIST_FIRST(&oldhash[i])) != NULL) { - LIST_REMOVE(pp, pfs_hash); - val = PFSPIDHASH(pp->pfs_pid); - LIST_INSERT_HEAD(&hash[val], pp, pfs_hash); - } - } - mutex_exit(&pfs_ihash_lock); - hashdone(oldhash, HASH_LIST, oldmask); -} - -/* - * Free pfsnode hash table. - */ -void -procfs_hashdone(void) -{ - hashdone(pfs_hashtbl, HASH_LIST, pfs_ihash); - mutex_destroy(&pfs_hashlock); - mutex_destroy(&pfs_ihash_lock); -} - -struct vnode * -procfs_hashget(pid_t pid, pfstype type, int fd, struct mount *mp) +static bool +procfs_revoke_selector(void *arg, struct vnode *vp) { - struct pfs_hashhead *ppp; - struct pfsnode *pp; - struct vnode *vp; - -loop: - mutex_enter(&pfs_ihash_lock); - ppp = &pfs_hashtbl[PFSPIDHASH(pid)]; - LIST_FOREACH(pp, ppp, pfs_hash) { - vp = PFSTOV(pp); - if (pid == pp->pfs_pid && pp->pfs_type == type && - pp->pfs_fd == fd && vp->v_mount == mp) { - mutex_enter(vp->v_interlock); - mutex_exit(&pfs_ihash_lock); - if (vget(vp, 0)) - goto loop; - return (vp); - } - } - mutex_exit(&pfs_ihash_lock); - return (NULL); -} - -/* - * Insert the pfsnode into the hash table and lock it. - */ -void -procfs_hashins(struct pfsnode *pp) -{ - struct pfs_hashhead *ppp; + struct proc *p = arg; + struct pfsnode *pfs = VTOPFS(vp); - mutex_enter(&pfs_ihash_lock); - ppp = &pfs_hashtbl[PFSPIDHASH(pp->pfs_pid)]; - LIST_INSERT_HEAD(ppp, pp, pfs_hash); - mutex_exit(&pfs_ihash_lock); -} - -/* - * Remove the pfsnode from the hash table. - */ -void -procfs_hashrem(struct pfsnode *pp) -{ - mutex_enter(&pfs_ihash_lock); - LIST_REMOVE(pp, pfs_hash); - mutex_exit(&pfs_ihash_lock); + return (pfs != NULL && pfs->pfs_pid == p->p_pid); } void procfs_revoke_vnodes(struct proc *p, void *arg) { - struct pfsnode *pfs, *pnext; struct vnode *vp; + struct vnode_iterator *marker; struct mount *mp = (struct mount *)arg; - struct pfs_hashhead *ppp; if (!(p->p_flag & PK_SUGID)) return; - mutex_enter(&pfs_ihash_lock); - ppp = &pfs_hashtbl[PFSPIDHASH(p->p_pid)]; - for (pfs = LIST_FIRST(ppp); pfs; pfs = pnext) { - vp = PFSTOV(pfs); - pnext = LIST_NEXT(pfs, pfs_hash); - if (pfs->pfs_pid != p->p_pid || vp->v_mount != mp) - continue; - mutex_enter(vp->v_interlock); - mutex_exit(&pfs_ihash_lock); - if (vget(vp, 0) != 0) { - mutex_enter(&pfs_ihash_lock); - continue; - } + vfs_vnode_iterator_init(mp, &marker); + + while ((vp = vfs_vnode_iterator_next(marker, + procfs_revoke_selector, p)) != NULL) { VOP_REVOKE(vp, REVOKEALL); vrele(vp); - mutex_enter(&pfs_ihash_lock); } - mutex_exit(&pfs_ihash_lock); + + vfs_vnode_iterator_destroy(marker); } int Index: src/sys/miscfs/procfs/procfs_vfsops.c diff -u src/sys/miscfs/procfs/procfs_vfsops.c:1.90 src/sys/miscfs/procfs/procfs_vfsops.c:1.90.2.1 --- src/sys/miscfs/procfs/procfs_vfsops.c:1.90 Sun Mar 23 15:21:16 2014 +++ src/sys/miscfs/procfs/procfs_vfsops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_vfsops.c,v 1.90 2014/03/23 15:21:16 hannken Exp $ */ +/* $NetBSD: procfs_vfsops.c,v 1.90.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1993 @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.90 2014/03/23 15:21:16 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.90.2.1 2014/08/10 06:56:05 tls Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -95,6 +95,8 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_vfsop #include <sys/signalvar.h> #include <sys/vnode.h> #include <sys/malloc.h> +#include <sys/file.h> +#include <sys/filedesc.h> #include <sys/kauth.h> #include <sys/module.h> @@ -130,6 +132,9 @@ procfs_mount( struct procfs_args *args = data; int error; + if (args == NULL) + return EINVAL; + if (UIO_MX & (UIO_MX-1)) { log(LOG_ERR, "procfs: invalid directory entry size"); return (EINVAL); @@ -201,7 +206,7 @@ procfs_root(struct mount *mp, struct vno { int error; - error = procfs_allocvp(mp, vpp, 0, PFSroot, -1, NULL); + error = procfs_allocvp(mp, vpp, 0, PFSroot, -1); if (error == 0) { error = vn_lock(*vpp, LK_EXCLUSIVE); if (error != 0) { @@ -260,22 +265,187 @@ procfs_vget(struct mount *mp, ino_t ino, return (EOPNOTSUPP); } +int +procfs_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) +{ + int error; + struct pfskey pfskey; + struct pfsnode *pfs; + + KASSERT(key_len == sizeof(pfskey)); + memcpy(&pfskey, key, key_len); + + pfs = kmem_alloc(sizeof(*pfs), KM_SLEEP); + pfs->pfs_pid = pfskey.pk_pid; + pfs->pfs_type = pfskey.pk_type; + pfs->pfs_fd = pfskey.pk_fd; + pfs->pfs_vnode = vp; + pfs->pfs_flags = 0; + pfs->pfs_fileno = + PROCFS_FILENO(pfs->pfs_pid, pfs->pfs_type, pfs->pfs_fd); + vp->v_tag = VT_PROCFS; + vp->v_op = procfs_vnodeop_p; + vp->v_data = pfs; + + switch (pfs->pfs_type) { + case PFSroot: /* /proc = dr-xr-xr-x */ + vp->v_vflag |= VV_ROOT; + /*FALLTHROUGH*/ + case PFSproc: /* /proc/N = dr-xr-xr-x */ + pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; + vp->v_type = VDIR; + break; + + case PFStask: /* /proc/N/task = dr-xr-xr-x */ + if (pfs->pfs_fd == -1) { + pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| + S_IROTH|S_IXOTH; + vp->v_type = VDIR; + break; + } + /*FALLTHROUGH*/ + case PFScurproc: /* /proc/curproc = lr-xr-xr-x */ + case PFSself: /* /proc/self = lr-xr-xr-x */ + case PFScwd: /* /proc/N/cwd = lr-xr-xr-x */ + case PFSchroot: /* /proc/N/chroot = lr-xr-xr-x */ + case PFSexe: /* /proc/N/exe = lr-xr-xr-x */ + pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; + vp->v_type = VLNK; + break; + + case PFSfd: + if (pfs->pfs_fd == -1) { /* /proc/N/fd = dr-x------ */ + pfs->pfs_mode = S_IRUSR|S_IXUSR; + vp->v_type = VDIR; + } else { /* /proc/N/fd/M = [ps-]rw------- */ + file_t *fp; + vnode_t *vxp; + struct proc *p; + + mutex_enter(proc_lock); + p = proc_find(pfs->pfs_pid); + mutex_exit(proc_lock); + if (p == NULL) { + error = ENOENT; + goto bad; + } + KASSERT(rw_read_held(&p->p_reflock)); + if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) { + error = EBADF; + goto bad; + } + + pfs->pfs_mode = S_IRUSR|S_IWUSR; + switch (fp->f_type) { + case DTYPE_VNODE: + vxp = fp->f_data; + + /* + * We make symlinks for directories + * to avoid cycles. + */ + if (vxp->v_type == VDIR) + goto symlink; + vp->v_type = vxp->v_type; + break; + case DTYPE_PIPE: + vp->v_type = VFIFO; + break; + case DTYPE_SOCKET: + vp->v_type = VSOCK; + break; + case DTYPE_KQUEUE: + case DTYPE_MISC: + case DTYPE_SEM: + symlink: + pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP| + S_IXGRP|S_IROTH|S_IXOTH; + vp->v_type = VLNK; + break; + default: + error = EOPNOTSUPP; + closef(fp); + goto bad; + } + closef(fp); + } + break; + + case PFSfile: /* /proc/N/file = -rw------- */ + case PFSmem: /* /proc/N/mem = -rw------- */ + case PFSregs: /* /proc/N/regs = -rw------- */ + case PFSfpregs: /* /proc/N/fpregs = -rw------- */ + pfs->pfs_mode = S_IRUSR|S_IWUSR; + vp->v_type = VREG; + break; + + case PFSctl: /* /proc/N/ctl = --w------ */ + case PFSnote: /* /proc/N/note = --w------ */ + case PFSnotepg: /* /proc/N/notepg = --w------ */ + pfs->pfs_mode = S_IWUSR; + vp->v_type = VREG; + break; + + case PFSmap: /* /proc/N/map = -r--r--r-- */ + case PFSmaps: /* /proc/N/maps = -r--r--r-- */ + case PFSstatus: /* /proc/N/status = -r--r--r-- */ + case PFSstat: /* /proc/N/stat = -r--r--r-- */ + case PFScmdline: /* /proc/N/cmdline = -r--r--r-- */ + case PFSemul: /* /proc/N/emul = -r--r--r-- */ + case PFSmeminfo: /* /proc/meminfo = -r--r--r-- */ + case PFScpustat: /* /proc/stat = -r--r--r-- */ + case PFSdevices: /* /proc/devices = -r--r--r-- */ + case PFScpuinfo: /* /proc/cpuinfo = -r--r--r-- */ + case PFSuptime: /* /proc/uptime = -r--r--r-- */ + case PFSmounts: /* /proc/mounts = -r--r--r-- */ + case PFSloadavg: /* /proc/loadavg = -r--r--r-- */ + case PFSstatm: /* /proc/N/statm = -r--r--r-- */ + case PFSversion: /* /proc/version = -r--r--r-- */ + pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH; + vp->v_type = VREG; + break; + +#ifdef __HAVE_PROCFS_MACHDEP + PROCFS_MACHDEP_NODETYPE_CASES + procfs_machdep_allocvp(vp); + break; +#endif + + default: + panic("procfs_allocvp"); + } + + uvm_vnp_setsize(vp, 0); + *new_key = &pfs->pfs_key; + + return 0; + +bad: + vp->v_tag =VT_NON; + vp->v_type = VNON; + vp->v_op = NULL; + vp->v_data = NULL; + kmem_free(pfs, sizeof(*pfs)); + return error; +} + void procfs_init(void) { - procfs_hashinit(); + } void procfs_reinit(void) { - procfs_hashreinit(); + } void procfs_done(void) { - procfs_hashdone(); + } extern const struct vnodeopv_desc procfs_vnodeop_opv_desc; @@ -296,6 +466,7 @@ struct vfsops procfs_vfsops = { .vfs_statvfs = procfs_statvfs, .vfs_sync = procfs_sync, .vfs_vget = procfs_vget, + .vfs_loadvnode = procfs_loadvnode, .vfs_fhtovp = (void *)eopnotsupp, .vfs_vptofh = (void *)eopnotsupp, .vfs_init = procfs_init, Index: src/sys/miscfs/procfs/procfs_vnops.c diff -u src/sys/miscfs/procfs/procfs_vnops.c:1.189 src/sys/miscfs/procfs/procfs_vnops.c:1.189.2.1 --- src/sys/miscfs/procfs/procfs_vnops.c:1.189 Fri Feb 7 15:29:22 2014 +++ src/sys/miscfs/procfs/procfs_vnops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_vnops.c,v 1.189 2014/02/07 15:29:22 hannken Exp $ */ +/* $NetBSD: procfs_vnops.c,v 1.189.2.1 2014/08/10 06:56:05 tls Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -105,7 +105,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.189 2014/02/07 15:29:22 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.189.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -259,6 +259,8 @@ const struct vnodeopv_entry_desc procfs_ { &vop_setattr_desc, procfs_setattr }, /* setattr */ { &vop_read_desc, procfs_read }, /* read */ { &vop_write_desc, procfs_write }, /* write */ + { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ + { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */ { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */ { &vop_poll_desc, procfs_poll }, /* poll */ @@ -439,8 +441,18 @@ procfs_reclaim(void *v) struct vop_reclaim_args /* { struct vnode *a_vp; } */ *ap = v; + struct vnode *vp = ap->a_vp; + struct pfsnode *pfs = VTOPFS(vp); - return (procfs_freevp(ap->a_vp)); + /* + * To interlock with procfs_revoke_vnodes(). + */ + mutex_enter(vp->v_interlock); + vp->v_data = NULL; + mutex_exit(vp->v_interlock); + vcache_remove(vp->v_mount, &pfs->pfs_key, sizeof(pfs->pfs_key)); + kmem_free(pfs, sizeof(*pfs)); + return 0; } /* @@ -1035,7 +1047,7 @@ procfs_lookup(void *v) if (i != nproc_root_targets) { error = procfs_allocvp(dvp->v_mount, vpp, 0, - pt->pt_pfstype, -1, NULL); + pt->pt_pfstype, -1); return (error); } @@ -1055,14 +1067,14 @@ procfs_lookup(void *v) if (procfs_proc_lock(pid, &p, ESRCH) != 0) break; - error = procfs_allocvp(dvp->v_mount, vpp, vnpid, type, -1, p); + error = procfs_allocvp(dvp->v_mount, vpp, vnpid, type, -1); procfs_proc_unlock(p); return (error); case PFSproc: if (cnp->cn_flags & ISDOTDOT) { error = procfs_allocvp(dvp->v_mount, vpp, 0, PFSroot, - -1, NULL); + -1); return (error); } @@ -1110,7 +1122,7 @@ procfs_lookup(void *v) } error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - pt->pt_pfstype, -1, p); + pt->pt_pfstype, -1); procfs_proc_unlock(p); return (error); @@ -1123,7 +1135,7 @@ procfs_lookup(void *v) if (cnp->cn_flags & ISDOTDOT) { error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - PFSproc, -1, p); + PFSproc, -1); procfs_proc_unlock(p); return (error); } @@ -1147,7 +1159,7 @@ procfs_lookup(void *v) closef(fp); error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - PFSfd, fd, p); + PFSfd, fd); procfs_proc_unlock(p); return error; } @@ -1159,7 +1171,7 @@ procfs_lookup(void *v) if (cnp->cn_flags & ISDOTDOT) { error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - PFSproc, -1, p); + PFSproc, -1); procfs_proc_unlock(p); return (error); } @@ -1170,7 +1182,7 @@ procfs_lookup(void *v) return ENOENT; } error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - PFStask, 0, p); + PFStask, 0); procfs_proc_unlock(p); return error; } Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.143 src/sys/miscfs/specfs/spec_vnops.c:1.143.2.1 --- src/sys/miscfs/specfs/spec_vnops.c:1.143 Mon Mar 24 13:42:40 2014 +++ src/sys/miscfs/specfs/spec_vnops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.143 2014/03/24 13:42:40 hannken Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.143.2.1 2014/08/10 06:56:05 tls Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.143 2014/03/24 13:42:40 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.143.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -123,6 +123,8 @@ const struct vnodeopv_entry_desc spec_vn { &vop_setattr_desc, spec_setattr }, /* setattr */ { &vop_read_desc, spec_read }, /* read */ { &vop_write_desc, spec_write }, /* write */ + { &vop_fallocate_desc, spec_fallocate }, /* fallocate */ + { &vop_fdiscard_desc, spec_fdiscard }, /* fdiscard */ { &vop_fcntl_desc, spec_fcntl }, /* fcntl */ { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ { &vop_poll_desc, spec_poll }, /* poll */ @@ -838,6 +840,46 @@ spec_write(void *v) } /* + * fdiscard, which on disk devices becomes TRIM. + */ +int +spec_fdiscard(void *v) +{ + struct vop_fdiscard_args /* { + struct vnode *a_vp; + off_t a_pos; + off_t a_len; + } */ *ap = v; + struct vnode *vp; + dev_t dev; + + vp = ap->a_vp; + dev = NODEV; + + mutex_enter(vp->v_interlock); + if (vdead_check(vp, VDEAD_NOWAIT) == 0 && vp->v_specnode != NULL) { + dev = vp->v_rdev; + } + mutex_exit(vp->v_interlock); + + if (dev == NODEV) { + return ENXIO; + } + + switch (vp->v_type) { + case VCHR: + // this is not stored for character devices + //KASSERT(vp == vp->v_specnode->sn_dev->sd_cdevvp); + return cdev_discard(dev, ap->a_pos, ap->a_len); + case VBLK: + KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); + return bdev_discard(dev, ap->a_pos, ap->a_len); + default: + panic("spec_fdiscard: not a device\n"); + } +} + +/* * Device ioctl operation. */ /* ARGSUSED */ Index: src/sys/miscfs/specfs/specdev.h diff -u src/sys/miscfs/specfs/specdev.h:1.42 src/sys/miscfs/specfs/specdev.h:1.42.2.1 --- src/sys/miscfs/specfs/specdev.h:1.42 Mon Sep 30 18:58:00 2013 +++ src/sys/miscfs/specfs/specdev.h Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: specdev.h,v 1.42 2013/09/30 18:58:00 hannken Exp $ */ +/* $NetBSD: specdev.h,v 1.42.2.1 2014/08/10 06:56:05 tls Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -119,6 +119,8 @@ int spec_close(void *); #define spec_setattr genfs_ebadf int spec_read(void *); int spec_write(void *); +#define spec_fallocate genfs_eopnotsupp +int spec_fdiscard(void *); #define spec_fcntl genfs_fcntl int spec_ioctl(void *); int spec_poll(void *); Index: src/sys/miscfs/umapfs/umap_vfsops.c diff -u src/sys/miscfs/umapfs/umap_vfsops.c:1.91 src/sys/miscfs/umapfs/umap_vfsops.c:1.91.2.1 --- src/sys/miscfs/umapfs/umap_vfsops.c:1.91 Sun Mar 23 15:21:16 2014 +++ src/sys/miscfs/umapfs/umap_vfsops.c Sun Aug 10 06:56:05 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: umap_vfsops.c,v 1.91 2014/03/23 15:21:16 hannken Exp $ */ +/* $NetBSD: umap_vfsops.c,v 1.91.2.1 2014/08/10 06:56:05 tls Exp $ */ /* * Copyright (c) 1992, 1993 @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: umap_vfsops.c,v 1.91 2014/03/23 15:21:16 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: umap_vfsops.c,v 1.91.2.1 2014/08/10 06:56:05 tls Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -81,6 +81,8 @@ umapfs_mount(struct mount *mp, const cha int i; #endif + if (args == NULL) + return EINVAL; if (*data_len < sizeof *args) return EINVAL; @@ -195,12 +197,7 @@ umapfs_mount(struct mount *mp, const cha amp->umapm_size = sizeof(struct umap_node); amp->umapm_tag = VT_UMAP; amp->umapm_bypass = umap_bypass; - amp->umapm_alloc = layer_node_alloc; /* the default alloc is fine */ amp->umapm_vnodeop_p = umap_vnodeop_p; - mutex_init(&->umapm_hashlock, MUTEX_DEFAULT, IPL_NONE); - amp->umapm_node_hashtbl = hashinit(NUMAPNODECACHE, HASH_LIST, true, - &->umapm_node_hash); - /* * fix up umap node for root vnode. @@ -212,8 +209,6 @@ umapfs_mount(struct mount *mp, const cha */ if (error) { vrele(lowerrootvp); - hashdone(amp->umapm_node_hashtbl, HASH_LIST, - amp->umapm_node_hash); kmem_free(amp, sizeof(struct umap_mount)); return error; } @@ -269,8 +264,6 @@ umapfs_unmount(struct mount *mp, int mnt /* * Finally, throw away the umap_mount structure */ - mutex_destroy(&->umapm_hashlock); - hashdone(amp->umapm_node_hashtbl, HASH_LIST, amp->umapm_node_hash); kmem_free(amp, sizeof(struct umap_mount)); mp->mnt_data = NULL; return 0; @@ -293,6 +286,7 @@ struct vfsops umapfs_vfsops = { .vfs_quotactl = layerfs_quotactl, .vfs_statvfs = layerfs_statvfs, .vfs_sync = layerfs_sync, + .vfs_loadvnode = layerfs_loadvnode, .vfs_vget = layerfs_vget, .vfs_fhtovp = layerfs_fhtovp, .vfs_vptofh = layerfs_vptofh,