X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/42ff4c2eab9341478afec7d34adcc8aaef51df20..ede9137980d8582754d6276d8d30f6c0fc02702f:/usr/src/sys/ufs/lfs/lfs_vfsops.c diff --git a/usr/src/sys/ufs/lfs/lfs_vfsops.c b/usr/src/sys/ufs/lfs/lfs_vfsops.c index 71c6ef1bad..34aac29662 100644 --- a/usr/src/sys/ufs/lfs/lfs_vfsops.c +++ b/usr/src/sys/ufs/lfs/lfs_vfsops.c @@ -1,379 +1,521 @@ /* - * Copyright (c) 1982, 1986 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. * - * @(#)lfs_vfsops.c 7.5 (Berkeley) %G% + * %sccs.include.redist.c% + * + * @(#)lfs_vfsops.c 8.6 (Berkeley) %G% */ -#include "param.h" -#include "systm.h" -#include "dir.h" -#include "user.h" -#include "inode.h" -#include "proc.h" -#include "fs.h" -#include "buf.h" -#include "mount.h" -#include "file.h" -#include "conf.h" -#include "ioctl.h" -#include "disklabel.h" -#include "stat.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include "ioctl.h" #include "disklabel.h" #include "stat.h" -smount() +#include +#include +#include +#include + +#include +#include + +int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); + +struct vfsops lfs_vfsops = { + lfs_mount, + ufs_start, + lfs_unmount, + lfs_root, + ufs_quotactl, + lfs_statfs, + lfs_sync, + lfs_vget, + lfs_fhtovp, + lfs_vptofh, + lfs_init, +}; + +int +lfs_mountroot() { - register struct a { - char *fspec; - char *freg; - int ronly; - } *uap = (struct a *)u.u_ap; - dev_t dev; - register struct inode *ip; - register struct fs *fs; - register struct nameidata *ndp = &u.u_nd; - u_int len; - - u.u_error = getmdev(&dev, uap->fspec); - if (u.u_error) - return; - ndp->ni_nameiop = LOOKUP | FOLLOW; - ndp->ni_segflg = UIO_USERSPACE; - ndp->ni_dirp = (caddr_t)uap->freg; - ip = namei(ndp); - if (ip == NULL) - return; - if (ip->i_count != 1) { - iput(ip); - u.u_error = EBUSY; - return; + panic("lfs_mountroot"); /* XXX -- implement */ +} + +/* + * VFS Operations. + * + * mount system call + */ +lfs_mount(mp, path, data, ndp, p) + register struct mount *mp; + char *path; + caddr_t data; + struct nameidata *ndp; + struct proc *p; +{ + struct vnode *devvp; + struct ufs_args args; + struct ufsmount *ump; + register struct lfs *fs; /* LFS */ + u_int size; + int error; + + if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) + return (error); + + /* Until LFS can do NFS right. XXX */ + if (args.export.ex_flags & MNT_EXPORTED) + return (EINVAL); + + /* + * If updating, check whether changing from read-only to + * read/write; if there is no device name, that's all we do. + */ + if (mp->mnt_flag & MNT_UPDATE) { + ump = VFSTOUFS(mp); +#ifdef NOTLFS /* LFS */ + fs = ump->um_fs; + if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) + fs->fs_ronly = 0; +#else + fs = ump->um_lfs; + if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) + fs->lfs_ronly = 0; +#endif + if (args.fspec == 0) { + /* + * Process export requests. + */ + return (vfs_export(mp, &ump->um_export, &args.export)); + } + } + /* + * Not an update, or updating the name: look up the name + * and verify that it refers to a sensible block device. + */ + NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); + if (error = namei(ndp)) + return (error); + devvp = ndp->ni_vp; + if (devvp->v_type != VBLK) { + vrele(devvp); + return (ENOTBLK); + } + if (major(devvp->v_rdev) >= nblkdev) { + vrele(devvp); + return (ENXIO); } - if ((ip->i_mode&IFMT) != IFDIR) { - iput(ip); - u.u_error = ENOTDIR; - return; + if ((mp->mnt_flag & MNT_UPDATE) == 0) + error = lfs_mountfs(devvp, mp, p); /* LFS */ + else { + if (devvp != ump->um_devvp) + error = EINVAL; /* needs translation */ + else + vrele(devvp); } - fs = mountfs(dev, uap->ronly, ip); - if (fs == 0) - return; - (void) copyinstr(uap->freg, fs->fs_fsmnt, sizeof(fs->fs_fsmnt)-1, &len); - bzero(fs->fs_fsmnt + len, sizeof (fs->fs_fsmnt) - len); + if (error) { + vrele(devvp); + return (error); + } + ump = VFSTOUFS(mp); + fs = ump->um_lfs; /* LFS */ +#ifdef NOTLFS /* LFS */ + (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); + bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); + bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, + MNAMELEN); + (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, + &size); + bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); + (void) ufs_statfs(mp, &mp->mnt_stat, p); +#else + (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); + bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); + bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, + MNAMELEN); + (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, + &size); + bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); + (void) lfs_statfs(mp, &mp->mnt_stat, p); +#endif + return (0); } -/* this routine has races if running twice */ -struct fs * -mountfs(dev, ronly, ip) - dev_t dev; - int ronly; - struct inode *ip; +/* + * Common code for mount and mountroot + * LFS specific + */ +int +lfs_mountfs(devvp, mp, p) + register struct vnode *devvp; + struct mount *mp; + struct proc *p; { - register struct mount *mp = 0; - struct buf *tp = 0; - register struct buf *bp = 0; - register struct fs *fs; + extern struct vnode *rootvp; + register struct lfs *fs; + register struct ufsmount *ump; + struct vnode *vp; + struct buf *bp; struct partinfo dpart; - int havepart = 0, blks; - caddr_t space; - int i, size; - register error; - int needclose = 0; - - error = - (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE, - S_IFBLK); - if (error) - goto out; - needclose = 1; - if ((*bdevsw[major(dev)].d_ioctl)(dev, DIOCGPART, - (caddr_t)&dpart, FREAD) == 0) { - havepart = 1; - size = dpart.disklab->d_secsize; - } else + dev_t dev; + int error, i, ronly, size; + + if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) + return (error); + + if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) size = DEV_BSIZE; -#ifdef SECSIZE - /* - * If possible, determine hardware sector size - * and adjust fsbtodb to correspond. - */ -#endif SECSIZE - if ((*bdevsw[major(dev)].d_ioctl)(dev, DIOCGPART, - (caddr_t)&dpart, FREAD) == 0) { - havepart = 1; + else { size = dpart.disklab->d_secsize; -#ifdef SECSIZE - if (size < MINSECSIZE) { - error = EINVAL; - goto out; - } -#endif SECSIZE - } else - size = DEV_BSIZE; -#ifdef SECSIZE - tp = bread(dev, (daddr_t)(SBOFF / size), SBSIZE, size); -#else SECSIZE - tp = bread(dev, SBLOCK, SBSIZE); -#endif SECSIZE - if (tp->b_flags & B_ERROR) +#ifdef NEVER_USED + dpart.part->p_fstype = FS_LFS; + dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ + dpart.part->p_frag = fs->lfs_frag; /* frags per block */ + dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ +#endif + } + + /* Don't free random space on error. */ + bp = NULL; + ump = NULL; + + /* Read in the superblock. */ + if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp)) goto out; - for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) - if (mp->m_bufp != 0 && dev == mp->m_dev) { - mp = 0; - error = EBUSY; - goto out; - } - for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) - if (mp->m_bufp == 0) - goto found; - mp = 0; - error = EMFILE; /* needs translation */ - goto out; -found: - mp->m_bufp = tp; /* just to reserve this slot */ - mp->m_dev = NODEV; - fs = tp->b_un.b_fs; - if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || - fs->fs_bsize < sizeof(struct fs)) { - error = EINVAL; /* also needs translation */ + error = EINVAL; /* XXX needs translation */ goto out; } - bp = geteblk((int)fs->fs_sbsize); - mp->m_bufp = bp; - bcopy((caddr_t)tp->b_un.b_addr, (caddr_t)bp->b_un.b_addr, - (u_int)fs->fs_sbsize); - brelse(tp); - tp = 0; - fs = bp->b_un.b_fs; - fs->fs_ronly = (ronly != 0); + + /* Allocate the mount structure, copy the superblock into it. */ + ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); + fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); + bcopy(bp->b_data, fs, sizeof(struct lfs)); + if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ + bp->b_flags |= B_INVAL; + brelse(bp); + bp = NULL; + + /* Set up the I/O information */ + fs->lfs_iocount = 0; + + /* Set up the ifile and lock aflags */ + fs->lfs_doifile = 0; + fs->lfs_writer = 0; + fs->lfs_dirops = 0; + fs->lfs_seglock = 0; + + /* Set the file system readonly/modify bits. */ + fs->lfs_ronly = ronly; if (ronly == 0) - fs->fs_fmod = 1; - if (havepart) { - dpart.part->p_fstype = FS_BSDFFS; - dpart.part->p_fsize = fs->fs_fsize; - dpart.part->p_frag = fs->fs_frag; - dpart.part->p_cpg = fs->fs_cpg; - fs->fs_dbsize = size; - } -#ifdef SECSIZE + fs->lfs_fmod = 1; + + /* Initialize the mount structure. */ + dev = devvp->v_rdev; + mp->mnt_data = (qaddr_t)ump; + mp->mnt_stat.f_fsid.val[0] = (long)dev; + mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS; + mp->mnt_flag |= MNT_LOCAL; + ump->um_mountp = mp; + ump->um_dev = dev; + ump->um_devvp = devvp; + ump->um_bptrtodb = 0; + ump->um_seqinc = 1 << fs->lfs_fsbtodb; + ump->um_nindir = fs->lfs_nindir; + for (i = 0; i < MAXQUOTAS; i++) + ump->um_quotas[i] = NULLVP; + devvp->v_specflags |= SI_MOUNTEDON; + /* - * If we have a disk label, force per-partition - * filesystem information to be correct - * and set correct current fsbtodb shift. + * We use the ifile vnode for almost every operation. Instead of + * retrieving it from the hash table each time we retrieve it here, + * artificially increment the reference count and keep a pointer + * to it in the incore copy of the superblock. */ -#endif SECSIZE - if (havepart) { - dpart.part->p_fstype = FS_BSDFFS; - dpart.part->p_fsize = fs->fs_fsize; - dpart.part->p_frag = fs->fs_frag; -#ifdef SECSIZE -#ifdef tahoe - /* - * Save the original fsbtodb shift to restore on updates. - * (Console doesn't understand fsbtodb changes.) - */ - fs->fs_sparecon[0] = fs->fs_fsbtodb; -#endif - i = fs->fs_fsize / size; - for (fs->fs_fsbtodb = 0; i > 1; i >>= 1) - fs->fs_fsbtodb++; -#endif SECSIZE - fs->fs_dbsize = size; - } - blks = howmany(fs->fs_cssize, fs->fs_fsize); - space = wmemall(vmemall, (int)fs->fs_cssize); - if (space == 0) { - error = ENOMEM; + if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) goto out; - } - for (i = 0; i < blks; i += fs->fs_frag) { - size = fs->fs_bsize; - if (i + fs->fs_frag > blks) - size = (blks - i) * fs->fs_fsize; -#ifdef SECSIZE - tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size, - fs->fs_dbsize); -#else SECSIZE - tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size); -#endif SECSIZE - if (tp->b_flags&B_ERROR) { - wmemfree(space, (int)fs->fs_cssize); - goto out; - } - bcopy((caddr_t)tp->b_un.b_addr, space, (u_int)size); - fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; - space += size; - brelse(tp); - tp = 0; - } - mp->m_inodp = ip; - mp->m_dev = dev; - if (ip) { - ip->i_flag |= IMOUNT; - cacheinval(ip); - iunlock(ip); - } - /* Sanity checks for old file systems. XXX */ - fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ - fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ + fs->lfs_ivnode = vp; + VREF(vp); + vput(vp); - return (fs); + return (0); out: - if (error == 0) - error = EIO; - if (needclose && ip) - (void) closei((dev_t)ip->i_rdev, IFBLK, - ronly? FREAD : FREAD|FWRITE); - if (needclose) - (void) closei((dev_t)ip->i_rdev, IFBLK, - ronly? FREAD : FREAD|FWRITE); - if (ip) - iput(ip); - if (mp) - mp->m_bufp = 0; if (bp) brelse(bp); - if (tp) - brelse(tp); - u.u_error = error; + (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); + if (ump) { + free(ump->um_lfs, M_UFSMNT); + free(ump, M_UFSMNT); + mp->mnt_data = (qaddr_t)0; + } + return (error); +} + +/* + * unmount system call + */ +lfs_unmount(mp, mntflags, p) + struct mount *mp; + int mntflags; + struct proc *p; +{ + extern int doforce; + register struct ufsmount *ump; + register struct lfs *fs; + int i, error, flags, ronly; + + flags = 0; + if (mntflags & MNT_FORCE) { + if (!doforce || (mp->mnt_flag & MNT_ROOTFS)) + return (EINVAL); + flags |= FORCECLOSE; + } + + ump = VFSTOUFS(mp); + fs = ump->um_lfs; + return (error); +#ifdef QUOTA + if (mp->mnt_flag & MNT_QUOTA) { + if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) + return (error); + for (i = 0; i < MAXQUOTAS; i++) { + if (ump->um_quotas[i] == NULLVP) + continue; + quotaoff(p, mp, i); + } + /* + * Here we fall through to vflush again to ensure + * that we have gotten rid of all the system vnodes. + */ + } +#endif + if (error = vflush(mp, fs->lfs_ivnode, flags)) + return (error); + fs->lfs_clean = 1; + if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) + return (error); + if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) + panic("lfs_unmount: still dirty blocks on ifile vnode\n"); + vrele(fs->lfs_ivnode); + vgone(fs->lfs_ivnode); + + ronly = !fs->lfs_ronly; + * Get file system statistics. + */ +lfs_statfs(mp, sbp, p) + struct mount *mp; + register struct statfs *sbp; + struct proc *p; +{ + register struct lfs *fs; + register struct ufsmount *ump; + + ump = VFSTOUFS(mp); + fs = ump->um_lfs; + if (fs->lfs_magic != LFS_MAGIC) + panic("lfs_statfs: magic"); + sbp->f_type = MOUNT_LFS; + sbp->f_bsize = fs->lfs_bsize; + sbp->f_iosize = fs->lfs_bsize; + sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); + sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); + sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - + (fs->lfs_dsize - fs->lfs_bfree); + sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); + sbp->f_files = fs->lfs_nfiles; + sbp->f_ffree = sbp->f_bfree * INOPB(fs); + if (sbp != &mp->mnt_stat) { + bcopy((caddr_t)mp->mnt_stat.f_mntonname, + (caddr_t)&sbp->f_mntonname[0], MNAMELEN); + bcopy((caddr_t)mp->mnt_stat.f_mntfromname, + (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); + } return (0); } -umount() +/* + * Go through the disk queues to initiate sandbagged IO; + * go through the inodes to write those that have been modified; + * initiate the writing of the super block if it has been modified. + * + * Note: we are always called with the filesystem marked `MPBUSY'. + */ +lfs_sync(mp, waitfor, cred, p) + struct mount *mp; + int waitfor; + struct ucred *cred; + struct proc *p; { - struct a { - char *fspec; - } *uap = (struct a *)u.u_ap; + int error; - u.u_error = unmount1(uap->fspec, 0); + /* All syncs must be checkpoints until roll-forward is implemented. */ + error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); +#ifdef QUOTA + qsync(mp); +#endif + return (error); } -unmount1(fname, forcibly) - caddr_t fname; - int forcibly; +/* + * Look up an LFS dinode number to find its incore vnode. If not already + * in core, read it in from the specified device. Return the inode locked. + * Detection and handling of mount points must be done by the calling routine. + */ +int +lfs_vget(mp, ino, vpp) + struct mount *mp; + ino_t ino; + struct vnode **vpp; { + register struct lfs *fs; + register struct inode *ip; + struct buf *bp; + struct ifile *ifp; + struct vnode *vp; + struct ufsmount *ump; + daddr_t daddr; dev_t dev; - register struct mount *mp; int error; - register struct inode *ip; - register struct fs *fs; - forcibly = 0; /* XXX */ - forcibly = 0; /* XXX */ - error = getmdev(&dev, fname); - if (error) + ump = VFSTOUFS(mp); + dev = ump->um_dev; + if ((*vpp = ufs_ihashget(dev, ino)) != NULL) + return (0); + + /* Translate the inode number to a disk address. */ + fs = ump->um_lfs; + if (ino == LFS_IFILE_INUM) + daddr = fs->lfs_idaddr; + else { + LFS_IENTRY(ifp, fs, ino, bp); + daddr = ifp->if_daddr; + brelse(bp); + if (daddr == LFS_UNUSED_DADDR) + return (ENOENT); + } + + /* Allocate new vnode/inode. */ + if (error = lfs_vcreate(mp, ino, &vp)) { + *vpp = NULL; return (error); - for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) - if (mp->m_bufp != NULL && dev == mp->m_dev) - goto found; - return (EINVAL); -found: - xumount(dev); /* remove unused sticky files from text table */ - nchinval(dev); /* flush the name cache */ - update(); -#ifdef QUOTA - if ((error = iflush(dev, mp->m_qinod)) && !forcibly) -#else - if ((error = iflush(dev)) && !forcibly) -#endif + } + + /* + * Put it onto its hash chain and lock it so that other requests for + * this inode will block if they arrive while we are sleeping waiting + * for old data structures to be purged or for the contents of the + * disk portion of this inode to be read. + */ + ip = VTOI(vp); + ufs_ihashins(ip); + + /* + * XXX + * This may not need to be here, logically it should go down with + * the i_devvp initialization. + * Ask Kirk. + */ + ip->i_lfs = ump->um_lfs; + + /* Read in the disk contents for the inode, copy into the inode. */ + if (error = + bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { + /* + * 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(). + */ + vput(vp); + brelse(bp); + *vpp = NULL; return (error); -#ifdef QUOTA - closedq(mp); + } + ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); + brelse(bp); + /* - * Here we have to iflush again to get rid of the quota inode. - * A drag, but it would be ugly to cheat, & this doesn't happen often. + * Initialize the vnode from the inode, check for aliases. In all + * cases re-init ip, the underlying vnode/inode may have changed. */ - (void)iflush(dev, (struct inode *)NULL); -#endif - ip = mp->m_inodp; - ip->i_flag &= ~IMOUNT; - fs = mp->m_bufp->b_un.b_fs; - wmemfree((caddr_t)fs->fs_csp[0], (int)fs->fs_cssize); - brelse(mp->m_bufp); - mp->m_bufp = 0; - mp->m_dev = 0; - mpurge(mp - &mount[0]); - error = closei(dev, IFBLK, fs->fs_ronly? FREAD : FREAD|FWRITE); - irele(ip); - return (error); + if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { + vput(vp); + *vpp = NULL; + return (error); + } + /* + * Finish inode initialization now that aliasing has been resolved. + */ + ip->i_devvp = ump->um_devvp; + VREF(ip->i_devvp); + *vpp = vp; + return (0); } -sbupdate(mp) - struct mount *mp; +/* + * File handle to vnode + * + * Have to be really careful about stale file handles: + * - check that the inode number is valid + * - call lfs_vget() to get the locked inode + * - check for an unallocated inode (i_mode == 0) + * - check that the given client host has export rights and return + * those rights via. exflagsp and credanonp + * + * XXX + * use ifile to see if inode is allocated instead of reading off disk + * what is the relationship between my generational number and the NFS + * generational number. + */ +int +lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) + register struct mount *mp; + struct fid *fhp; + struct mbuf *nam; + struct vnode **vpp; + int *exflagsp; + struct ucred **credanonp; { - register struct fs *fs = mp->m_bufp->b_un.b_fs; - register struct buf *bp; - int blks; - caddr_t space; - int i, size; - -#ifdef SECSIZE - bp = getblk(mp->m_dev, (daddr_t)fsbtodb(fs, SBOFF / fs->fs_fsize), - (int)fs->fs_sbsize, fs->fs_dbsize); -#else SECSIZE - bp = getblk(mp->m_dev, SBLOCK, (int)fs->fs_sbsize); -#endif SECSIZE - bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); -#ifdef SECSIZE -#ifdef tahoe - /* restore standard fsbtodb shift */ - bp->b_un.b_fs->fs_fsbtodb = fs->fs_sparecon[0]; - bp->b_un.b_fs->fs_sparecon[0] = 0; -#endif -#endif SECSIZE - bwrite(bp); - blks = howmany(fs->fs_cssize, fs->fs_fsize); - space = (caddr_t)fs->fs_csp[0]; - for (i = 0; i < blks; i += fs->fs_frag) { - size = fs->fs_bsize; - if (i + fs->fs_frag > blks) - size = (blks - i) * fs->fs_fsize; -#ifdef SECSIZE - bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size, - fs->fs_dbsize); -#else SECSIZE - bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size); -#endif SECSIZE - bcopy(space, bp->b_un.b_addr, (u_int)size); - space += size; - bwrite(bp); - } + register struct ufid *ufhp; + + ufhp = (struct ufid *)fhp; + if (ufhp->ufid_ino < ROOTINO) + return (ESTALE); + return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); } /* - * Common code for mount and umount. - * Check that the user's argument is a reasonable - * thing on which to mount, and return the device number if so. + * Vnode pointer to File handle */ -getmdev(pdev, fname) - caddr_t fname; - dev_t *pdev; +/* ARGSUSED */ +lfs_vptofh(vp, fhp) + struct vnode *vp; + struct fid *fhp; { - dev_t dev; register struct inode *ip; - register struct nameidata *ndp = &u.u_nd; - - if (!suser()) - return (u.u_error); - ndp->ni_nameiop = LOOKUP | FOLLOW; - ndp->ni_segflg = UIO_USERSPACE; - ndp->ni_dirp = fname; - ip = namei(ndp); - if (ip == NULL) { - if (u.u_error == ENOENT) - return (ENODEV); /* needs translation */ - return (u.u_error); - } - if ((ip->i_mode&IFMT) != IFBLK) { - iput(ip); - return (ENOTBLK); - } - dev = (dev_t)ip->i_rdev; - iput(ip); - if (major(dev) >= nblkdev) - return (ENXIO); - *pdev = dev; + register struct ufid *ufhp; + + ip = VTOI(vp); + ufhp = (struct ufid *)fhp; + ufhp->ufid_len = sizeof(struct ufid); + ufhp->ufid_ino = ip->i_number; + ufhp->ufid_gen = ip->i_gen; return (0); }