X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/8a4911ca75a1f2fe8fa16e1d73debbb09f6a894d..cc1730771008ddc8f1bccc5ed3aa8a987856137e:/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 7b01a61ce0..707664788b 100644 --- a/usr/src/sys/ufs/lfs/lfs_vfsops.c +++ b/usr/src/sys/ufs/lfs/lfs_vfsops.c @@ -1,112 +1,57 @@ /* - * Copyright (c) 1989 The Regents of the University of California. + * Copyright (c) 1989, 1991 The Regents of the University of California. * All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * %sccs.include.redist.c% * - * @(#)lfs_vfsops.c 7.21 (Berkeley) %G% + * @(#)lfs_vfsops.c 7.67 (Berkeley) %G% */ -#include "param.h" -#include "systm.h" -#include "time.h" -#include "kernel.h" -#include "namei.h" -#include "vnode.h" -#include "mount.h" -#include "buf.h" -#include "ucred.h" -#include "file.h" -#include "disklabel.h" -#include "ioctl.h" -#include "errno.h" -#include "malloc.h" -#include "../ufs/fs.h" -#include "../ufs/ufsmount.h" -#include "../ufs/inode.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "ioctl.h" #include "disklabel.h" #include "stat.h" -/* - * ufs vfs operations. - */ -int ufs_mount(); -int ufs_start(); -int ufs_unmount(); -int ufs_root(); -int ufs_statfs(); -int ufs_sync(); -int ufs_fhtovp(); -int ufs_vptofh(); - -struct vfsops ufs_vfsops = { - ufs_mount, - ufs_start, - ufs_unmount, - ufs_root, - ufs_statfs, - ufs_sync, - ufs_fhtovp, - ufs_vptofh -}; +#include +#include +#include +#include -/* - * ufs mount table. - */ -struct ufsmount mounttab[NMOUNT]; +#include +#include -/* - * Called by vfs_mountroot when ufs is going to be mounted as root - * - * XXX - Need to have a way of figuring the name of the root device - */ -#define ROOTNAME "root_device" +static int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); -ufs_mountroot() -{ - register struct mount *mp; - extern struct vnode *rootvp; - struct ufsmount *ump; - register struct fs *fs; - u_int size; - int error; +struct vfsops lfs_vfsops = { + lfs_mount, + ufs_start, + lfs_unmount, + lfs_root, + ufs_quotactl, + lfs_statfs, + lfs_sync, + lfs_fhtovp, + lfs_vptofh, + lfs_init, +}; - mp = (struct mount *)malloc((u_long)sizeof(struct mount), - M_MOUNT, M_WAITOK); - mp->m_op = &ufs_vfsops; - mp->m_flag = 0; - mp->m_exroot = 0; - error = mountfs(rootvp, mp); - if (error) { - free((caddr_t)mp, M_MOUNT); - return (error); - } - error = vfs_add((struct vnode *)0, mp, 0); - if (error) { - (void)ufs_unmount(mp, 0); - free((caddr_t)mp, M_MOUNT); - return (error); - } - ump = VFSTOUFS(mp); - fs = ump->um_fs; - fs->fs_fsmnt[0] = '/'; - bzero(fs->fs_fsmnt + 1, sizeof(fs->fs_fsmnt) - 1); - (void) copystr(ROOTNAME, ump->um_mntname, MNAMELEN - 1, &size); - bzero(ump->um_mntname + size, MNAMELEN - size); - vfs_unlock(mp); - inittodr(fs->fs_time); - return (0); +int +lfs_mountroot() +{ + panic("lfs_mountroot"); /* XXX -- implement */ } /* @@ -114,473 +59,409 @@ ufs_mountroot() * * mount system call */ -ufs_mount(mp, path, data, ndp) - struct mount *mp; +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 fs *fs; + register struct lfs *fs; /* LFS */ u_int size; int error; if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) return (error); - if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) + + /* Until LFS can do NFS right. XXX */ + if (args.exflags & MNT_EXPORTED) + return (EINVAL); + /* + * Process export requests. + */ + if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) { + if (args.exflags & MNT_EXPORTED) + mp->mnt_flag |= MNT_EXPORTED; + else + mp->mnt_flag &= ~MNT_EXPORTED; + if (args.exflags & MNT_EXRDONLY) + mp->mnt_flag |= MNT_EXRDONLY; + else + mp->mnt_flag &= ~MNT_EXRDONLY; + mp->mnt_exroot = args.exroot; + } + /* + * 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) + return (0); + } + /* + * Not an update, or updating the name: look up the name + * and verify that it refers to a sensible block device. + */ + ndp->ni_nameiop = LOOKUP | FOLLOW; + ndp->ni_segflg = UIO_USERSPACE; + ndp->ni_dirp = args.fspec; + if (error = namei(ndp, p)) return (error); - error = mountfs(devvp, mp); + devvp = ndp->ni_vp; + if (devvp->v_type != VBLK) { + vrele(devvp); + return (ENOTBLK); + } + if (major(devvp->v_rdev) >= nblkdev) { + vrele(devvp); + return (ENXIO); + } + 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); + } if (error) { vrele(devvp); return (error); } ump = VFSTOUFS(mp); - fs = ump->um_fs; + 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); - (void) copyinstr(args.fspec, ump->um_mntname, MNAMELEN - 1, &size); - bzero(ump->um_mntname + size, MNAMELEN - 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); } /* * Common code for mount and mountroot + * LFS specific */ -mountfs(devvp, mp) - struct vnode *devvp; +static int +lfs_mountfs(devvp, mp, p) + register struct vnode *devvp; struct mount *mp; + struct proc *p; { + extern struct vnode *rootvp; + register struct lfs *fs; register struct ufsmount *ump; - struct ufsmount *fmp = NULL; - struct buf *bp = NULL; - register struct fs *fs; - dev_t dev = devvp->v_rdev; + struct inode *ip; + struct vnode *vp; + struct buf *bp; struct partinfo dpart; - int havepart = 0, blks; - caddr_t base, space; - int havepart = 0, blks; - int error, i, size; - int needclose = 0; - int ronly = (mp->m_flag & M_RDONLY) != 0; - - for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) { - if (ump->um_fs == NULL) { - if (fmp == NULL) - fmp = ump; - } else if (dev == ump->um_dev) { - return (EBUSY); /* needs translation */ - } - } - (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE, - S_IFBLK); - if (error) { - ump->um_fs = NULL; + daddr_t seg_addr; + dev_t dev; + int error, i, ronly, size; + + if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) return (error); - } - needclose = 1; - if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) + + if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) size = DEV_BSIZE; else { - havepart = 1; size = dpart.disklab->d_secsize; +#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 } - if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) { - ump->um_fs = NULL; + + /* 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; - } - fs = bp->b_un.b_fs; - ump->um_fs = NULL; - error = EINVAL; /* XXX also needs translation */ + error = EINVAL; /* XXX needs translation */ goto out; } - ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, - M_WAITOK); - bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, - (u_int)fs->fs_sbsize); +#ifdef DEBUG + lfs_dump_super(fs); +#endif + + /* Allocate the mount structure, copy the superblock into it. */ + ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); + ump->um_lfs = malloc(sizeof(struct lfs), M_SUPERBLK, M_WAITOK); + bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(struct lfs)); + if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ + bp->b_flags |= B_INVAL; brelse(bp); bp = NULL; - fs = ump->um_fs; - fs->fs_ronly = ronly; + + /* Set up the I/O information */ + fs->lfs_iocount = 0; + /* XXX NOTUSED: fs->lfs_seglist = NULL; */ + + /* Set the file system readonly/modify bits. */ + fs = ump->um_lfs; + 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; - } -#ifdef SECSIZE - /* - * If we have a disk label, force per-partition - * filesystem information to be correct - * and set correct current fsbtodb shift. - */ -#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); - base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, - M_WAITOK); - 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 - error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, - NOCRED, &bp); - if (error) { - free((caddr_t)base, M_SUPERBLK); - goto out; - } - bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); - fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; - space += size; - brelse(bp); - bp = NULL; - } - mp->m_data = (qaddr_t)ump; - mp->m_bsize = fs->fs_bsize; - mp->m_fsize = fs->fs_fsize; - mp->m_fsid.val[0] = (long)dev; - mp->m_fsid.val[1] = MOUNT_UFS; + 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_qinod = NULL; - devvp->v_mount = mp; + for (i = 0; i < MAXQUOTAS; i++) + ump->um_quotas[i] = NULLVP; + + /* Read the ifile disk inode and store it in a vnode. */ + if (error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp)) + goto out; + if (error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp)) + goto out; + ip = VTOI(vp); + VREF(ip->i_devvp); + + /* The ifile inode is stored in the superblock. */ + fs->lfs_ivnode = vp; + + /* Copy the on-disk inode into place. */ + ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino); + brelse(bp); + + /* Initialize the associated vnode */ + vp->v_type = IFTOVT(ip->i_mode); - /* 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 */ - if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ - fs->fs_nrpos = 8; /* XXX */ + devvp->v_specflags |= SI_MOUNTEDON; + VREF(ip->i_devvp); return (0); out: - if (needclose) - (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); - if (ump->um_fs) { - free((caddr_t)ump->um_fs, M_SUPERBLK); - ump->um_fs = NULL; - } if (bp) brelse(bp); + (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); + if (ump) { + free(ump->um_lfs, M_SUPERBLK); + free(ump, M_UFSMNT); + mp->mnt_data = (qaddr_t)0; + } return (error); } -/* - * Make a filesystem operational. - * Nothing to do at the moment. - */ -ufs_start(mp, flags) - struct mount *mp; - int flags; -{ - - return (0); -} - /* * unmount system call */ -ufs_unmount(mp, flags) +lfs_unmount(mp, mntflags, p) struct mount *mp; - int flags; + int mntflags; + struct proc *p; { + extern int doforce; register struct ufsmount *ump; - register struct fs *fs; - dev_t dev; - int error, ronly; + register struct lfs *fs; /* LFS */ + int i, error, ronly, flags = 0; + int ndirty; /* LFS */ - if (flags & MNT_FORCE) - return (EINVAL); - ump = VFSTOUFS(mp); - dev = ump->um_dev; -#ifdef QUOTA - if ((error = iflush(dev, mp->m_qinod)) && !forcibly) -#else - if ((error = iflush(dev)) && !forcibly) +#ifdef VERBOSE + printf("lfs_unmount\n"); #endif + if (mntflags & MNT_FORCE) { + if (!doforce || mp == rootfs) + return (EINVAL); + flags |= FORCECLOSE; + } + if (error = lfs_segwrite(mp, 1)) + return(error); + +ndirty = lfs_umountdebug(mp); +printf("lfs_umountdebug: returned %d dirty\n", ndirty); +return(0); + if (mntinvalbuf(mp)) + return (EBUSY); + ump = VFSTOUFS(mp); return (error); #ifdef QUOTA - (void)closedq(ump); - /* - * 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. - */ - (void)iflush(dev, (struct inode *)NULL); + if (mp->mnt_flag & MNT_QUOTA) { + if (error = vflush(mp, NULLVP, 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, NULLVP, flags)) + return (error); +#ifdef NOTLFS /* LFS */ fs = ump->um_fs; ronly = !fs->fs_ronly; - free((caddr_t)fs->fs_csp[0], M_SUPERBLK); - error = closei(dev, IFBLK, fs->fs_ronly? FREAD : FREAD|FWRITE); - irele(ip); - return (error); -} - -/* - * Return root of a filesystem - */ -ufs_root(mp, vpp) - struct mount *mp; - struct vnode **vpp; -{ - struct inode tip, *ip; - int error; - - tip.i_dev = VFSTOUFS(mp)->um_dev; - tip.i_vnode.v_mount = mp; - error = iget(&tip, (ino_t)ROOTINO, &ip); - if (error) - return (error); - *vpp = ITOV(ip); - return (0); -} - -/* +#else + fs = ump->um_lfs; + ronly = !fs->lfs_ronly; +#endif * Get file system statistics. */ -ufs_statfs(mp, sbp) +lfs_statfs(mp, sbp, p) struct mount *mp; register struct statfs *sbp; + struct proc *p; { + register struct lfs *fs; register struct ufsmount *ump; - register struct fs *fs; ump = VFSTOUFS(mp); - fs = ump->um_fs; - if (fs->fs_magic != FS_MAGIC) - panic("ufs_statfs"); - sbp->f_type = MOUNT_UFS; - sbp->f_flags = mp->m_flag &~ (M_MLOCK|M_MWAIT); - sbp->f_fsize = fs->fs_fsize; - sbp->f_bsize = fs->fs_bsize; - sbp->f_blocks = fs->fs_dsize; - sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + - fs->fs_cstotal.cs_nffree; - sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - - (fs->fs_dsize - sbp->f_bfree); - if (sbp->f_bavail < 0) - sbp->f_bavail = 0; - sbp->f_files = fs->fs_ncg * fs->fs_ipg; - sbp->f_ffree = fs->fs_cstotal.cs_nifree; - sbp->f_fsid = mp->m_fsid; - bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)&sbp->f_mntonname[0], MNAMELEN); - bcopy((caddr_t)ump->um_mntname, (caddr_t)&sbp->f_mntfromname[0], - MNAMELEN); + 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 = fs->lfs_dsize; + sbp->f_bfree = fs->lfs_bfree; + sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - + (fs->lfs_dsize - sbp->f_bfree); + sbp->f_files = fs->lfs_nfiles; + sbp->f_ffree = fs->lfs_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); } -int syncprt = 0; - /* * 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'. */ -ufs_sync(mp, waitfor) +lfs_sync(mp, waitfor) struct mount *mp; int waitfor; { - register struct inode *ip; - register struct ufsmount *ump = VFSTOUFS(mp); - register struct fs *fs; - int error = 0; - static int updlock = 0; + extern int crashandburn, syncprt; + static int sync_lock, sync_want; + int error; - if (syncprt) - bufstats(); - if (updlock) - return (EBUSY); - fs = ump->um_fs; - if (fs == (struct fs *)1) +#ifdef VERBOSE + printf("lfs_sync\n"); +#endif + +#ifdef DIAGNOSTIC + if (crashandburn) return (0); - updlock++; - /* - * Write back modified superblock. - * Consistency check that the superblock - * is still in the buffer cache. - */ - if (fs->fs_fmod != 0) { - if (fs->fs_ronly != 0) { /* XXX */ - printf("fs = %s\n", fs->fs_fsmnt); - panic("update: rofs mod"); - } - fs->fs_fmod = 0; - fs->fs_time = time.tv_sec; - error = sbupdate(ump, waitfor); - } +#endif /* - * Write back each (modified) inode. + * Meta data blocks are only marked dirty, not busy, so LFS syncs + * must be single threaded. */ - for (ip = inode; ip < inodeNINODE; ip++) { - if (ip->i_devvp != ump->um_devvp || - (ip->i_flag & ILOCKED) != 0 || ITOV(ip)->v_count == 0 || - (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0) - continue; - ILOCK(ip); - VREF(ITOV(ip)); - error = iupdat(ip, &time, &time, waitfor == MNT_WAIT); - iput(ip); + while (sync_lock) { + sync_want = 1; + if (error = tsleep(&sync_lock, PLOCK | PCATCH, "lfs sync", 0)) + return (error); } - updlock = 0; - /* - * Force stale buffer cache information to be flushed. - */ - bflush(ump->um_devvp->v_mount); - return (error); -} + sync_lock = 1; -/* - * Write a superblock and associated information back to disk. - */ -sbupdate(mp, waitfor) - struct ufsmount *mp; - int waitfor; -{ - register struct fs *fs = mp->um_fs; - register struct buf *bp; - int blks; - caddr_t space; - int i, size, error = 0; - -#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->um_devvp, SBLOCK, (int)fs->fs_sbsize); -#endif SECSIZE - bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); - /* Restore compatibility to old file systems. XXX */ - if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ - bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ -#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; + if (syncprt) + ufs_bufstats(); + + /* All syncs must be checkpoints until roll-forward is implemented. */ + error = lfs_segwrite(mp, 1); +#ifdef QUOTA + qsync(mp); #endif -#endif SECSIZE - if (waitfor == MNT_WAIT) - error = bwrite(bp); - else - bawrite(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->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); -#endif SECSIZE - bcopy(space, bp->b_un.b_addr, (u_int)size); - space += size; - if (waitfor == MNT_WAIT) - error = bwrite(bp); - else - bawrite(bp); + sync_lock = 0; + if (sync_want) { + sync_want = 0; + wakeup(&sync_lock); } return (error); } -/* - * Print out statistics on the current allocation of the buffer pool. - * Can be enabled to print out on every ``sync'' by setting "syncprt" - * above. - */ -bufstats() -{ - int s, i, j, count; - register struct buf *bp, *dp; - int counts[MAXBSIZE/CLBYTES+1]; - static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; - - for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { - count = 0; - for (j = 0; j <= MAXBSIZE/CLBYTES; j++) - counts[j] = 0; - s = splbio(); - for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { - counts[dp->b_bufsize/CLBYTES]++; - count++; - } - splx(s); - printf("%s: total-%d", bname[i], count); - for (j = 0; j <= MAXBSIZE/CLBYTES; j++) - if (counts[j] != 0) - printf(", %d-%d", j * CLBYTES, counts[j]); - printf("\n"); - } -} - /* * File handle to vnode * * Have to be really careful about stale file handles: - * - check that the inode number is in range - * - call iget() to get the locked inode + * - 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 generation number matches + * + * 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. */ -ufs_fhtovp(mp, fhp, vpp) +int +lfs_fhtovp(mp, fhp, vpp) register struct mount *mp; struct fid *fhp; struct vnode **vpp; { + register struct inode *ip; register struct ufid *ufhp; - register struct fs *fs; - struct inode tip, *ip; + struct vnode *nvp; int error; ufhp = (struct ufid *)fhp; - fs = VFSTOUFS(mp)->um_fs; - if (ufhp->ufid_ino < ROOTINO || - ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { - *vpp = (struct vnode *)0; + if (ufhp->ufid_ino < ROOTINO) return (EINVAL); - } - tip.i_dev = VFSTOUFS(mp)->um_dev; - tip.i_vnode.v_mount = mp; - if (error = iget(&tip, ufhp->ufid_ino, &ip)) { - *vpp = (struct vnode *)0; + if (error = lfs_vget(mp, ufhp->ufid_ino, &nvp)) { + *vpp = NULLVP; return (error); } + ip = VTOI(nvp); if (ip->i_mode == 0) { - iput(ip); - *vpp = (struct vnode *)0; + ufs_iput(ip); + *vpp = NULLVP; return (EINVAL); } if (ip->i_gen != ufhp->ufid_gen) { - iput(ip); - *vpp = (struct vnode *)0; + ufs_iput(ip); + *vpp = NULLVP; return (EINVAL); } - *vpp = ITOV(ip); + *vpp = nvp; return (0); } @@ -588,49 +469,17 @@ ufs_fhtovp(mp, fhp, vpp) * Vnode pointer to File handle */ /* ARGSUSED */ -ufs_vptofh(vp, fhp) +lfs_vptofh(vp, fhp) struct vnode *vp; struct fid *fhp; { - register struct inode *ip = VTOI(vp); + register struct inode *ip; 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); } - -/* - * Common code for mount and quota. - * Check that the user's argument is a reasonable - * thing on which to mount, and return the device number if so. - */ -getmdev(devvpp, fname, ndp) - struct vnode **devvpp; - caddr_t fname; - register struct nameidata *ndp; -{ - register struct vnode *vp; - int error; - - ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; - ndp->ni_segflg = UIO_USERSPACE; - ndp->ni_dirp = fname; - if (error = namei(ndp)) { - if (error == ENOENT) - return (ENODEV); /* needs translation */ - return (error); - } - vp = ndp->ni_vp; - if (vp->v_type != VBLK) { - vput(vp); - return (ENOTBLK); - } - if (major(vp->v_rdev) >= nblkdev) - return (ENXIO); - iunlock(VTOI(vp)); - *devvpp = vp; - return (0); -}