1*21864bc5SMatthew Dillon /* 2*21864bc5SMatthew Dillon * Copyright (c) 2009 The DragonFly Project. All rights reserved. 3*21864bc5SMatthew Dillon * 4*21864bc5SMatthew Dillon * This code is derived from software contributed to The DragonFly Project 5*21864bc5SMatthew Dillon * by Alex Hornung <ahornung@gmail.com> 6*21864bc5SMatthew Dillon * 7*21864bc5SMatthew Dillon * Redistribution and use in source and binary forms, with or without 8*21864bc5SMatthew Dillon * modification, are permitted provided that the following conditions 9*21864bc5SMatthew Dillon * are met: 10*21864bc5SMatthew Dillon * 11*21864bc5SMatthew Dillon * 1. Redistributions of source code must retain the above copyright 12*21864bc5SMatthew Dillon * notice, this list of conditions and the following disclaimer. 13*21864bc5SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 14*21864bc5SMatthew Dillon * notice, this list of conditions and the following disclaimer in 15*21864bc5SMatthew Dillon * the documentation and/or other materials provided with the 16*21864bc5SMatthew Dillon * distribution. 17*21864bc5SMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 18*21864bc5SMatthew Dillon * contributors may be used to endorse or promote products derived 19*21864bc5SMatthew Dillon * from this software without specific, prior written permission. 20*21864bc5SMatthew Dillon * 21*21864bc5SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*21864bc5SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*21864bc5SMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24*21864bc5SMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25*21864bc5SMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26*21864bc5SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27*21864bc5SMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28*21864bc5SMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29*21864bc5SMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30*21864bc5SMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31*21864bc5SMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*21864bc5SMatthew Dillon * SUCH DAMAGE. 33*21864bc5SMatthew Dillon */ 34*21864bc5SMatthew Dillon #include <sys/param.h> 35*21864bc5SMatthew Dillon #include <sys/systm.h> 36*21864bc5SMatthew Dillon #include <sys/kernel.h> 37*21864bc5SMatthew Dillon #include <sys/mount.h> 38*21864bc5SMatthew Dillon #include <sys/vnode.h> 39*21864bc5SMatthew Dillon #include <sys/jail.h> 40*21864bc5SMatthew Dillon #include <vfs/devfs/devfs.h> 41*21864bc5SMatthew Dillon 42*21864bc5SMatthew Dillon MALLOC_DECLARE(M_DEVFS); 43*21864bc5SMatthew Dillon 44*21864bc5SMatthew Dillon extern struct vop_ops devfs_vnode_norm_vops; 45*21864bc5SMatthew Dillon extern struct vop_ops devfs_vnode_dev_vops; 46*21864bc5SMatthew Dillon extern struct lock devfs_lock; 47*21864bc5SMatthew Dillon 48*21864bc5SMatthew Dillon static int devfs_mount (struct mount *mp, char *path, caddr_t data, 49*21864bc5SMatthew Dillon struct ucred *cred); 50*21864bc5SMatthew Dillon static int devfs_statfs (struct mount *mp, struct statfs *sbp, 51*21864bc5SMatthew Dillon struct ucred *cred); 52*21864bc5SMatthew Dillon static int devfs_unmount (struct mount *mp, int mntflags); 53*21864bc5SMatthew Dillon int devfs_root(struct mount *mp, struct vnode **vpp); 54*21864bc5SMatthew Dillon 55*21864bc5SMatthew Dillon /* 56*21864bc5SMatthew Dillon * VFS Operations. 57*21864bc5SMatthew Dillon * 58*21864bc5SMatthew Dillon * mount system call 59*21864bc5SMatthew Dillon */ 60*21864bc5SMatthew Dillon /* ARGSUSED */ 61*21864bc5SMatthew Dillon static int 62*21864bc5SMatthew Dillon devfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) 63*21864bc5SMatthew Dillon { 64*21864bc5SMatthew Dillon size_t size; 65*21864bc5SMatthew Dillon 66*21864bc5SMatthew Dillon devfs_debug(DEVFS_DEBUG_DEBUG, "(vfsops) devfs_mount() called!\n"); 67*21864bc5SMatthew Dillon 68*21864bc5SMatthew Dillon if (mp->mnt_flag & MNT_UPDATE) 69*21864bc5SMatthew Dillon return (EOPNOTSUPP); 70*21864bc5SMatthew Dillon 71*21864bc5SMatthew Dillon 72*21864bc5SMatthew Dillon mp->mnt_flag |= MNT_LOCAL; 73*21864bc5SMatthew Dillon mp->mnt_kern_flag |= MNTK_NOSTKMNT; 74*21864bc5SMatthew Dillon mp->mnt_data = 0; 75*21864bc5SMatthew Dillon vfs_getnewfsid(mp); 76*21864bc5SMatthew Dillon 77*21864bc5SMatthew Dillon size = sizeof("devfs") - 1; 78*21864bc5SMatthew Dillon bcopy("devfs", mp->mnt_stat.f_mntfromname, size); 79*21864bc5SMatthew Dillon bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 80*21864bc5SMatthew Dillon devfs_statfs(mp, &mp->mnt_stat, cred); 81*21864bc5SMatthew Dillon 82*21864bc5SMatthew Dillon //XXX: save other mount info passed from userland or so. 83*21864bc5SMatthew Dillon mp->mnt_data = kmalloc(sizeof(struct devfs_mnt_data), M_DEVFS, M_WAITOK); 84*21864bc5SMatthew Dillon 85*21864bc5SMatthew Dillon lockmgr(&devfs_lock, LK_EXCLUSIVE); 86*21864bc5SMatthew Dillon DEVFS_MNTDATA(mp)->jailed = jailed(cred); 87*21864bc5SMatthew Dillon DEVFS_MNTDATA(mp)->mntonnamelen = strlen(mp->mnt_stat.f_mntonname); 88*21864bc5SMatthew Dillon DEVFS_MNTDATA(mp)->leak_count = 0; 89*21864bc5SMatthew Dillon DEVFS_MNTDATA(mp)->root_node = devfs_allocp(Proot, "", NULL, mp, NULL); 90*21864bc5SMatthew Dillon KKASSERT(DEVFS_MNTDATA(mp)->root_node); 91*21864bc5SMatthew Dillon TAILQ_INIT(DEVFS_ORPHANLIST(mp)); 92*21864bc5SMatthew Dillon lockmgr(&devfs_lock, LK_RELEASE); 93*21864bc5SMatthew Dillon 94*21864bc5SMatthew Dillon vfs_add_vnodeops(mp, &devfs_vnode_norm_vops, &mp->mnt_vn_norm_ops); 95*21864bc5SMatthew Dillon vfs_add_vnodeops(mp, &devfs_vnode_dev_vops, &mp->mnt_vn_spec_ops); 96*21864bc5SMatthew Dillon 97*21864bc5SMatthew Dillon devfs_debug(DEVFS_DEBUG_DEBUG, "calling devfs_mount_add\n"); 98*21864bc5SMatthew Dillon devfs_mount_add(DEVFS_MNTDATA(mp)); 99*21864bc5SMatthew Dillon 100*21864bc5SMatthew Dillon return (0); 101*21864bc5SMatthew Dillon } 102*21864bc5SMatthew Dillon 103*21864bc5SMatthew Dillon /* 104*21864bc5SMatthew Dillon * unmount system call 105*21864bc5SMatthew Dillon */ 106*21864bc5SMatthew Dillon static int 107*21864bc5SMatthew Dillon devfs_unmount(struct mount *mp, int mntflags) 108*21864bc5SMatthew Dillon { 109*21864bc5SMatthew Dillon int error = 0; 110*21864bc5SMatthew Dillon int flags = 0; 111*21864bc5SMatthew Dillon 112*21864bc5SMatthew Dillon devfs_debug(DEVFS_DEBUG_DEBUG, "(vfsops) devfs_unmount() called!\n"); 113*21864bc5SMatthew Dillon 114*21864bc5SMatthew Dillon if (mntflags & MNT_FORCE) 115*21864bc5SMatthew Dillon flags |= FORCECLOSE; 116*21864bc5SMatthew Dillon 117*21864bc5SMatthew Dillon error = vflush(mp, 0, flags); 118*21864bc5SMatthew Dillon 119*21864bc5SMatthew Dillon if (error) 120*21864bc5SMatthew Dillon return (error); 121*21864bc5SMatthew Dillon 122*21864bc5SMatthew Dillon devfs_debug(DEVFS_DEBUG_DEBUG, "There were %d devfs_node orphans left\n", devfs_tracer_orphan_count(mp, 1)); 123*21864bc5SMatthew Dillon devfs_debug(DEVFS_DEBUG_DEBUG, "There are %d devfs_node orphans left\n", devfs_tracer_orphan_count(mp, 0)); 124*21864bc5SMatthew Dillon devfs_mount_del(DEVFS_MNTDATA(mp)); 125*21864bc5SMatthew Dillon kfree(mp->mnt_data, M_DEVFS); 126*21864bc5SMatthew Dillon 127*21864bc5SMatthew Dillon return (0); 128*21864bc5SMatthew Dillon } 129*21864bc5SMatthew Dillon 130*21864bc5SMatthew Dillon /* 131*21864bc5SMatthew Dillon * Sets *vpp to the root procfs vnode, referenced and exclusively locked 132*21864bc5SMatthew Dillon */ 133*21864bc5SMatthew Dillon int 134*21864bc5SMatthew Dillon devfs_root(struct mount *mp, struct vnode **vpp) 135*21864bc5SMatthew Dillon { 136*21864bc5SMatthew Dillon int ret; 137*21864bc5SMatthew Dillon devfs_debug(DEVFS_DEBUG_DEBUG, "(vfsops) devfs_root() called!\n"); 138*21864bc5SMatthew Dillon lockmgr(&devfs_lock, LK_EXCLUSIVE); 139*21864bc5SMatthew Dillon ret = devfs_allocv(vpp, DEVFS_MNTDATA(mp)->root_node); 140*21864bc5SMatthew Dillon lockmgr(&devfs_lock, LK_RELEASE); 141*21864bc5SMatthew Dillon return ret; 142*21864bc5SMatthew Dillon } 143*21864bc5SMatthew Dillon 144*21864bc5SMatthew Dillon /* 145*21864bc5SMatthew Dillon * Get file system statistics. 146*21864bc5SMatthew Dillon */ 147*21864bc5SMatthew Dillon static int 148*21864bc5SMatthew Dillon devfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) 149*21864bc5SMatthew Dillon { 150*21864bc5SMatthew Dillon devfs_debug(DEVFS_DEBUG_DEBUG, "(vfsops) devfs_stat() called!\n"); 151*21864bc5SMatthew Dillon sbp->f_bsize = DEV_BSIZE; 152*21864bc5SMatthew Dillon sbp->f_iosize = DEV_BSIZE; 153*21864bc5SMatthew Dillon sbp->f_blocks = 2; /* avoid divide by zero in some df's */ 154*21864bc5SMatthew Dillon sbp->f_bfree = 0; 155*21864bc5SMatthew Dillon sbp->f_bavail = 0; 156*21864bc5SMatthew Dillon sbp->f_files = 0; 157*21864bc5SMatthew Dillon sbp->f_ffree = 0; 158*21864bc5SMatthew Dillon 159*21864bc5SMatthew Dillon if (sbp != &mp->mnt_stat) { 160*21864bc5SMatthew Dillon sbp->f_type = mp->mnt_vfc->vfc_typenum; 161*21864bc5SMatthew Dillon bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 162*21864bc5SMatthew Dillon bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 163*21864bc5SMatthew Dillon } 164*21864bc5SMatthew Dillon 165*21864bc5SMatthew Dillon return (0); 166*21864bc5SMatthew Dillon } 167*21864bc5SMatthew Dillon 168*21864bc5SMatthew Dillon static struct vfsops devfs_vfsops = { 169*21864bc5SMatthew Dillon .vfs_mount = devfs_mount, 170*21864bc5SMatthew Dillon .vfs_unmount = devfs_unmount, 171*21864bc5SMatthew Dillon .vfs_root = devfs_root, 172*21864bc5SMatthew Dillon .vfs_statfs = devfs_statfs, 173*21864bc5SMatthew Dillon .vfs_sync = vfs_stdsync 174*21864bc5SMatthew Dillon }; 175*21864bc5SMatthew Dillon 176*21864bc5SMatthew Dillon VFS_SET(devfs_vfsops, devfs, VFCF_SYNTHETIC); 177*21864bc5SMatthew Dillon MODULE_VERSION(devfs, 1); 178