Index: src/sys/conf/files =================================================================== --- src/sys/conf/files (revision 177) +++ src/sys/conf/files (working copy) @@ -1767,17 +1767,33 @@ security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test ufs/ffs/ffs_alloc.c optional ffs +ufs/ffs/ffs_alloc.c optional ifs ufs/ffs/ffs_balloc.c optional ffs +ufs/ffs/ffs_balloc.c optional ifs ufs/ffs/ffs_inode.c optional ffs +ufs/ffs/ffs_inode.c optional ifs ufs/ffs/ffs_snapshot.c optional ffs +ufs/ffs/ffs_snapshot.c optional ifs ufs/ffs/ffs_softdep.c optional ffs +ufs/ffs/ffs_softdep.c optional ifs ufs/ffs/ffs_subr.c optional ffs +ufs/ffs/ffs_subr.c optional ifs ufs/ffs/ffs_tables.c optional ffs +ufs/ffs/ffs_tables.c optional ifs ufs/ffs/ffs_vfsops.c optional ffs +ufs/ffs/ffs_vfsops.c optional ifs ufs/ffs/ffs_vnops.c optional ffs +ufs/ffs/ffs_vnops.c optional ifs ufs/ffs/ffs_rawread.c optional directio ufs/ufs/ufs_acl.c optional ffs +ufs/ufs/ufs_acl.c optional ifs ufs/ufs/ufs_bmap.c optional ffs +ufs/ufs/ufs_bmap.c optional ifs +ufs/ufs/ufs_vnops.c optional ifs +ufs/ifs/ifs_lookup.c optional ifs +ufs/ifs/ifs_vfsops.c optional ifs +ufs/ifs/ifs_vnops.c optional ifs +ufs/ifs/ifs_subr.c optional ifs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs ufs/ufs/ufs_inode.c optional ffs Index: src/sys/conf/options =================================================================== --- src/sys/conf/options (revision 177) +++ src/sys/conf/options (working copy) @@ -186,6 +186,7 @@ # Broken - ffs_snapshot() dependency from ufs_lookup() :-( FFS opt_ffs_broken_fixme.h +IFS opt_ffs_broken_fixme.h # These static filesystems have one slightly bogus static dependency in # sys/i386/i386/autoconf.c. If any of these filesystems are Index: src/sys/ufs/ifs/ifs_vfsops.c =================================================================== --- src/sys/ufs/ifs/ifs_vfsops.c (revision 0) +++ src/sys/ufs/ifs/ifs_vfsops.c (revision 0) @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2005 Suleiman Souhlal + * Copyright (c) 1999, 2000 + * Adrian Chadd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 + * $FreeBSD: /repoman/r/ncvs/src/sys/ufs/ifs/ifs_vfsops.c,v 1.10 2002/04/04 21:03:33 jhb Exp $ + */ + + +#include "opt_ffs.h" +#include "opt_quota.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +extern uma_zone_t uma_inode, uma_ufs1, uma_ufs2; + +static int ifs_init (struct vfsconf *); +static int ifs_mount (struct mount *, struct thread *); +static int ifs_vget (struct mount *, ino_t, int, struct vnode **); + +static struct vfsops ifs_vfsops = { + .vfs_mount = ifs_mount, + .vfs_unmount = ffs_unmount, + .vfs_root = ufs_root, + .vfs_quotactl = ufs_quotactl, + .vfs_statfs = ffs_statfs, + .vfs_sync = ffs_sync, + .vfs_vget = ifs_vget, + .vfs_fhtovp = ffs_fhtovp, + .vfs_vptofh = ffs_vptofh, + .vfs_init = ifs_init, +}; + +VFS_SET(ifs_vfsops, ifs, 0); + +/* + * ifs_mount + * + * A simple wrapper around ffs_mount - IFS filesystems right now can't + * deal with softupdates so we make sure the user isn't trying to use it. + */ +static int +ifs_mount(struct mount *mp, struct thread *td) +{ + /* Clear the softdep flag */ + mp->mnt_flag &= ~MNT_SOFTDEP; + return (ffs_mount(mp, td)); +} + +/* + * Initialize the filesystem; just use ufs_init. + */ +static int +ifs_init(struct vfsconf *vfsp) +{ + /* XXX dqinit() if QUOTA? */ + return (0); +} + +static int +ifs_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) +{ + struct fs *fs; + struct inode *ip; + struct ufsmount *ump; + struct buf *bp; + struct vnode *vp; + struct cdev *dev; + int error; + + error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); + if (error || *vpp != NULL) + return (error); + + /* + * We must promote to an exclusive lock for vnode creation. This + * can happen if lookup is passed LOCKSHARED. + */ + if ((flags & LK_TYPE_MASK) == LK_SHARED) { + flags &= ~LK_TYPE_MASK; + flags |= LK_EXCLUSIVE; + } + + ump = VFSTOUFS(mp); + dev = ump->um_dev; + fs = ump->um_fs; + + /* + * If this MALLOC() is performed after the getnewvnode() + * it might block, leaving a vnode with a NULL v_data to be + * found by ffs_sync() if a sync happens to fire right then, + * which will cause a panic because ffs_sync() blindly + * dereferences vp->v_data (as well it should). + */ + ip = uma_zalloc(uma_inode, M_WAITOK | M_ZERO); + + /* Allocate a new vnode/inode. */ + error = getnewvnode("ufs", mp, &ifs_vnodeops, &vp); + if (error) { + *vpp = NULL; + uma_zfree(uma_inode, ip); + return (error); + } + /* + * IFS supports recursive and shared locking. + */ + vp->v_vnlock->lk_flags |= LK_CANRECURSE; + vp->v_vnlock->lk_flags &= ~LK_NOSHARE; + vp->v_data = ip; + vp->v_bufobj.bo_bsize = fs->fs_bsize; + ip->i_vnode = vp; + ip->i_ump = ump; + ip->i_fs = fs; + ip->i_dev = dev; + ip->i_number = ino; +#ifdef QUOTA + { + int i; + for (i = 0; i < MAXQUOTAS; i++) + ip->i_dquot[i] = NODQUOT; + } +#endif + error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL); + if (error || *vpp != NULL) + return (error); + + /* Read in the disk contents for the inode, copy into the inode. */ + error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), + (int)fs->fs_bsize, NOCRED, &bp); + if (error) { + /* + * The inode does not contain anything useful, so it would + * be misleading to leave it on its hash chain. With mode + * still zero, it will be unlinked and returned to the free + * list by vput(). + */ + brelse(bp); + vput(vp); + *vpp = NULL; + return (error); + } + if (ip->i_ump->um_fstype != UFS2) + return (EINVAL); + ip->i_din2 = uma_zalloc(uma_ufs2, M_WAITOK); + ffs_load_inode(bp, ip, fs, ino); + if (DOINGSOFTDEP(vp)) + softdep_load_inodeblock(ip); + else + ip->i_effnlink = ip->i_nlink; + bqrelse(bp); + + /* + * Initialize the vnode from the inode, check for aliases. + * Note that the underlying vnode may have changed. + */ + error = ufs_vinit(mp, &ifs_fifoops, &vp); + if (error) { + vput(vp); + *vpp = NULL; + return (error); + } + /* + * Finish inode initialization now that aliasing has been resolved. + */ + + /* + * Set up a generation number for this inode if it does not + * already have one. This should only happen on old filesystems. + */ + if (ip->i_gen == 0) { + ip->i_gen = arc4random() / 2 + 1; + if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { + ip->i_flag |= IN_MODIFIED; + DIP_SET(ip, i_gen, ip->i_gen); + } + } + + *vpp = vp; + return (0); +} Index: src/sys/ufs/ifs/ifs_vnops.c =================================================================== --- src/sys/ufs/ifs/ifs_vnops.c (revision 0) +++ src/sys/ufs/ifs/ifs_vnops.c (revision 0) @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2005 Suleiman Souhlal + * Copyright (c) 1999, 2000 + * Adrian Chadd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95 + * $FreeBSD: /repoman/r/ncvs/src/sys/ufs/ifs/ifs_vnops.c,v 1.8 2002/05/18 18:51:10 iedowse Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +/* IFS debugging */ +#undef DEBUG_IFS_READDIR + +static int ifs_getattr(struct vop_getattr_args *); +static int ifs_create(struct vop_create_args *); +static int ifs_makeinode(int mode, struct vnode *, struct vnode **, + struct componentname *); +static int ifs_remove(struct vop_remove_args *); +static int ifs_readdir(struct vop_readdir_args *); +static int ifs_dirremove(struct vnode *, struct inode *, int, int); + +/* Global vfs data structures for ifs. */ +struct vop_vector ifs_vnodeops = { + .vop_default = &default_vnodeops, + .vop_access = &ufs_access, + .vop_fsync = &ffs_fsync, + .vop_getpages = &ffs_getpages, + .vop_read = &ffs_read, + .vop_reallocblks = &ffs_reallocblks, + .vop_reclaim = &ufs_reclaim, + .vop_strategy = &ufs_strategy, + .vop_write = &ffs_write, + + .vop_lookup = &ifs_lookup, + .vop_getattr = &ifs_getattr, + .vop_create = &ifs_create, + .vop_remove = &ifs_remove, + .vop_readdir = &ifs_readdir, +}; + +struct vop_vector ifs_fifoops = { + .vop_default = &ufs_fifoops, + .vop_fsync = &ffs_fsync, +}; + +/* ARGSUSED */ +static int +ifs_getattr(ap) + struct vop_getattr_args /* { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + struct vattr *vap = ap->a_vap; + + ufs_itimes(vp); + /* + * Copy from inode table + */ + vap->va_fsid = dev2udev(ip->i_dev); + vap->va_fileid = ip->i_number; + vap->va_mode = ip->i_mode & ~IFMT; + vap->va_nlink = ip->i_effnlink; + vap->va_uid = ip->i_uid; + vap->va_gid = ip->i_gid; + vap->va_rdev = ip->i_din2->di_rdev; + vap->va_size = ip->i_din2->di_size; + vap->va_atime.tv_sec = ip->i_din2->di_atime; + vap->va_atime.tv_nsec = ip->i_din2->di_atimensec; + vap->va_mtime.tv_sec = ip->i_din2->di_mtime; + vap->va_mtime.tv_nsec = ip->i_din2->di_mtimensec; + vap->va_ctime.tv_sec = ip->i_din2->di_ctime; + vap->va_ctime.tv_nsec = ip->i_din2->di_ctimensec; + vap->va_birthtime.tv_sec = ip->i_din2->di_birthtime; + vap->va_birthtime.tv_nsec = ip->i_din2->di_birthnsec; + vap->va_flags = ip->i_flags; + vap->va_gen = ip->i_gen; + vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; + vap->va_type = IFTOVT(ip->i_mode); + vap->va_filerev = ip->i_modrev; + return (0); +} + + +/* + * Create a regular file + */ +int +ifs_create(ap) + struct vop_create_args /* { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; + } */ *ap; +{ + return (ifs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), + ap->a_dvp, ap->a_vpp, ap->a_cnp)); +} + + +/* + * Allocate a new inode. + * Vnode dvp must be locked. + */ +int +ifs_makeinode(mode, dvp, vpp, cnp) + int mode; + struct vnode *dvp; + struct vnode **vpp; + struct componentname *cnp; +{ + struct inode *ip, *pdir; + struct vnode *tvp; + int error; + + pdir = VTOI(dvp); +#ifdef DIAGNOSTIC + if ((cnp->cn_flags & HASBUF) == 0) + panic("ifs_makeinode: no name"); +#endif + *vpp = NULL; + if ((mode & IFMT) == 0) + mode |= IFREG; + error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp); + if (error) + return (error); + ip = VTOI(tvp); + ip->i_gid = pdir->i_gid; + DIP_SET(ip, i_gid, pdir->i_gid); + ip->i_uid = cnp->cn_cred->cr_uid; + DIP_SET(ip, i_uid, ip->i_uid); +#ifdef QUOTA + if ((error = getinoquota(ip)) || + (error = chkiq(ip, 1, cnp->cn_cred, 0))) { + UFS_VFREE(tvp, ip->i_number, mode); + vput(tvp); + return (error); + } +#endif + ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; + ip->i_mode = mode; + DIP_SET(ip, i_mode, mode); + tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ + ip->i_effnlink = 1; + ip->i_nlink = 1; + DIP_SET(ip, i_nlink, 1); + if (DOINGSOFTDEP(tvp)) + softdep_change_linkcnt(ip); + if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && + suser_cred(cnp->cn_cred, SUSER_ALLOWJAIL)) { + ip->i_mode &= ~ISGID; + DIP_SET(ip, i_mode, ip->i_mode); + } + + if (cnp->cn_flags & ISWHITEOUT) { + ip->i_flags |= UF_OPAQUE; + DIP_SET(ip, i_flags, ip->i_flags); + } + + /* + * Make sure inode goes to disk before directory entry. + */ + error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp))); + if (error) + goto bad; + *vpp = tvp; + return (0); +bad: + /* + * Write error occurred trying to update the inode + * or the directory so must deallocate the inode. + */ + ip->i_effnlink = 0; + ip->i_nlink = 0; + DIP_SET(ip, i_nlink, 0); + ip->i_flag |= IN_CHANGE; + if (DOINGSOFTDEP(tvp)) + softdep_change_linkcnt(ip); + vput(tvp); + return (error); +} + + +int +ifs_remove(ap) + struct vop_remove_args /* { + struct vnode *a_dvp; + struct vnode *a_vp; + struct componentname *a_cnp; + } */ *ap; +{ + struct inode *ip; + struct vnode *vp = ap->a_vp; + struct vnode *dvp = ap->a_dvp; + + ip = VTOI(vp); + if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || + (VTOI(dvp)->i_flags & APPEND)) + return (EPERM); + return (ifs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0)); +} + + +/* + * highly cutdown ufs_dirremove, since we're not updating + * any directory entries. :-) + */ +static int +ifs_dirremove(struct vnode *dvp, struct inode *ip, int flags, int isrmdir) +{ + int error; + + if (ip) { + ip->i_effnlink--; + ip->i_flag |= IN_CHANGE; + ip->i_nlink--; + DIP_SET(ip, i_nlink, ip->i_nlink); + error = 0; + } else + error = ENOENT; + return (error); +} + + +/* + * ifs_readdir + * + * Do the directory listing, representing the allocated inodes + * making up this filesystem. + * + */ + +static int +ifs_readdir(ap) + struct vop_readdir_args /* { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + int *a_eofflag; + int *ncookies; + u_long **a_cookies; + } */ *ap; +{ + int inodenum; + struct dirent *dent, *lastdp = NULL; + struct dirent *tmpdp; + char *dirbuf; + struct inode *ip = VTOI(ap->a_vp); /* To get the mount info later */ + struct mount *mp = ap->a_vp->v_mount; + struct fs *fs = VFSTOUFS(mp)->um_fs; + int maxnuminode = fs->fs_ncg * fs->fs_ipg; + int error = 0; + int count; + int dircount = 0; + int copylen = 0; + char iret; + + /* + * Get the offset, which represents the inode we're going to + * start from + */ + inodenum = ap->a_uio->uio_offset; +#ifdef DEBUG_IFS_READDIR + printf("ifs_readdir: starting with inode %d\n", inodenum); +#endif + if (inodenum < 0) + return (EINVAL); + /* + * Next, get the buffer size, round it down to a dirent, and + * figure out how many allocated inodes we need to match + */ + count = ap->a_uio->uio_resid; + /* + * Next, create a dirbuf to fill with directory entries + */ + tmpdp = malloc(sizeof (struct dirent), M_TEMP, M_WAITOK); + dirbuf = malloc(count, M_TEMP, M_WAITOK); + dent = (struct dirent *)dirbuf; + /* now, keep reading until we run out of inodes */ + while (inodenum < maxnuminode) { + /* Get bitmap info and see if we bother with this cg */ + iret = ifs_isinodealloc(ip, inodenum); + if (iret == IFS_INODE_EMPTYCG) { + /* Skip this CG */ + inodenum -= inodenum % fs->fs_ipg; + inodenum += fs->fs_ipg; + continue; + } + /* Allocated and not special? */ + if ((inodenum > 2) && iret == IFS_INODE_ISALLOC) { + /* Create a new entry */ + sprintf(tmpdp->d_name, "%d", inodenum); + tmpdp->d_fileno = inodenum; + tmpdp->d_type = DT_REG; + tmpdp->d_namlen = strlen(tmpdp->d_name); + tmpdp->d_reclen = DIRECTSIZ(tmpdp->d_namlen); + /* Make sure we have enough space for this entry */ + if (tmpdp->d_reclen > count) + break; + /* Copy it to the given buffer */ + bcopy(tmpdp, dent, tmpdp->d_reclen); + /* Decrement the count */ + count -= dent->d_reclen; + copylen += dent->d_reclen; + lastdp = dent; + /* Increment the offset pointer */ + dent = (struct dirent *)((char *)dent + dent->d_reclen); + dircount++; + } + /* Increment the inode number we are checking */ + inodenum++; + } +#ifdef DEBUG_IFS_READDIR + printf("ifs_readdir: copied %d directories\n", dircount); +#endif + /* + * Get the last dent updated, and make the record d_reclen last the + * whole buffer. + */ + if (lastdp != NULL) { + /* Update the length of the last entry */ + lastdp->d_reclen += count; + } + /* Copy the data out */ +#ifdef DEBUG_IFS_READDIR + printf("ifs_readdir: copied %d bytes\n", copylen); +#endif + error = uiomove(dirbuf, copylen, ap->a_uio); + /* Free memory we've used */ + free(dirbuf, M_TEMP); + free(tmpdp, M_TEMP); + /* Set uio_offset to the last inode number */ + ap->a_uio->uio_offset = inodenum; + /* Handle EOF/eofflag */ + if ((inodenum >= maxnuminode) && (ap->a_eofflag != NULL)) { + *ap->a_eofflag = 1; +#ifdef DEBUG_IFS_READDIR + printf("ifs_readdir: setting EOF flag\n"); +#endif + } +#ifdef DEBUG_IFS_READDIR + printf("ifs_readdir: new offset: %d\n", inodenum); +#endif + return (error); +} + Index: src/sys/ufs/ifs/ifs_lookup.c =================================================================== --- src/sys/ufs/ifs/ifs_lookup.c (revision 0) +++ src/sys/ufs/ifs/ifs_lookup.c (revision 0) @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1999, 2000 + * Adrian Chadd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95 + * $FreeBSD: /repoman/r/ncvs/src/sys/ufs/ifs/ifs_lookup.c,v 1.4 2002/03/17 01:25:47 mckusick Exp $ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* true if old FS format...*/ +#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0) + +/* Define if you want my debug printfs inside ifs_lookup() */ +#undef DEBUG_IFS_LOOKUP + +/* + * Convert a path to an inode. + * + * This is HIGHLY simplified - we just take the path fragment given to us, + * attempt to convert it to an inode, and return the inode if we can. + * No permission checking is done here, that is done further up in the + * VFS call layers. + */ +int +ifs_lookup(ap) + struct vop_lookup_args /* { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + } */ *ap; +{ + struct vnode *vdp; /* vnode for directory being searched */ + struct inode *dp; /* inode for directory being searched */ + struct vnode *pdp; /* saved dp during symlink work */ + struct vnode *tdp; /* returned by VFS_VGET */ + struct vnode **vpp = ap->a_vpp; + struct componentname *cnp = ap->a_cnp; + struct ucred *cred = cnp->cn_cred; + struct mount *mp = ap->a_dvp->v_mount; + struct fs *fs = VFSTOUFS(mp)->um_fs; + int nameiop = cnp->cn_nameiop; + int error; + ino_t inodenum; + char *endp; + + *vpp = NULL; + vdp = ap->a_dvp; + dp = VTOI(vdp); + pdp = vdp; + /* + * Firstly, we are NOT dealing with RENAME, at all + */ + if (nameiop == RENAME) { + *vpp = NULL; +#ifdef DEBUG_IFS_LOOKUP + printf("ifs_lookup(): Denying RENAME nameiop\n"); +#endif + return (EPERM); + } + /* Deal with the '.' directory */ + if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') { + /* We don't unlock the parent dir since the're the same */ + *vpp = vdp; + vref(vdp); + return (0); + } + /* + * 'newfile' is considered something special .. read below why + * we're returning NULL + */ + if ((cnp->cn_namelen) == 7 && (strncmp(cnp->cn_nameptr, "newfile", 7) == 0)) { + if (nameiop == CREATE) { + /* Check for write permissions in . */ + error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread); + if (error) + return (error); + *vpp = NULL; + cnp->cn_flags |= SAVENAME; + return (EJUSTRETURN); + } else { + *vpp = NULL; +#ifdef DEBUG_IFS_LOOKUP + printf("ifs_lookup(): Denying !CREATE on 'newfile'\n"); +#endif + return (EPERM); + } + } + /* Grab the hex inode number */ + inodenum = strtouq(cnp->cn_nameptr, &endp, 0); + /* Sanity Check */ + if (endp != (cnp->cn_nameptr + cnp->cn_namelen)) { + *vpp = NULL; + return (ENOENT); + } + /* + * error check here - inodes 0-2 are considered 'special' even here + * so we will hide it from the user. + */ + if (inodenum <= 2) { +#ifdef DEBUG_IFS_LOOKUP + printf("ifs_lookup(): Access to disk inode '%d' denied\n", + (int)inodenum); +#endif + return (EPERM); + } + /* Check we haven't overflowed the number of inodes in the fs */ + if (inodenum > (fs->fs_ncg * fs->fs_ipg)) { +#ifdef DEBUG_IFS_LOOKUP + printf("ifs_lookup(): disk inode '%d' is outside the disk\n"), + (int)inodenum); +#endif + return (EINVAL); + } + /* + * The next bit of code grabs the inode, checks to see whether + * we're allowed to do our nameiop on it. The only one we need + * to check here is CREATE - only allow create on an inode + * that exists. + * + * Comment for VFS-newbies: + * read vn_open() - you'll learn that if you return a name here, + * it assumes you don't need to call VOP_CREATE. Bad juju as + * you now have a vnode that isn't tagged with the right type, + * and it'll panic in the VOP_READ/VOP_WRITE routines.. + */ + /* + * If we get here and its a CREATE, then return EPERM if the inode + * doesn't exist. + */ + if ((nameiop == CREATE) && + (ifs_isinodealloc(VTOI(vdp), inodenum) != IFS_INODE_ISALLOC)) { +#ifdef DEBUG_IFS_LOOKUP + printf("ifs_lookup(): CREATE on inode %d which doesn't exist\n", + (int)inodenum); +#endif + return (EPERM); +#ifdef DEBUG_IFS_LOOKUP + } else if (nameiop == CREATE) { + /* It does exist, allow CREATE */ + printf("ifs_lookup(): CREATE on inode %d which exists\n", + (int)inodenum); + } +#else + } +#endif + /* + * Make sure that the inode exists if we're trying to delete or + * modify + */ + if ((nameiop == LOOKUP || nameiop == DELETE) && + ifs_isinodealloc(VTOI(vdp), inodenum) != IFS_INODE_ISALLOC) { + /* it doesn't exist */ +#ifdef DEBUG_IFS_LOOKUP + printf("ifs_lookup(): Inode %d isn't allocated\n", + (int)inodenum); +#endif + return (ENOENT); + } + /* Now, we can get the vnode */ + error = VFS_VGET(vdp->v_mount, inodenum, LK_EXCLUSIVE, &tdp); + if (error) + return (error); + *vpp = tdp; + return (0); +} + Index: src/sys/ufs/ifs/ifs_extern.h =================================================================== --- src/sys/ufs/ifs/ifs_extern.h (revision 0) +++ src/sys/ufs/ifs/ifs_extern.h (revision 0) @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95 + * $FreeBSD: /repoman/r/ncvs/src/sys/ufs/ifs/ifs_extern.h,v 1.3 2001/09/12 08:38:08 julian Exp $ + */ + +#ifndef _UFS_IFS_EXTERN_H +#define _UFS_IFS_EXTERN_H + +/* + * Sysctl values for the fast filesystem. + */ +#define IFS_REALLOCBLKS 3 /* block reallocation enabled */ +#define IFS_ASYNCFREE 4 /* asynchronous block freeing enabled */ +#define IFS_MAXID 5 /* number of valid ffs ids */ + + +/* Return vals from ifs_isinodealloc */ +#define IFS_INODE_ISALLOC 1 +#define IFS_INODE_NOALLOC 0 +#define IFS_INODE_EMPTYCG -1 + +#define IFS_NAMES { \ + { 0, 0 }, \ + { 0, 0 }, \ + { 0, 0 }, \ + { "doreallocblks", CTLTYPE_INT }, \ + { "doasyncfree", CTLTYPE_INT }, \ +} + +struct buf; +struct fid; +struct fs; +struct inode; +struct malloc_type; +struct mount; +struct sockaddr; +struct statfs; +struct ucred; +struct vnode; +//struct vop_balloc_args; +//struct vop_fsync_args; +//struct vop_reallocblks_args; + +extern struct vop_vector ifs_vnodeops; +extern struct vop_vector ifs_specops; +extern struct vop_vector ifs_fifoops; + +int ifs_lookup(struct vop_lookup_args *); +int ifs_isinodealloc(struct inode *, ufs2_daddr_t); + +#endif /* !_UFS_IFS_EXTERN_H */ Index: src/sys/ufs/ifs/ifs_subr.c =================================================================== --- src/sys/ufs/ifs/ifs_subr.c (revision 0) +++ src/sys/ufs/ifs/ifs_subr.c (revision 0) @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1999, 2000 + * Adrian Chadd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95 + * $FreeBSD: /repoman/r/ncvs/src/sys/ufs/ifs/ifs_subr.c,v 1.3 2002/03/20 08:48:07 jeff Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* + * Check whether the given inode number is free. + * + * This routine is a chunk of ffs_nodealloccg - we aren't + * allocating here. We also check whether there will be + * any other inodes in the cylinder group, and if not, + * we return -1. + */ +int +ifs_isinodealloc(struct inode *ip, ufs2_daddr_t ino) +{ + struct fs *fs; + struct cg *cgp; + struct buf *bp; + int error; + int cg; + int retval = 0; + + /* Grab the filesystem info and cylinder group */ + fs = ip->i_fs; + cg = ino_to_cg(fs, ino); + + /* Read in the cylinder group inode allocation bitmap .. */ + error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), + (int)fs->fs_cgsize, NOCRED, &bp); + if (error) { + retval = IFS_INODE_NOALLOC; + goto end; + } + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp)) { + retval = IFS_INODE_NOALLOC; + goto end; + } + ino %= fs->fs_ipg; + /* + * Check whether we have any inodes in this cg, or whether the + * inode is allocated + */ + if (!isclr(cg_inosused(cgp), ino)) + retval = IFS_INODE_ISALLOC; /* it is allocated */ + else if (cgp->cg_niblk == cgp->cg_cs.cs_nifree) + retval = IFS_INODE_EMPTYCG; /* empty cg */ + else + retval = IFS_INODE_NOALLOC; /* its not allocated */ +end: + /* Close the buffer and return */ + brelse(bp); + return (retval); +} + Index: src/sys/ufs/ifs/README =================================================================== --- src/sys/ufs/ifs/README (revision 0) +++ src/sys/ufs/ifs/README (revision 0) @@ -0,0 +1,109 @@ + +$FreeBSD: /repoman/r/ncvs/src/sys/ufs/ifs/README,v 1.1 2000/10/14 03:02:30 adrian Exp $ + +ifs- inode filesystem +-- + + +ifs is the beginning of a little experiment - to remove the namespace +from ffs. FFS is a good generic filesystem, however in high volume +activities today (eg web, mail, cache, news) one thing causes a rather +huge resource drain - the namespace. + +Having to maintain the directory structures means wasting a lot of +disk IO and/or memory. Since most applications these days have their +own database containing object->ufs namespace mappings, we can effectively +bypass namespace together and talk instead to just inodes. + +This is a big big hack(1), but its also a start. It should speed up news +servers and cache servers quite a bit - since the time spent in open() +and unlink() is drastically reduced - however, it is nowhere near +optimal. We'll cover that shortly. + +(1) not hack as evil and ugly, hack as in non-optimal solution. The + optimal solution hasn't quite presented itself yet. :-) + + + +How it works: +-- + +Basically ifs is a copy of ffs, overriding some vfs/vnops. (Yes, hack.) +I didn't see the need in duplicating all of sys/ufs/ffs to get this +off the ground. + +File creation is done through a special file - 'newfile' . When newfile +is called, the system allocates and returns an inode. Note that newfile +is done in a cloning fashion: + +fd = open("newfile", O_CREAT|O_RDWR, 0644); +fstat(fd, &st); + +printf("new file is %d\n", (int)st.st_ino); + +Once you have created a file, you can open() and unlink() it by its returned +inode number retrieved from the stat call, ie: + +fd = open("5", O_RDWR); + +The creation permissions depend entirely if you have write access to the +root directory of the filesystem. + + +Why its nowhere near optimal +-- + +When doing file allocation in FFS, it tries to reduce the disk seeks by +allocating new files inside the cylinder group of the parent directory, if +possible. In this scheme, we've had to drop that. Files are allocated +sequentially, filling up cylinder groups as we go along. Its not very optimal, +more research will have to be done into how cylinder group locality can be +bought back into this. (It entirely depends upon the benefits here..) + +Allowing create by inode number requires quite a bit of code rewrite, and in +the test applications here I didn't need it. Maybe in the next phase I might +look at allowing create by inode number, feedback, please. + +SOFTUPDATES will *NOT* work here - especially in unlink() where I've just +taken a large axe to it. I've tried to keep as much of the softupdates call +stubs in as much as possible, but I haven't looked at the softupdates code. +My reasoning was that because there's no directory metadata anymore, +softupdates isn't as important. Besides, fsck's are so damn quick .. + +Extras +-- + +I've taken the liberty of applying a large axe to bits of fsck - stripping out +namespace checks. As far as I can *TELL*, its close, however, I'd like it if +someone fsck clued poked me back on what I missed. + +There's also a modified copy of mount that will mount a fs type 'ifs'. Again, +its just the normal mount with s/"ufs"/"ifs"/g, async/noatime/etc mount +options work just as normal. + +I haven't supplied an ifs 'newfs' - use FFS newfs to create a blank drive. +That creates the root directory, which you still do DEFINITELY need. +However, ifs updates on the drive will not update directory entries in '.'. +There is a 1:1 mapping between the inode numbers in open()/stat() and the +inodes on disk. You don't get access to inodes 0-2. They don't show up +in a readdir. I'll work on making 2 avaliable, but since the current ufs/ffs +code assumes things are locked against the root inode which is 2 .. + +You can find these utilities in src/sbin/mount_ifs and src/sbin/fsck_ifs . +Yes, this means that you can tie in ifs partitions in your bootup +sequence. + +TODO: +-- + +* Implement cookies for NFS + + (Realise that this is a huge hack which uses the existing UFS/FFS code. + Therefore its nowhere near as optimal as it could be, and things aren't + as easy to add as one might think. Especially 'fake' files. :-) + + + +-- +Adrian Chadd + Index: src/sys/ufs/ufs/ufs_vnops.c =================================================================== --- src/sys/ufs/ufs/ufs_vnops.c (revision 177) +++ src/sys/ufs/ufs/ufs_vnops.c (working copy) @@ -85,7 +85,6 @@ #include -static vop_access_t ufs_access; static vop_advlock_t ufs_advlock; static int ufs_chmod(struct vnode *, int, struct ucred *, struct thread *); static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct thread *); @@ -104,7 +103,6 @@ static vop_rename_t ufs_rename; static vop_rmdir_t ufs_rmdir; static vop_setattr_t ufs_setattr; -static vop_strategy_t ufs_strategy; static vop_symlink_t ufs_symlink; static vop_whiteout_t ufs_whiteout; static vop_close_t ufsfifo_close; @@ -281,7 +279,7 @@ return (0); } -static int +int ufs_access(ap) struct vop_access_args /* { struct vnode *a_vp; @@ -1912,7 +1910,7 @@ * In order to be able to swap to a file, the ufs_bmaparray() operation may not * deadlock on memory. See ufs_bmap() for details. */ -static int +int ufs_strategy(ap) struct vop_strategy_args /* { struct vnode *a_vp; Index: src/sys/ufs/ufs/ufs_extern.h =================================================================== --- src/sys/ufs/ufs/ufs_extern.h (revision 177) +++ src/sys/ufs/ufs/ufs_extern.h (working copy) @@ -54,6 +54,7 @@ extern struct vop_vector ufs_fifoops; extern struct vop_vector ufs_vnodeops; +vop_access_t ufs_access; int ufs_bmap(struct vop_bmap_args *); int ufs_bmaparray(struct vnode *, ufs2_daddr_t, ufs2_daddr_t *, struct buf *, int *, int *); @@ -77,8 +78,9 @@ int ufs_lookup(struct vop_cachedlookup_args *); int ufs_readdir(struct vop_readdir_args *); int ufs_reclaim(struct vop_reclaim_args *); +vfs_root_t ufs_root; void ffs_snapgone(struct inode *); -vfs_root_t ufs_root; +vop_strategy_t ufs_strategy; int ufs_uninit(struct vfsconf *); int ufs_vinit(struct mount *, struct vop_vector *, struct vnode **); Index: src/sys/ufs/ffs/ffs_vnops.c =================================================================== --- src/sys/ufs/ffs/ffs_vnops.c (revision 177) +++ src/sys/ufs/ffs/ffs_vnops.c (working copy) @@ -102,11 +102,7 @@ #ifdef DIRECTIO extern int ffs_rawread(struct vnode *vp, struct uio *uio, int *workdone); #endif -static vop_fsync_t ffs_fsync; static vop_lock_t ffs_lock; -static vop_getpages_t ffs_getpages; -static vop_read_t ffs_read; -static vop_write_t ffs_write; static int ffs_extread(struct vnode *vp, struct uio *uio, int ioflag); static int ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred); @@ -171,7 +167,7 @@ * Synch an open file. */ /* ARGSUSED */ -static int +int ffs_fsync(struct vop_fsync_args *ap) { int error; @@ -345,7 +341,7 @@ * Vnode op for reading. */ /* ARGSUSED */ -static int +int ffs_read(ap) struct vop_read_args /* { struct vnode *a_vp; @@ -554,7 +550,7 @@ /* * Vnode op for writing. */ -static int +int ffs_write(ap) struct vop_write_args /* { struct vnode *a_vp; @@ -755,7 +751,7 @@ /* * get page routine */ -static int +int ffs_getpages(ap) struct vop_getpages_args *ap; { Index: src/sys/ufs/ffs/ffs_extern.h =================================================================== --- src/sys/ufs/ffs/ffs_extern.h (revision 177) +++ src/sys/ufs/ffs/ffs_extern.h (working copy) @@ -63,12 +63,17 @@ void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t); int ffs_copyonwrite(struct vnode *, struct buf *); int ffs_flushfiles(struct mount *, int, struct thread *); +vfs_fhtovp_t ffs_fhtovp; void ffs_fragacct(struct fs *, int, int32_t [], int); int ffs_freefile(struct ufsmount *, struct fs *, struct vnode *, ino_t, int); +vop_fsync_t ffs_fsync; +vop_getpages_t ffs_getpages; int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t); void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t); +vfs_mount_t ffs_mount; int ffs_mountroot(void); +vop_read_t ffs_read; int ffs_reallocblks(struct vop_reallocblks_args *); int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t, ufs2_daddr_t, int, int, struct ucred *, struct buf **); @@ -78,13 +83,18 @@ int ffs_snapshot(struct mount *mp, char *snapfile); void ffs_snapshot_mount(struct mount *mp); void ffs_snapshot_unmount(struct mount *mp); +vfs_statfs_t ffs_statfs; +vfs_sync_t ffs_sync; int ffs_syncvnode(struct vnode *vp, int waitfor); int ffs_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *); +vfs_unmount_t ffs_unmount; int ffs_update(struct vnode *, int); int ffs_valloc(struct vnode *, int, struct ucred *, struct vnode **); int ffs_vfree(struct vnode *, ino_t, int); vfs_vget_t ffs_vget; +vfs_vptofh_t ffs_vptofh; +vop_write_t ffs_write; extern struct vop_vector ffs_vnodeops1; extern struct vop_vector ffs_fifoops1; Index: src/sys/ufs/ffs/ffs_vfsops.c =================================================================== --- src/sys/ufs/ffs/ffs_vfsops.c (revision 177) +++ src/sys/ufs/ffs/ffs_vfsops.c (working copy) @@ -68,7 +68,7 @@ #include #include -static uma_zone_t uma_inode, uma_ufs1, uma_ufs2; +uma_zone_t uma_inode, uma_ufs1, uma_ufs2; static int ffs_sbupdate(struct ufsmount *, int); static int ffs_reload(struct mount *, struct thread *); @@ -81,12 +81,6 @@ static vfs_uninit_t ffs_uninit; static vfs_extattrctl_t ffs_extattrctl; static vfs_cmount_t ffs_cmount; -static vfs_unmount_t ffs_unmount; -static vfs_mount_t ffs_mount; -static vfs_statfs_t ffs_statfs; -static vfs_fhtovp_t ffs_fhtovp; -static vfs_vptofh_t ffs_vptofh; -static vfs_sync_t ffs_sync; static struct vfsops ufs_vfsops = { .vfs_extattrctl = ffs_extattrctl, @@ -118,7 +112,7 @@ static const char *ffs_opts[] = { "from", "export", NULL }; -static int +int ffs_mount(struct mount *mp, struct thread *td) { struct vnode *devvp; @@ -900,7 +894,7 @@ /* * unmount system call */ -static int +int ffs_unmount(mp, mntflags, td) struct mount *mp; int mntflags; @@ -1020,7 +1014,7 @@ /* * Get filesystem statistics. */ -static int +int ffs_statfs(mp, sbp, td) struct mount *mp; struct statfs *sbp; @@ -1056,7 +1050,7 @@ * * Note: we are always called with the filesystem marked `MPBUSY'. */ -static int +int ffs_sync(mp, waitfor, td) struct mount *mp; int waitfor; @@ -1334,7 +1328,7 @@ * - check that the given client host has export rights and return * those rights via. exflagsp and credanonp */ -static int +int ffs_fhtovp(mp, fhp, vpp) struct mount *mp; struct fid *fhp; @@ -1355,7 +1349,7 @@ * Vnode pointer to File handle */ /* ARGSUSED */ -static int +int ffs_vptofh(vp, fhp) struct vnode *vp; struct fid *fhp;