portal_vfsops.c revision 162647
1139776Simp/*- 222521Sdyson * Copyright (c) 1992, 1993, 1995 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software donated to Berkeley by 61541Srgrimes * Jan-Simon Pendry. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 4. Neither the name of the University nor the names of its contributors 171541Srgrimes * may be used to endorse or promote products derived from this software 181541Srgrimes * without specific prior written permission. 191541Srgrimes * 201541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301541Srgrimes * SUCH DAMAGE. 311541Srgrimes * 3222521Sdyson * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95 331541Srgrimes * 3450477Speter * $FreeBSD: head/sys/fs/portalfs/portal_vfsops.c 162647 2006-09-26 04:12:49Z tegge $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes/* 381541Srgrimes * Portal Filesystem 391541Srgrimes */ 401541Srgrimes 411541Srgrimes#include <sys/param.h> 421541Srgrimes#include <sys/systm.h> 4376166Smarkm#include <sys/domain.h> 4476166Smarkm#include <sys/filedesc.h> 453034Sdg#include <sys/kernel.h> 4676166Smarkm#include <sys/lock.h> 4789316Salfred#include <sys/mutex.h> 4876166Smarkm#include <sys/malloc.h> 4976166Smarkm#include <sys/file.h> /* Must come after sys/malloc.h */ 5076166Smarkm#include <sys/mount.h> 511541Srgrimes#include <sys/proc.h> 5276166Smarkm#include <sys/protosw.h> 531541Srgrimes#include <sys/socket.h> 541541Srgrimes#include <sys/socketvar.h> 5576166Smarkm#include <sys/vnode.h> 5676166Smarkm 5777031Sru#include <fs/portalfs/portal.h> 581541Srgrimes 59151897Srwatsonstatic MALLOC_DEFINE(M_PORTALFSMNT, "portal_mount", "PORTAL mount structure"); 6030354Sphk 61116271Sphkstatic vfs_unmount_t portal_unmount; 62116271Sphkstatic vfs_root_t portal_root; 63116271Sphkstatic vfs_statfs_t portal_statfs; 6412335Sbde 65138489Sphkstatic const char *portal_opts[] = { 66138489Sphk "socket", "config", 67138489Sphk NULL 68138489Sphk}; 69138489Sphk 70138489Sphkstatic int 71138489Sphkportal_cmount(struct mntarg *ma, void *data, int flags, struct thread *td) 72138489Sphk{ 73138489Sphk struct portal_args args; 74138489Sphk int error; 75138489Sphk 76138489Sphk if (data == NULL) 77138489Sphk return (EINVAL); 78138489Sphk error = copyin(data, &args, sizeof args); 79138489Sphk if (error) 80138489Sphk return (error); 81138489Sphk 82138489Sphk ma = mount_argf(ma, "socket", "%d", args.pa_socket); 83138489Sphk ma = mount_argsu(ma, "config", args.pa_config, MAXPATHLEN); 84138489Sphk error = kernel_mount(ma, flags); 85138489Sphk 86138489Sphk return (error); 87138489Sphk} 88138489Sphk 891541Srgrimes/* 901541Srgrimes * Mount the per-process file descriptors (/dev/fd) 911541Srgrimes */ 9212769Sphkstatic int 93138489Sphkportal_mount(struct mount *mp, struct thread *td) 941541Srgrimes{ 951541Srgrimes struct file *fp; 961541Srgrimes struct portalmount *fmp; 971541Srgrimes struct socket *so; 981541Srgrimes struct vnode *rvp; 9916312Sdg struct portalnode *pn; 100138489Sphk int error, v; 101138489Sphk char *p; 1021541Srgrimes 103138489Sphk if (vfs_filteropt(mp->mnt_optnew, portal_opts)) 104138489Sphk return (EINVAL); 1051541Srgrimes 106138489Sphk error = vfs_scanopt(mp->mnt_optnew, "socket", "%d", &v); 107138489Sphk if (error != 1) 108138489Sphk return (EINVAL); 109138489Sphk error = vfs_getopt(mp->mnt_optnew, "config", (void **)&p, NULL); 1103496Sphk if (error) 1111541Srgrimes return (error); 1121541Srgrimes 113138489Sphk if ((error = fget(td, v, &fp)) != 0) 1141541Srgrimes return (error); 11586872Sdillon if (fp->f_type != DTYPE_SOCKET) { 11686872Sdillon fdrop(fp, td); 11786872Sdillon return(ENOTSOCK); 11886872Sdillon } 119109153Sdillon so = fp->f_data; /* XXX race against userland */ 12069149Sjlemon if (so->so_proto->pr_domain->dom_family != AF_UNIX) { 12183366Sjulian fdrop(fp, td); 1221541Srgrimes return (ESOCKTNOSUPPORT); 12369149Sjlemon } 1241541Srgrimes 12516312Sdg MALLOC(pn, struct portalnode *, sizeof(struct portalnode), 126111119Simp M_TEMP, M_WAITOK); 12716312Sdg 12816312Sdg MALLOC(fmp, struct portalmount *, sizeof(struct portalmount), 129111119Simp M_PORTALFSMNT, M_WAITOK); /* XXX */ 13016312Sdg 131138290Sphk error = getnewvnode("portal", mp, &portal_vnodeops, &rvp); /* XXX */ 13216312Sdg if (error) { 13330354Sphk FREE(fmp, M_PORTALFSMNT); 13416312Sdg FREE(pn, M_TEMP); 13583366Sjulian fdrop(fp, td); 1361541Srgrimes return (error); 13716312Sdg } 1381541Srgrimes 13916312Sdg rvp->v_data = pn; 1401541Srgrimes rvp->v_type = VDIR; 141101308Sjeff rvp->v_vflag |= VV_ROOT; 1421541Srgrimes VTOPORTAL(rvp)->pt_arg = 0; 1431541Srgrimes VTOPORTAL(rvp)->pt_size = 0; 1441541Srgrimes VTOPORTAL(rvp)->pt_fileid = PORTAL_ROOTFILEID; 1451541Srgrimes fmp->pm_root = rvp; 14689306Salfred fhold(fp); 14789306Salfred fmp->pm_server = fp; 1481541Srgrimes 149162647Stegge MNT_ILOCK(mp); 1501541Srgrimes mp->mnt_flag |= MNT_LOCAL; 151162647Stegge MNT_IUNLOCK(mp); 1521541Srgrimes mp->mnt_data = (qaddr_t) fmp; 15322521Sdyson vfs_getnewfsid(mp); 1541541Srgrimes 155138489Sphk vfs_mountedfrom(mp, p); 15683366Sjulian fdrop(fp, td); 1571541Srgrimes return (0); 1581541Srgrimes} 1591541Srgrimes 16012769Sphkstatic int 16183366Sjulianportal_unmount(mp, mntflags, td) 1621541Srgrimes struct mount *mp; 1631541Srgrimes int mntflags; 16483366Sjulian struct thread *td; 1651541Srgrimes{ 1661541Srgrimes int error, flags = 0; 1671541Srgrimes 1681541Srgrimes 16922521Sdyson if (mntflags & MNT_FORCE) 1701541Srgrimes flags |= FORCECLOSE; 1711541Srgrimes 1721541Srgrimes /* 1731541Srgrimes * Clear out buffer cache. I don't think we 1741541Srgrimes * ever get anything cached at this level at the 1751541Srgrimes * moment, but who knows... 1761541Srgrimes */ 1771541Srgrimes#ifdef notyet 1788876Srgrimes mntflushbuf(mp, 0); 1791541Srgrimes if (mntinvalbuf(mp, 1)) 1801541Srgrimes return (EBUSY); 1811541Srgrimes#endif 18276688Siedowse /* There is 1 extra root vnode reference (pm_root). */ 183132023Salfred error = vflush(mp, 1, flags, td); 1843496Sphk if (error) 1851541Srgrimes return (error); 1861541Srgrimes 1871541Srgrimes /* 1881541Srgrimes * Shutdown the socket. This will cause the select in the 1891541Srgrimes * daemon to wake up, and then the accept will get ECONNABORTED 1901541Srgrimes * which it interprets as a request to go and bury itself. 1911541Srgrimes */ 192109153Sdillon soshutdown(VFSTOPORTAL(mp)->pm_server->f_data, 2); 1931541Srgrimes /* 1941541Srgrimes * Discard reference to underlying file. Must call closef because 1951541Srgrimes * this may be the last reference. 1961541Srgrimes */ 19783366Sjulian closef(VFSTOPORTAL(mp)->pm_server, (struct thread *) 0); 1981541Srgrimes /* 1991541Srgrimes * Finally, throw away the portalmount structure 2001541Srgrimes */ 20130354Sphk free(mp->mnt_data, M_PORTALFSMNT); /* XXX */ 2021541Srgrimes mp->mnt_data = 0; 2031541Srgrimes return (0); 2041541Srgrimes} 2051541Srgrimes 20612769Sphkstatic int 207144058Sjeffportal_root(mp, flags, vpp, td) 2081541Srgrimes struct mount *mp; 209144058Sjeff int flags; 2101541Srgrimes struct vnode **vpp; 211132023Salfred struct thread *td; 2121541Srgrimes{ 2131541Srgrimes struct vnode *vp; 2141541Srgrimes 2151541Srgrimes /* 2161541Srgrimes * Return locked reference to root. 2171541Srgrimes */ 2181541Srgrimes vp = VFSTOPORTAL(mp)->pm_root; 2191541Srgrimes VREF(vp); 22083366Sjulian vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2211541Srgrimes *vpp = vp; 2221541Srgrimes return (0); 2231541Srgrimes} 2241541Srgrimes 22512769Sphkstatic int 22683366Sjulianportal_statfs(mp, sbp, td) 2271541Srgrimes struct mount *mp; 2281541Srgrimes struct statfs *sbp; 22983366Sjulian struct thread *td; 2301541Srgrimes{ 2311541Srgrimes 2321541Srgrimes sbp->f_flags = 0; 2331541Srgrimes sbp->f_bsize = DEV_BSIZE; 2341541Srgrimes sbp->f_iosize = DEV_BSIZE; 2351541Srgrimes sbp->f_blocks = 2; /* 1K to keep df happy */ 2361541Srgrimes sbp->f_bfree = 0; 2371541Srgrimes sbp->f_bavail = 0; 2381541Srgrimes sbp->f_files = 1; /* Allow for "." */ 2391541Srgrimes sbp->f_ffree = 0; /* See comments above */ 2401541Srgrimes return (0); 2411541Srgrimes} 2421541Srgrimes 24312769Sphkstatic struct vfsops portal_vfsops = { 244138489Sphk .vfs_cmount = portal_cmount, 245138489Sphk .vfs_mount = portal_mount, 246116271Sphk .vfs_root = portal_root, 247116271Sphk .vfs_statfs = portal_statfs, 248116271Sphk .vfs_unmount = portal_unmount, 2491541Srgrimes}; 2502946Swollman 25177133SruVFS_SET(portal_vfsops, portalfs, VFCF_SYNTHETIC); 252