From 10f666af84d48e89e4e2960415c9b616fce4077f Mon Sep 17 00:00:00 2001 From: dyson Date: Mon, 10 Feb 1997 02:22:35 +0000 Subject: This is the kernel Lite/2 commit. There are some requisite userland changes, so don't expect to be able to run the kernel as-is (very well) without the appropriate Lite/2 userland changes. The system boots and can mount UFS filesystems. Untested: ext2fs, msdosfs, NFS Known problems: Incorrect Berkeley ID strings in some files. Mount_std mounts will not work until the getfsent library routine is changed. Reviewed by: various people Submitted by: Jeffery Hsu --- sys/ufs/ffs/ffs_alloc.c | 244 +++++++++++++++++++++++++--------- sys/ufs/ffs/ffs_balloc.c | 116 +++++++++------- sys/ufs/ffs/ffs_extern.h | 41 ++++-- sys/ufs/ffs/ffs_inode.c | 50 ++++--- sys/ufs/ffs/ffs_subr.c | 27 ++-- sys/ufs/ffs/ffs_vfsops.c | 314 +++++++++++++++++++++++++++----------------- sys/ufs/ffs/ffs_vnops.c | 51 +++++-- sys/ufs/ffs/fs.h | 288 +++++++++++++++++++++------------------- sys/ufs/lfs/lfs_subr.c | 9 +- sys/ufs/lfs/lfs_syscalls.c | 10 +- sys/ufs/mfs/mfs_extern.h | 4 +- sys/ufs/mfs/mfs_vfsops.c | 24 ++-- sys/ufs/mfs/mfs_vnops.c | 24 ++-- sys/ufs/mfs/mfsnode.h | 8 +- sys/ufs/ufs/dinode.h | 53 +++++--- sys/ufs/ufs/dir.h | 63 +++++---- sys/ufs/ufs/inode.h | 100 +++++++------- sys/ufs/ufs/quota.h | 48 +++---- sys/ufs/ufs/ufs_bmap.c | 21 +-- sys/ufs/ufs/ufs_extern.h | 17 ++- sys/ufs/ufs/ufs_ihash.c | 117 +++++++---------- sys/ufs/ufs/ufs_inode.c | 88 +++---------- sys/ufs/ufs/ufs_lookup.c | 151 ++++++++++++++------- sys/ufs/ufs/ufs_quota.c | 151 +++++++++------------ sys/ufs/ufs/ufs_readwrite.c | 14 +- sys/ufs/ufs/ufs_vfsops.c | 56 +++++--- sys/ufs/ufs/ufs_vnops.c | 266 +++++++++++++++++++------------------ sys/ufs/ufs/ufsmount.h | 34 ++++- 28 files changed, 1352 insertions(+), 1037 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index e1272ab..4787c1c 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 + * @(#)ffs_alloc.c 8.18 (Berkeley) 5/26/95 * $FreeBSD$ */ @@ -57,23 +57,23 @@ extern u_long nextgennumber; -typedef daddr_t allocfcn_t __P((struct inode *ip, int cg, daddr_t bpref, - int size)); +typedef ufs_daddr_t allocfcn_t __P((struct inode *ip, int cg, ufs_daddr_t bpref, + int size)); -static daddr_t ffs_alloccg __P((struct inode *, int, daddr_t, int)); -static daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, daddr_t)); -#ifdef notyet -static daddr_t ffs_clusteralloc __P((struct inode *, int, daddr_t, int)); -#endif +static ufs_daddr_t ffs_alloccg __P((struct inode *, int, ufs_daddr_t, int)); +static ufs_daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, ufs_daddr_t)); +static void ffs_clusteracct __P((struct fs *, struct cg *, ufs_daddr_t, + int)); +static ufs_daddr_t ffs_clusteralloc __P((struct inode *, int, ufs_daddr_t, + int)); static ino_t ffs_dirpref __P((struct fs *)); -static daddr_t ffs_fragextend __P((struct inode *, int, long, int, int)); +static ufs_daddr_t ffs_fragextend __P((struct inode *, int, long, int, int)); static void ffs_fserr __P((struct fs *, u_int, char *)); static u_long ffs_hashalloc __P((struct inode *, int, long, int, allocfcn_t *)); -static ino_t ffs_nodealloccg __P((struct inode *, int, daddr_t, int)); -static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int)); - -static void ffs_clusteracct __P((struct fs *, struct cg *, daddr_t, int)); +static ino_t ffs_nodealloccg __P((struct inode *, int, ufs_daddr_t, int)); +static ufs_daddr_t ffs_mapsearch __P((struct fs *, struct cg *, ufs_daddr_t, + int)); /* * Allocate a block in the file system. @@ -97,19 +97,18 @@ static void ffs_clusteracct __P((struct fs *, struct cg *, daddr_t, int)); int ffs_alloc(ip, lbn, bpref, size, cred, bnp) register struct inode *ip; - daddr_t lbn, bpref; + ufs_daddr_t lbn, bpref; int size; struct ucred *cred; - daddr_t *bnp; + ufs_daddr_t *bnp; { register struct fs *fs; - daddr_t bno; + ufs_daddr_t bno; int cg; #ifdef QUOTA int error; #endif - *bnp = 0; fs = ip->i_fs; #ifdef DIAGNOSTIC @@ -136,7 +135,8 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) cg = ino_to_cg(fs, ip->i_number); else cg = dtog(fs, bpref); - bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size, ffs_alloccg); + bno = (ufs_daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size, + ffs_alloccg); if (bno > 0) { ip->i_blocks += btodb(size); ip->i_flag |= IN_CHANGE | IN_UPDATE; @@ -166,8 +166,8 @@ nospace: int ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) register struct inode *ip; - daddr_t lbprev; - daddr_t bpref; + ufs_daddr_t lbprev; + ufs_daddr_t bpref; int osize, nsize; struct ucred *cred; struct buf **bpp; @@ -175,7 +175,7 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) register struct fs *fs; struct buf *bp; int cg, request, error; - daddr_t bprev, bno; + ufs_daddr_t bprev, bno; *bpp = 0; fs = ip->i_fs; @@ -285,7 +285,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) panic("ffs_realloccg: bad optim"); /* NOTREACHED */ } - bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, ffs_alloccg); + bno = (ufs_daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, + ffs_alloccg); if (bno > 0) { bp->b_blkno = fsbtodb(fs, bno); ffs_blkfree(ip, bprev, (long)osize); @@ -331,7 +332,13 @@ nospace: * the previous block allocation will be used. */ static int doasyncfree = 1; -SYSCTL_INT(_debug, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); +SYSCTL_INT(_vfs_ffs, FFS_ASYNCFREE, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); + +int doreallocblks = 1; +SYSCTL_INT(_vfs_ffs, FFS_REALLOCBLKS, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, ""); + +static int prtrealloc = 0; + int ffs_reallocblks(ap) struct vop_reallocblks_args /* { @@ -346,13 +353,15 @@ ffs_reallocblks(ap) struct inode *ip; struct vnode *vp; struct buf *sbp, *ebp; - daddr_t *bap, *sbap, *ebap = 0; + ufs_daddr_t *bap, *sbap, *ebap = 0; struct cluster_save *buflist; - daddr_t start_lbn, end_lbn, soff, newblk, blkno; + ufs_daddr_t start_lbn, end_lbn, soff, newblk, blkno; struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; int i, len, start_lvl, end_lvl, pref, ssize; struct timeval tv; + if (doreallocblks == 0) + return (ENOSPC); vp = ap->a_vp; ip = VTOI(vp); fs = ip->i_fs; @@ -363,9 +372,18 @@ ffs_reallocblks(ap) start_lbn = buflist->bs_children[0]->b_lblkno; end_lbn = start_lbn + len - 1; #ifdef DIAGNOSTIC + for (i = 0; i < len; i++) + if (!ffs_checkblk(ip, + dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize)) + panic("ffs_reallocblks: unallocated block 1"); for (i = 1; i < len; i++) if (buflist->bs_children[i]->b_lblkno != start_lbn + i) - panic("ffs_reallocblks: non-cluster"); + panic("ffs_reallocblks: non-logical cluster"); + blkno = buflist->bs_children[0]->b_blkno; + ssize = fsbtodb(fs, fs->fs_frag); + for (i = 1; i < len - 1; i++) + if (buflist->bs_children[i]->b_blkno != blkno + (i * ssize)) + panic("ffs_reallocblks: non-physical cluster %d", i); #endif /* * If the latest allocation is in a new cylinder group, assume that @@ -390,7 +408,7 @@ ffs_reallocblks(ap) brelse(sbp); return (ENOSPC); } - sbap = (daddr_t *)sbp->b_data; + sbap = (ufs_daddr_t *)sbp->b_data; soff = idp->in_off; } /* @@ -410,12 +428,12 @@ ffs_reallocblks(ap) ssize = len - (idp->in_off + 1); if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp)) goto fail; - ebap = (daddr_t *)ebp->b_data; + ebap = (ufs_daddr_t *)ebp->b_data; } /* * Search the block map looking for an allocation of the desired size. */ - if ((newblk = (daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref, + if ((newblk = (ufs_daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref, len, ffs_clusteralloc)) == 0) goto fail; /* @@ -425,14 +443,26 @@ ffs_reallocblks(ap) * block pointers in the inode and indirect blocks associated * with the file. */ +#ifdef DEBUG + if (prtrealloc) + printf("realloc: ino %d, lbns %d-%d\n\told:", ip->i_number, + start_lbn, end_lbn); +#endif blkno = newblk; for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) { if (i == ssize) bap = ebap; #ifdef DIAGNOSTIC - if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) + if (!ffs_checkblk(ip, + dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize)) + panic("ffs_reallocblks: unallocated block 2"); + if (dbtofsb(fs, buflist->bs_children[i]->b_blkno) != *bap) panic("ffs_reallocblks: alloc mismatch"); #endif +#ifdef DEBUG + if (prtrealloc) + printf(" %d,", *bap); +#endif *bap++ = blkno; } /* @@ -469,11 +499,28 @@ ffs_reallocblks(ap) /* * Last, free the old blocks and assign the new blocks to the buffers. */ +#ifdef DEBUG + if (prtrealloc) + printf("\n\tnew:"); +#endif for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) { ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize); buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); +#ifdef DEBUG + if (!ffs_checkblk(ip, + dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize)) + panic("ffs_reallocblks: unallocated block 3"); + if (prtrealloc) + printf(" %d,", blkno); +#endif + } +#ifdef DEBUG + if (prtrealloc) { + prtrealloc--; + printf("\n"); } +#endif return (0); fail: @@ -615,17 +662,17 @@ ffs_dirpref(fs) * fs_rotdelay milliseconds. This is to allow time for the processor to * schedule another I/O transfer. */ -daddr_t +ufs_daddr_t ffs_blkpref(ip, lbn, indx, bap) struct inode *ip; - daddr_t lbn; + ufs_daddr_t lbn; int indx; - daddr_t *bap; + ufs_daddr_t *bap; { register struct fs *fs; register int cg; int avgbfree, startcg; - daddr_t nextblk; + ufs_daddr_t nextblk; fs = ip->i_fs; if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { @@ -740,7 +787,7 @@ ffs_hashalloc(ip, cg, pref, size, allocator) * Check to see if the necessary fragments are available, and * if they are, allocate them. */ -static daddr_t +static ufs_daddr_t ffs_fragextend(ip, cg, bprev, osize, nsize) struct inode *ip; int cg; @@ -810,11 +857,11 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) * Check to see if a block of the appropriate size is available, * and if it is, allocate it. */ -static daddr_t +static ufs_daddr_t ffs_alloccg(ip, cg, bpref, size) struct inode *ip; int cg; - daddr_t bpref; + ufs_daddr_t bpref; int size; { register struct fs *fs; @@ -904,13 +951,13 @@ ffs_alloccg(ip, cg, bpref, size) * Note that this routine only allocates fs_bsize blocks; these * blocks may be fragmented by the routine that allocates them. */ -static daddr_t +static ufs_daddr_t ffs_alloccgblk(fs, cgp, bpref) register struct fs *fs; register struct cg *cgp; - daddr_t bpref; + ufs_daddr_t bpref; { - daddr_t bno, blkno; + ufs_daddr_t bno, blkno; int cylno, pos, delta; short *cylbp; register int i; @@ -1016,21 +1063,22 @@ gotit: * are multiple choices in the same cylinder group. Instead we just * take the first one that we find following bpref. */ -static daddr_t +static ufs_daddr_t ffs_clusteralloc(ip, cg, bpref, len) struct inode *ip; int cg; - daddr_t bpref; + ufs_daddr_t bpref; int len; { register struct fs *fs; register struct cg *cgp; struct buf *bp; - int i, run, bno, bit, map; + int i, got, run, bno, bit, map; u_char *mapp; + int32_t *lp; fs = ip->i_fs; - if (fs->fs_cs(fs, cg).cs_nbfree < len) + if (fs->fs_maxcluster[cg] < len) return (NULL); if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, NOCRED, &bp)) @@ -1042,11 +1090,25 @@ ffs_clusteralloc(ip, cg, bpref, len) * Check to see if a cluster of the needed size (or bigger) is * available in this cylinder group. */ + lp = &cg_clustersum(cgp)[len]; for (i = len; i <= fs->fs_contigsumsize; i++) - if (cg_clustersum(cgp)[i] > 0) + if (*lp++ > 0) break; - if (i > fs->fs_contigsumsize) + if (i > fs->fs_contigsumsize) { + /* + * This is the first time looking for a cluster in this + * cylinder group. Update the cluster summary information + * to reflect the true maximum sized cluster so that + * future cluster allocation requests can avoid reading + * the cylinder group map only to find no clusters. + */ + lp = &cg_clustersum(cgp)[len - 1]; + for (i = len - 1; i > 0; i--) + if (*lp-- > 0) + break; + fs->fs_maxcluster[cg] = i; goto fail; + } /* * Search the cluster map to find a big enough cluster. * We take the first one that we find, even if it is larger @@ -1065,7 +1127,7 @@ ffs_clusteralloc(ip, cg, bpref, len) mapp = &cg_clustersfree(cgp)[bpref / NBBY]; map = *mapp++; bit = 1 << (bpref % NBBY); - for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) { + for (run = 0, got = bpref; got < cgp->cg_nclusterblks; got++) { if ((map & bit) == 0) { run = 0; } else { @@ -1073,22 +1135,27 @@ ffs_clusteralloc(ip, cg, bpref, len) if (run == len) break; } - if ((i & (NBBY - 1)) != (NBBY - 1)) { + if ((got & (NBBY - 1)) != (NBBY - 1)) { bit <<= 1; } else { map = *mapp++; bit = 1; } } - if (i == cgp->cg_nclusterblks) + if (got == cgp->cg_nclusterblks) goto fail; /* * Allocate the cluster that we have found. */ - bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1); + for (i = 1; i <= len; i++) + if (!ffs_isblock(fs, cg_blksfree(cgp), got - run + i)) + panic("ffs_clusteralloc: map mismatch"); + bno = cg * fs->fs_fpg + blkstofrags(fs, got - run + 1); + if (dtog(fs, bno) != cg) + panic("ffs_clusteralloc: allocated out of group"); len = blkstofrags(fs, len); for (i = 0; i < len; i += fs->fs_frag) - if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i) + if ((got = ffs_alloccgblk(fs, cgp, bno + i)) != bno + i) panic("ffs_clusteralloc: lost block"); bdwrite(bp); return (bno); @@ -1112,7 +1179,7 @@ static ino_t ffs_nodealloccg(ip, cg, ipref, mode) struct inode *ip; int cg; - daddr_t ipref; + ufs_daddr_t ipref; int mode; { register struct fs *fs; @@ -1191,13 +1258,13 @@ gotit: void ffs_blkfree(ip, bno, size) register struct inode *ip; - daddr_t bno; + ufs_daddr_t bno; long size; { register struct fs *fs; register struct cg *cgp; struct buf *bp; - daddr_t blkno; + ufs_daddr_t blkno; int i, error, cg, blk, frags, bbase; fs = ip->i_fs; @@ -1288,6 +1355,56 @@ ffs_blkfree(ip, bno, size) bdwrite(bp); } +#ifdef DIAGNOSTIC +/* + * Verify allocation of a block or fragment. Returns true if block or + * fragment is allocated, false if it is free. + */ +ffs_checkblk(ip, bno, size) + struct inode *ip; + ufs_daddr_t bno; + long size; +{ + struct fs *fs; + struct cg *cgp; + struct buf *bp; + int i, error, frags, free; + + fs = ip->i_fs; + if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) { + printf("bsize = %d, size = %d, fs = %s\n", + fs->fs_bsize, size, fs->fs_fsmnt); + panic("checkblk: bad size"); + } + if ((u_int)bno >= fs->fs_size) + panic("checkblk: bad block %d", bno); + error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, dtog(fs, bno))), + (int)fs->fs_cgsize, NOCRED, &bp); + if (error) { + brelse(bp); + return; + } + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp)) { + brelse(bp); + return; + } + bno = dtogd(fs, bno); + if (size == fs->fs_bsize) { + free = ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno)); + } else { + frags = numfrags(fs, size); + for (free = 0, i = 0; i < frags; i++) + if (isset(cg_blksfree(cgp), bno + i)) + free++; + if (free != 0 && free != frags) + panic("checkblk: partially free fragment"); + } + brelse(bp); + return (!free); +} +#endif /* DIAGNOSTIC */ + /* * Free an inode. * @@ -1355,14 +1472,14 @@ ffs_vfree(ap) * It is a panic if a request is made to find a block if none are * available. */ -static daddr_t +static ufs_daddr_t ffs_mapsearch(fs, cgp, bpref, allocsiz) register struct fs *fs; register struct cg *cgp; - daddr_t bpref; + ufs_daddr_t bpref; int allocsiz; { - daddr_t bno; + ufs_daddr_t bno; int start, len, loc, i; int blk, field, subfield, pos; @@ -1423,10 +1540,11 @@ static void ffs_clusteracct(fs, cgp, blkno, cnt) struct fs *fs; struct cg *cgp; - daddr_t blkno; + ufs_daddr_t blkno; int cnt; { - long *sump; + int32_t *sump; + int32_t *lp; u_char *freemapp, *mapp; int i, start, end, forw, back, map, bit; @@ -1495,6 +1613,14 @@ ffs_clusteracct(fs, cgp, blkno, cnt) sump[back] -= cnt; if (forw > 0) sump[forw] -= cnt; + /* + * Update cluster summary information. + */ + lp = &sump[fs->fs_contigsumsize]; + for (i = fs->fs_contigsumsize; i > 0; i--) + if (*lp-- > 0) + break; + fs->fs_maxcluster[cgp->cg_cgx] = i; } /* diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 4d382fa..5d7d798 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93 + * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 * $FreeBSD$ */ @@ -56,27 +56,27 @@ * the inode and the logical block number in a file. */ int -ffs_balloc(ip, bn, size, cred, bpp, flags) +ffs_balloc(ip, lbn, size, cred, bpp, flags) register struct inode *ip; - register daddr_t bn; + register ufs_daddr_t lbn; int size; struct ucred *cred; struct buf **bpp; int flags; { register struct fs *fs; - register daddr_t nb; + register ufs_daddr_t nb; struct buf *bp, *nbp; struct vnode *vp = ITOV(ip); struct indir indirs[NIADDR + 2]; - daddr_t newb, lbn, *bap, pref; - int osize, nsize, num, i, error; + ufs_daddr_t newb, *bap, pref; + int deallocated, osize, nsize, num, i, error; + ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1]; *bpp = NULL; - if (bn < 0) + if (lbn < 0) return (EFBIG); fs = ip->i_fs; - lbn = bn; /* * If the next write will extend the file into a new block, @@ -84,7 +84,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) * this fragment has to be extended to be a full block. */ nb = lblkno(fs, ip->i_size); - if (nb < NDADDR && nb < bn) { + if (nb < NDADDR && nb < lbn) { osize = blksize(fs, ip, nb); if (osize < fs->fs_bsize && osize > 0) { error = ffs_realloccg(ip, nb, @@ -104,10 +104,10 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) /* * The first NDADDR blocks are direct blocks */ - if (bn < NDADDR) { - nb = ip->i_db[bn]; - if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) { - error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp); + if (lbn < NDADDR) { + nb = ip->i_db[lbn]; + if (nb != 0 && ip->i_size >= (lbn + 1) * fs->fs_bsize) { + error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp); if (error) { brelse(bp); return (error); @@ -123,35 +123,35 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) osize = fragroundup(fs, blkoff(fs, ip->i_size)); nsize = fragroundup(fs, size); if (nsize <= osize) { - error = bread(vp, bn, osize, NOCRED, &bp); + error = bread(vp, lbn, osize, NOCRED, &bp); if (error) { brelse(bp); return (error); } bp->b_blkno = fsbtodb(fs, nb); } else { - error = ffs_realloccg(ip, bn, - ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]), - osize, nsize, cred, &bp); + error = ffs_realloccg(ip, lbn, + ffs_blkpref(ip, lbn, (int)lbn, + &ip->i_db[0]), osize, nsize, cred, &bp); if (error) return (error); } } else { - if (ip->i_size < (bn + 1) * fs->fs_bsize) + if (ip->i_size < (lbn + 1) * fs->fs_bsize) nsize = fragroundup(fs, size); else nsize = fs->fs_bsize; - error = ffs_alloc(ip, bn, - ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]), + error = ffs_alloc(ip, lbn, + ffs_blkpref(ip, lbn, (int)lbn, &ip->i_db[0]), nsize, cred, &newb); if (error) return (error); - bp = getblk(vp, bn, nsize, 0, 0); + bp = getblk(vp, lbn, nsize, 0, 0); bp->b_blkno = fsbtodb(fs, newb); if (flags & B_CLRBUF) vfs_bio_clrbuf(bp); } - ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); + ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bpp = bp; return (0); @@ -160,8 +160,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) * Determine the number of levels of indirection. */ pref = 0; - error = ufs_getlbns(vp, bn, indirs, &num); - if (error) + if (error = ufs_getlbns(vp, lbn, indirs, &num)) return(error); #ifdef DIAGNOSTIC if (num < 1) @@ -172,26 +171,26 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) */ --num; nb = ip->i_ib[indirs[0].in_off]; + allocib = NULL; + allocblk = allociblk; if (nb == 0) { - pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0); - error = ffs_alloc(ip, lbn, pref, - (int)fs->fs_bsize, cred, &newb); - if (error) + pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0); + if (error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, + cred, &newb)) return (error); nb = newb; + *allocblk++ = nb; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0); - bp->b_blkno = fsbtodb(fs, newb); + bp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(bp); /* * Write synchronously so that indirect blocks * never point at garbage. */ - error = bwrite(bp); - if (error) { - ffs_blkfree(ip, nb, fs->fs_bsize); - return (error); - } - ip->i_ib[indirs[0].in_off] = newb; + if (error = bwrite(bp)) + goto fail; + allocib = &ip->i_ib[indirs[0].in_off]; + *allocib = nb; ip->i_flag |= IN_CHANGE | IN_UPDATE; } /* @@ -202,9 +201,9 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp); if (error) { brelse(bp); - return (error); + goto fail; } - bap = (daddr_t *)bp->b_data; + bap = (ufs_daddr_t *)bp->b_data; nb = bap[indirs[i].in_off]; if (i == num) break; @@ -214,14 +213,14 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) continue; } if (pref == 0) - pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0); - error = - ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb); - if (error) { + pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0); + if (error = + ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) { brelse(bp); - return (error); + goto fail; } nb = newb; + *allocblk++ = nb; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(nbp); @@ -229,11 +228,9 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) * Write synchronously so that indirect blocks * never point at garbage. */ - error = bwrite(nbp); - if (error) { - ffs_blkfree(ip, nb, fs->fs_bsize); + if (error = bwrite(nbp)) { brelse(bp); - return (error); + goto fail; } bap[indirs[i - 1].in_off] = nb; /* @@ -255,9 +252,10 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) lbn, pref, (int)fs->fs_bsize, cred, &newb); if (error) { brelse(bp); - return (error); + goto fail; } nb = newb; + *allocblk++ = nb; nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); if (flags & B_CLRBUF) @@ -280,7 +278,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp); if (error) { brelse(nbp); - return (error); + goto fail; } } else { nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0); @@ -288,4 +286,26 @@ ffs_balloc(ip, bn, size, cred, bpp, flags) } *bpp = nbp; return (0); +fail: + /* + * If we have failed part way through block allocation, we + * have to deallocate any indirect blocks that we have allocated. + */ + for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { + ffs_blkfree(ip, *blkp, fs->fs_bsize); + deallocated += fs->fs_bsize; + } + if (allocib != NULL) + *allocib = 0; + if (deallocated) { +#ifdef QUOTA + /* + * Restore user's disk quota because allocation failed. + */ + (void) chkdq(ip, (long)-btodb(deallocated), cred, FORCE); +#endif + ip->i_blocks -= btodb(deallocated); + ip->i_flag |= IN_CHANGE | IN_UPDATE; + } + return (error); } diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index c0ef7c4..f168d01 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -30,13 +30,31 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94 + * @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95 * $FreeBSD$ */ #ifndef _UFS_FFS_EXTERN_H #define _UFS_FFS_EXTERN_H +/* + * Sysctl values for the fast filesystem. + */ +#define FFS_CLUSTERREAD 1 /* cluster reading enabled */ +#define FFS_CLUSTERWRITE 2 /* cluster writing enabled */ +#define FFS_REALLOCBLKS 3 /* block reallocation enabled */ +#define FFS_ASYNCFREE 4 /* asynchronous block freeing enabled */ +#define FFS_MAXID 5 /* number of valid ffs ids */ + +#define FFS_NAMES { \ + { 0, 0 }, \ + { "doclusterread", CTLTYPE_INT }, \ + { "doclusterwrite", CTLTYPE_INT }, \ + { "doreallocblks", CTLTYPE_INT }, \ + { "doasyncfree", CTLTYPE_INT }, \ +} + +struct buf; struct fid; struct fs; struct inode; @@ -44,29 +62,28 @@ struct mbuf; struct mount; struct statfs; struct vnode; +struct mbuf; int ffs_alloc __P((struct inode *, - daddr_t, daddr_t, int, struct ucred *, daddr_t *)); + ufs_daddr_t, ufs_daddr_t, int, struct ucred *, ufs_daddr_t *)); int ffs_balloc __P((struct inode *, - daddr_t, int, struct ucred *, struct buf **, int)); + ufs_daddr_t, int, struct ucred *, struct buf **, int)); int ffs_blkatoff __P((struct vop_blkatoff_args *)); -void ffs_blkfree __P((struct inode *, daddr_t, long)); -daddr_t ffs_blkpref __P((struct inode *, daddr_t, int, daddr_t *)); +void ffs_blkfree __P((struct inode *, ufs_daddr_t, long)); +ufs_daddr_t ffs_blkpref __P((struct inode *, ufs_daddr_t, int, ufs_daddr_t *)); int ffs_bmap __P((struct vop_bmap_args *)); -void ffs_clrblock __P((struct fs *, u_char *, daddr_t)); +void ffs_clrblock __P((struct fs *, u_char *, ufs_daddr_t)); int ffs_fhtovp __P((struct mount *, struct fid *, struct mbuf *, struct vnode **, int *, struct ucred **)); -int ffs_flushfiles __P((struct mount *, int, struct proc *)); -void ffs_fragacct __P((struct fs *, int, long [], int)); -int ffs_init __P((void)); -int ffs_isblock __P((struct fs *, u_char *, daddr_t)); +void ffs_fragacct __P((struct fs *, int, int32_t [], int)); +int ffs_isblock __P((struct fs *, u_char *, ufs_daddr_t)); int ffs_mountfs __P((struct vnode *, struct mount *, struct proc *)); int ffs_mountroot __P((void)); int ffs_reallocblks __P((struct vop_reallocblks_args *)); int ffs_realloccg __P((struct inode *, - daddr_t, daddr_t, int, int, struct ucred *, struct buf **)); + ufs_daddr_t, ufs_daddr_t, int, int, struct ucred *, struct buf **)); int ffs_reclaim __P((struct vop_reclaim_args *)); -void ffs_setblock __P((struct fs *, u_char *, daddr_t)); +void ffs_setblock __P((struct fs *, u_char *, ufs_daddr_t)); int ffs_statfs __P((struct mount *, struct statfs *, struct proc *)); int ffs_sync __P((struct mount *, int, struct ucred *, struct proc *)); int ffs_truncate __P((struct vop_truncate_args *)); diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index ba3e82a..f7af3f3 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ffs_inode.c 8.5 (Berkeley) 12/30/93 + * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95 * $FreeBSD$ */ @@ -59,14 +59,8 @@ #include #include -static int ffs_indirtrunc __P((struct inode *, daddr_t, daddr_t, daddr_t, int, - long *)); - -int -ffs_init() -{ - return (ufs_init()); -} +static int ffs_indirtrunc __P((struct inode *, ufs_daddr_t, ufs_daddr_t, + ufs_daddr_t, int, long *)); /* * Update the access, modified, and inode change times as specified by the @@ -115,15 +109,15 @@ ffs_update(ap) */ tv_sec = time.tv_sec; if (ip->i_flag & IN_ACCESS) - ip->i_atime.tv_sec = + ip->i_atime = (ap->a_access == &time ? tv_sec : ap->a_access->tv_sec); if (ip->i_flag & IN_UPDATE) { - ip->i_mtime.tv_sec = + ip->i_mtime = (ap->a_modify == &time ? tv_sec : ap->a_modify->tv_sec); ip->i_modrev++; } if (ip->i_flag & IN_CHANGE) - ip->i_ctime.tv_sec = tv_sec; + ip->i_ctime = tv_sec; ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE); fs = ip->i_fs; /* @@ -169,10 +163,10 @@ ffs_truncate(ap) } */ *ap; { register struct vnode *ovp = ap->a_vp; - register daddr_t lastblock; + ufs_daddr_t lastblock; register struct inode *oip; - daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR]; - daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; + ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR]; + ufs_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; off_t length = ap->a_length; register struct fs *fs; struct buf *bp; @@ -185,8 +179,10 @@ ffs_truncate(ap) oip = VTOI(ovp); fs = oip->i_fs; - if (length < 0 || length > fs->fs_maxfilesize) + if (length < 0) return (EINVAL); + if (length > fs->fs_maxfilesize) + return (EFBIG); tv = time; if (ovp->v_type == VLNK && (oip->i_size < ovp->v_mount->mnt_maxsymlinklen || oip->i_din.di_blocks == 0)) { @@ -220,12 +216,12 @@ ffs_truncate(ap) aflags = B_CLRBUF; if (ap->a_flags & IO_SYNC) aflags |= B_SYNC; - vnode_pager_setsize(ovp, length); error = ffs_balloc(oip, lbn, offset + 1, ap->a_cred, &bp, aflags); if (error) return (error); oip->i_size = length; + vnode_pager_setsize(ovp, length); if (aflags & B_SYNC) bwrite(bp); else if (ovp->v_mount->mnt_flag & MNT_ASYNC) @@ -264,6 +260,7 @@ ffs_truncate(ap) else bawrite(bp); } + vnode_pager_setsize(ovp, length); /* * Calculate index into inode's block list of * last direct and indirect blocks (if any) @@ -413,17 +410,17 @@ done: static int ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) register struct inode *ip; - daddr_t lbn, lastbn; - daddr_t dbn; + ufs_daddr_t lbn, lastbn; + ufs_daddr_t dbn; int level; long *countp; { register int i; struct buf *bp; register struct fs *fs = ip->i_fs; - register daddr_t *bap; + register ufs_daddr_t *bap; struct vnode *vp; - daddr_t *copy = NULL, nb, nlbn, last; + ufs_daddr_t *copy = NULL, nb, nlbn, last; long blkcount, factor; int nblocks, blocksreleased = 0; int error = 0, allerror = 0; @@ -466,12 +463,12 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) return (error); } - bap = (daddr_t *)bp->b_data; + bap = (ufs_daddr_t *)bp->b_data; if (lastbn != -1) { - MALLOC(copy, daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK); + MALLOC(copy, ufs_daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK); bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize); bzero((caddr_t)&bap[last + 1], - (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t)); + (u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t)); if ((vp->v_mount->mnt_flag & MNT_ASYNC) == 0) { error = bwrite(bp); if (error) @@ -491,9 +488,8 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp) if (nb == 0) continue; if (level > SINGLE) { - error = ffs_indirtrunc(ip, nlbn, - fsbtodb(fs, nb), (daddr_t)-1, level - 1, &blkcount); - if (error) + if (error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb), + (ufs_daddr_t)-1, level - 1, &blkcount)) allerror = error; blocksreleased += blkcount; } diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c index 1cb9f3f..629a228 100644 --- a/sys/ufs/ffs/ffs_subr.c +++ b/sys/ufs/ffs/ffs_subr.c @@ -30,22 +30,26 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 + * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 * $FreeBSD$ */ #include -#include -#ifdef KERNEL +#ifndef KERNEL +#include +#include +#else #include "opt_ddb.h" #include #include -#include #include #include #include +#include +#include +#include /* * Return buffer with the contents of block "offset" from the beginning of @@ -64,7 +68,7 @@ ffs_blkatoff(ap) struct inode *ip; register struct fs *fs; struct buf *bp; - daddr_t lbn; + ufs_daddr_t lbn; int bsize, error; ip = VTOI(ap->a_vp); @@ -93,7 +97,7 @@ void ffs_fragacct(fs, fragmap, fraglist, cnt) struct fs *fs; int fragmap; - long fraglist[]; + int32_t fraglist[]; int cnt; { int inblk; @@ -127,7 +131,7 @@ ffs_checkoverlap(bp, ip) struct inode *ip; { register struct buf *ebp, *ep; - register daddr_t start, last; + register ufs_daddr_t start, last; struct vnode *vp; ebp = &buf[nbuf]; @@ -137,7 +141,8 @@ ffs_checkoverlap(bp, ip) if (ep == bp || (ep->b_flags & B_INVAL) || ep->b_vp == NULLVP) continue; - if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL, NULL)) + if (VOP_BMAP(ep->b_vp, (ufs_daddr_t)0, &vp, (ufs_daddr_t)0, + NULL)) continue; if (vp != ip->i_devvp) continue; @@ -163,7 +168,7 @@ int ffs_isblock(fs, cp, h) struct fs *fs; unsigned char *cp; - daddr_t h; + ufs_daddr_t h; { unsigned char mask; @@ -191,7 +196,7 @@ void ffs_clrblock(fs, cp, h) struct fs *fs; u_char *cp; - daddr_t h; + ufs_daddr_t h; { switch ((int)fs->fs_frag) { @@ -219,7 +224,7 @@ void ffs_setblock(fs, cp, h) struct fs *fs; unsigned char *cp; - daddr_t h; + ufs_daddr_t h; { switch ((int)fs->fs_frag) { diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 4b86cb0..c8b8959 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94 + * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 * $FreeBSD$ */ @@ -72,8 +72,9 @@ static int ffs_sbupdate __P((struct ufsmount *, int)); static int ffs_reload __P((struct mount *,struct ucred *,struct proc *)); static int ffs_oldfscompat __P((struct fs *)); -static int ffs_mount __P((struct mount *, - char *, caddr_t, struct nameidata *, struct proc *)); +static int ffs_mount __P((struct mount *, char *, caddr_t, + struct nameidata *, struct proc *)); +static int ffs_init __P((struct vfsconf *)); struct vfsops ufs_vfsops = { ffs_mount, @@ -93,7 +94,6 @@ VFS_SET(ufs_vfsops, ufs, MOUNT_UFS, 0); extern u_long nextgennumber; - /* * ffs_mount * @@ -133,7 +133,7 @@ extern u_long nextgennumber; */ static int ffs_mount( mp, path, data, ndp, p) - register struct mount *mp; /* mount struct pointer*/ + struct mount *mp; /* mount struct pointer*/ char *path; /* path to mount point*/ caddr_t data; /* arguments to FS specific mount*/ struct nameidata *ndp; /* mount point credentials*/ @@ -159,13 +159,10 @@ ffs_mount( mp, path, data, ndp, p) */ /* Get vnode for root device*/ - if( bdevvp( rootdev, &rootvp)) - panic("ffs_mountroot: can't setup bdevvp for root"); - - /* - * FS specific handling - */ - mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/ + if ((err = bdevvp( rootdev, &rootvp))) { + printf("ffs_mountroot: can't setup bdevvp for root"); + return (err); + } /* * Attempt mount @@ -202,12 +199,7 @@ ffs_mount( mp, path, data, ndp, p) flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; - if (vfs_busy(mp)) { - err = EBUSY; - goto error_1; - } err = ffs_flushfiles(mp, flags, p); - vfs_unbusy(mp); } if (!err && (mp->mnt_flag & MNT_RELOAD)) err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); @@ -341,7 +333,6 @@ success: return( err); } - /* * Reload all incore data for a filesystem (used after running fsck on * the root filesystem and finding things to fix). The filesystem must @@ -365,8 +356,10 @@ ffs_reload(mp, cred, p) struct inode *ip; struct csum *space; struct buf *bp; - struct fs *fs; + struct fs *fs, *newfs; + struct partinfo dpart; int i, blks, size, error; + int32_t *lp; if ((mp->mnt_flag & MNT_RDONLY) == 0) return (EINVAL); @@ -379,24 +372,33 @@ ffs_reload(mp, cred, p) /* * Step 2: re-read superblock from disk. */ - error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp); - if (error) + if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) + size = DEV_BSIZE; + else + size = dpart.disklab->d_secsize; + if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) return (error); - fs = (struct fs *)bp->b_data; - fs->fs_fmod = 0; - if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || - fs->fs_bsize < sizeof(struct fs)) { - brelse(bp); - return (EIO); /* XXX needs translation */ + newfs = (struct fs *)bp->b_data; + if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE || + newfs->fs_bsize < sizeof(struct fs)) { + brelse(bp); + return (EIO); /* XXX needs translation */ } fs = VFSTOUFS(mp)->um_fs; - bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0], - sizeof(fs->fs_csp)); - bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize); + /* + * Copy pointer fields back into superblock before copying in XXX + * new superblock. These should really be in the ufsmount. XXX + * Note that important parameters (eg fs_ncg) are unchanged. + */ + bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp)); + newfs->fs_maxcluster = fs->fs_maxcluster; + bcopy(newfs, fs, (u_int)fs->fs_sbsize); if (fs->fs_sbsize < SBSIZE) bp->b_flags |= B_INVAL; brelse(bp); + mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; ffs_oldfscompat(fs); + /* * Step 3: re-read summary information from disk. */ @@ -413,21 +415,36 @@ ffs_reload(mp, cred, p) bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); brelse(bp); } + /* + * We no longer know anything about clusters per cylinder group. + */ + if (fs->fs_contigsumsize > 0) { + lp = fs->fs_maxcluster; + for (i = 0; i < fs->fs_ncg; i++) + *lp++ = fs->fs_contigsumsize; + } + loop: + simple_lock(&mntvnode_slock); for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { + if (vp->v_mount != mp) { + simple_unlock(&mntvnode_slock); + goto loop; + } nvp = vp->v_mntvnodes.le_next; /* * Step 4: invalidate all inactive vnodes. */ - if (vp->v_usecount == 0) { - vgone(vp); - continue; - } + if (vrecycle(vp, &mntvnode_slock, p)) + goto loop; /* * Step 5: invalidate all cached file data. */ - if (vget(vp, 1)) + simple_lock(&vp->v_interlock); + simple_unlock(&mntvnode_slock); + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { goto loop; + } if (vinvalbuf(vp, 0, cred, p, 0, 0)) panic("ffs_reload: dirty2"); /* @@ -445,9 +462,9 @@ loop: ino_to_fsbo(fs, ip->i_number)); brelse(bp); vput(vp); - if (vp->v_mount != mp) - goto loop; + simple_lock(&mntvnode_slock); } + simple_unlock(&mntvnode_slock); return (0); } @@ -463,15 +480,18 @@ ffs_mountfs(devvp, mp, p) register struct ufsmount *ump; struct buf *bp; register struct fs *fs; - dev_t dev = devvp->v_rdev; + dev_t dev; struct partinfo dpart; caddr_t base, space; - int havepart = 0, blks; - int error, i, size; - int ronly; + int error, i, blks, size, ronly; + int32_t *lp; + struct ucred *cred; + u_int64_t maxfilesize; /* XXX */ u_int strsize; int ncount; + dev = devvp->v_rdev; + cred = p ? p->p_ucred : NOCRED; /* * Disallow multiple mounts of the same device. * Disallow mounting of a device that is currently in use @@ -486,25 +506,21 @@ ffs_mountfs(devvp, mp, p) ncount -= 1; if (ncount > 1 && devvp != rootvp) return (EBUSY); - error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0); - if (error) + if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) return (error); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); if (error) return (error); - if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) + if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) size = DEV_BSIZE; - else { - havepart = 1; + else size = dpart.disklab->d_secsize; - } bp = NULL; ump = NULL; - error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp); - if (error) + if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp)) goto out; fs = (struct fs *)bp->b_data; if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || @@ -522,6 +538,11 @@ ffs_mountfs(devvp, mp, p) goto out; } } + /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ + if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { + error = EROFS; /* needs translation */ + goto out; + } ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); bzero((caddr_t)ump, sizeof *ump); ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, @@ -537,16 +558,17 @@ ffs_mountfs(devvp, mp, p) fs->fs_fmod = 1; fs->fs_clean = 0; } - blks = howmany(fs->fs_cssize, fs->fs_fsize); - base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT, - M_WAITOK); + size = fs->fs_cssize; + blks = howmany(size, fs->fs_fsize); + if (fs->fs_contigsumsize > 0) + size += fs->fs_ncg * sizeof(int32_t); + base = space = malloc((u_long)size, M_UFSMNT, 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; - error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, - NOCRED, &bp); - if (error) { + if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, + cred, &bp)) { free(base, M_UFSMNT); goto out; } @@ -556,11 +578,15 @@ ffs_mountfs(devvp, mp, p) brelse(bp); bp = NULL; } + if (fs->fs_contigsumsize > 0) { + fs->fs_maxcluster = lp = (int32_t *)space; + for (i = 0; i < fs->fs_ncg; i++) + *lp++ = fs->fs_contigsumsize; + } mp->mnt_data = (qaddr_t)ump; mp->mnt_stat.f_fsid.val[0] = (long)dev; - mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; + mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; - mp->mnt_flag |= MNT_LOCAL; ump->um_mountp = mp; ump->um_dev = dev; ump->um_devvp = devvp; @@ -589,8 +615,15 @@ ffs_mountfs(devvp, mp, p) */ mp->mnt_time = fs->fs_time; } - if (ronly == 0) - ffs_sbupdate(ump, MNT_WAIT); + + ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ + maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */ + if (fs->fs_maxfilesize > maxfilesize) /* XXX */ + fs->fs_maxfilesize = maxfilesize; /* XXX */ + if (ronly == 0) { + fs->fs_clean = 0; + (void) ffs_sbupdate(ump, MNT_WAIT); + } /* * Only VMIO the backing device if the backing device is a real * block device. This excludes the original MFS implementation. @@ -604,7 +637,7 @@ ffs_mountfs(devvp, mp, p) out: if (bp) brelse(bp); - (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); + (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); if (ump) { free(ump->um_fs, M_UFSMNT); free(ump, M_UFSMNT); @@ -630,7 +663,8 @@ ffs_oldfscompat(fs) if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ #if 0 int i; /* XXX */ - quad_t sizepb = fs->fs_bsize; /* XXX */ + u_int64_t sizepb = fs->fs_bsize; /* XXX */ + /* XXX */ fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ for (i = 0; i < NIADDR; i++) { /* XXX */ sizepb *= NINDIR(fs); /* XXX */ @@ -655,7 +689,7 @@ ffs_unmount(mp, mntflags, p) { register struct ufsmount *ump; register struct fs *fs; - int error, flags, ronly; + int error, flags; flags = 0; if (mntflags & MNT_FORCE) { @@ -666,18 +700,21 @@ ffs_unmount(mp, mntflags, p) return (error); ump = VFSTOUFS(mp); fs = ump->um_fs; - ronly = fs->fs_ronly; - if (!ronly) { + if (fs->fs_ronly == 0) { fs->fs_clean = 1; - ffs_sbupdate(ump, MNT_WAIT); + error = ffs_sbupdate(ump, MNT_WAIT); + if (error) { + fs->fs_clean = 0; + return (error); + } } ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; - VOP_LOCK(ump->um_devvp); - vnode_pager_uncache(ump->um_devvp); - VOP_UNLOCK(ump->um_devvp); + vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p); + vnode_pager_uncache(ump->um_devvp, p); + VOP_UNLOCK(ump->um_devvp, 0, p); - error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, + error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, NOCRED, p); vrele(ump->um_devvp); @@ -686,7 +723,6 @@ ffs_unmount(mp, mntflags, p) free(fs, M_UFSMNT); free(ump, M_UFSMNT); mp->mnt_data = (qaddr_t)0; - mp->mnt_flag &= ~MNT_LOCAL; return (error); } @@ -702,8 +738,6 @@ ffs_flushfiles(mp, flags, p) register struct ufsmount *ump; int error; - if (!doforce) - flags &= ~FORCECLOSE; ump = VFSTOUFS(mp); #ifdef QUOTA if (mp->mnt_flag & MNT_QUOTA) { @@ -742,7 +776,6 @@ ffs_statfs(mp, sbp, p) fs = ump->um_fs; if (fs->fs_magic != FS_MAGIC) panic("ffs_statfs"); - sbp->f_type = MOUNT_UFS; sbp->f_bsize = fs->fs_fsize; sbp->f_iosize = fs->fs_bsize; sbp->f_blocks = fs->fs_dsize; @@ -752,6 +785,7 @@ ffs_statfs(mp, sbp, p) sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; sbp->f_ffree = fs->fs_cstotal.cs_nifree; if (sbp != &mp->mnt_stat) { + sbp->f_type = mp->mnt_vfc->vfc_typenum; bcopy((caddr_t)mp->mnt_stat.f_mntonname, (caddr_t)&sbp->f_mntonname[0], MNAMELEN); bcopy((caddr_t)mp->mnt_stat.f_mntfromname, @@ -774,31 +808,22 @@ ffs_sync(mp, waitfor, cred, p) struct ucred *cred; struct proc *p; { - register struct vnode *vp, *nvp; - register struct inode *ip; - register struct ufsmount *ump = VFSTOUFS(mp); - register struct fs *fs; + struct vnode *nvp, *vp; + struct inode *ip; + struct ufsmount *ump = VFSTOUFS(mp); + struct fs *fs; struct timeval tv; int error, allerror = 0; fs = ump->um_fs; - /* - * 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; - allerror = ffs_sbupdate(ump, waitfor); + if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */ + printf("fs = %s\n", fs->fs_fsmnt); + panic("update: rofs mod"); } /* * Write back each (modified) inode. */ + simple_lock(&mntvnode_slock); loop: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { /* @@ -807,27 +832,40 @@ loop: */ if (vp->v_mount != mp) goto loop; + simple_lock(&vp->v_interlock); nvp = vp->v_mntvnodes.le_next; - if (VOP_ISLOCKED(vp)) - continue; ip = VTOI(vp); - if ((((ip->i_flag & - (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)) && - vp->v_dirtyblkhd.lh_first == NULL) + if (((ip->i_flag & + (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) && + vp->v_dirtyblkhd.lh_first == NULL) { + simple_unlock(&vp->v_interlock); continue; + } if (vp->v_type != VCHR) { - if (vget(vp, 1)) - goto loop; - error = VOP_FSYNC(vp, cred, waitfor, p); - if (error) + simple_unlock(&mntvnode_slock); + error = + vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); + if (error) { + simple_lock(&mntvnode_slock); + if (error == ENOENT) + goto loop; + continue; + } + if (error = VOP_FSYNC(vp, cred, waitfor, p)) allerror = error; - vput(vp); + VOP_UNLOCK(vp, 0, p); + vrele(vp); + simple_lock(&mntvnode_slock); } else { + simple_unlock(&mntvnode_slock); + simple_unlock(&vp->v_interlock); tv = time; /* VOP_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT); */ VOP_UPDATE(vp, &tv, &tv, 0); + simple_lock(&mntvnode_slock); } } + simple_unlock(&mntvnode_slock); /* * Force stale file system control information to be flushed. */ @@ -837,6 +875,15 @@ loop: #ifdef QUOTA qsync(mp); #endif + /* + * Write back modified superblock. + */ + if (fs->fs_fmod != 0) { + fs->fs_fmod = 0; + fs->fs_time = time.tv_sec; + if (error = ffs_sbupdate(ump, waitfor)) + allerror = error; + } return (allerror); } @@ -854,8 +901,8 @@ ffs_vget(mp, ino, vpp) ino_t ino; struct vnode **vpp; { - register struct fs *fs; - register struct inode *ip; + struct fs *fs; + struct inode *ip; struct ufsmount *ump; struct buf *bp; struct vnode *vp; @@ -903,6 +950,7 @@ restart: return (error); } bzero((caddr_t)ip, sizeof(struct inode)); + lockinit(&ip->i_lock, PINOD, "inode", 0, 0); vp->v_data = ip; ip->i_vnode = vp; ip->i_fs = fs = ump->um_fs; @@ -1035,6 +1083,17 @@ ffs_vptofh(vp, fhp) } /* + * Initialize the filesystem; just use ufs_init. + */ +static int +ffs_init(vfsp) + struct vfsconf *vfsp; +{ + + return (ufs_init(vfsp)); +} + +/* * Write a superblock and associated information back to disk. */ static int @@ -1042,21 +1101,15 @@ ffs_sbupdate(mp, waitfor) struct ufsmount *mp; int waitfor; { - register struct fs *fs = mp->um_fs; + register struct fs *dfs, *fs = mp->um_fs; register struct buf *bp; int blks; caddr_t space; - int i, size, error = 0; + int i, size, error, allerror = 0; - bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0); - bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); - /* Restore compatibility to old file systems. XXX */ - if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ - ((struct fs *)bp->b_data)->fs_nrpos = -1; /* XXX */ - if (waitfor == MNT_WAIT) - error = bwrite(bp); - else - bawrite(bp); + /* + * First write back the summary information. + */ blks = howmany(fs->fs_cssize, fs->fs_fsize); space = (caddr_t)fs->fs_csp[0]; for (i = 0; i < blks; i += fs->fs_frag) { @@ -1067,10 +1120,37 @@ ffs_sbupdate(mp, waitfor) size, 0, 0); bcopy(space, bp->b_data, (u_int)size); space += size; - if (waitfor == MNT_WAIT) - error = bwrite(bp); - else + if (waitfor != MNT_WAIT) bawrite(bp); + else if (error = bwrite(bp)) + allerror = error; } - return (error); + /* + * Now write back the superblock itself. If any errors occurred + * up to this point, then fail so that the superblock avoids + * being written out as clean. + */ + if (allerror) + return (allerror); + bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0); + bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); + /* Restore compatibility to old file systems. XXX */ + dfs = (struct fs *)bp->b_data; /* XXX */ + if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ + dfs->fs_nrpos = -1; /* XXX */ + if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ + int32_t *lp, tmp; /* XXX */ + /* XXX */ + lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ + tmp = lp[4]; /* XXX */ + for (i = 4; i > 0; i--) /* XXX */ + lp[i] = lp[i-1]; /* XXX */ + lp[0] = tmp; /* XXX */ + } /* XXX */ + dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ + if (waitfor != MNT_WAIT) + bawrite(bp); + else if (error = bwrite(bp)) + allerror = error; + return (allerror); } diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index c3f750b..ddce646 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ffs_vnops.c 8.7 (Berkeley) 2/3/94 + * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95 * $FreeBSD$ */ @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -78,6 +79,7 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { { &vop_default_desc, (vop_t *)vn_default_error }, { &vop_lookup_desc, (vop_t *)ufs_lookup }, /* lookup */ { &vop_create_desc, (vop_t *)ufs_create }, /* create */ + { &vop_whiteout_desc, (vop_t *)ufs_whiteout }, /* whiteout */ { &vop_mknod_desc, (vop_t *)ufs_mknod }, /* mknod */ { &vop_open_desc, (vop_t *)ufs_open }, /* open */ { &vop_close_desc, (vop_t *)ufs_close }, /* close */ @@ -86,8 +88,10 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { { &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */ { &vop_read_desc, (vop_t *)ffs_read }, /* read */ { &vop_write_desc, (vop_t *)ffs_write }, /* write */ + { &vop_lease_desc, (vop_t *)ufs_lease_check }, /* lease */ { &vop_ioctl_desc, (vop_t *)ufs_ioctl }, /* ioctl */ { &vop_select_desc, (vop_t *)ufs_select }, /* select */ + { &vop_revoke_desc, (vop_t *)ufs_revoke }, /* revoke */ { &vop_mmap_desc, (vop_t *)ufs_mmap }, /* mmap */ { &vop_fsync_desc, (vop_t *)ffs_fsync }, /* fsync */ { &vop_seek_desc, (vop_t *)ufs_seek }, /* seek */ @@ -101,7 +105,7 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { { &vop_readlink_desc, (vop_t *)ufs_readlink }, /* readlink */ { &vop_abortop_desc, (vop_t *)ufs_abortop }, /* abortop */ { &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */ - { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */ + { &vop_reclaim_desc, (vop_t *)ffs_reclaim }, /* reclaim */ { &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */ { &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */ { &vop_bmap_desc, (vop_t *)ufs_bmap }, /* bmap */ @@ -136,8 +140,10 @@ static struct vnodeopv_entry_desc ffs_specop_entries[] = { { &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */ { &vop_read_desc, (vop_t *)ufsspec_read }, /* read */ { &vop_write_desc, (vop_t *)ufsspec_write }, /* write */ + { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */ { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */ { &vop_select_desc, (vop_t *)spec_select }, /* select */ + { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */ { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */ { &vop_fsync_desc, (vop_t *)ffs_fsync }, /* fsync */ { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */ @@ -151,7 +157,7 @@ static struct vnodeopv_entry_desc ffs_specop_entries[] = { { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */ { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */ { &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */ - { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */ + { &vop_reclaim_desc, (vop_t *)ffs_reclaim }, /* reclaim */ { &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */ { &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */ { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */ @@ -186,8 +192,10 @@ static struct vnodeopv_entry_desc ffs_fifoop_entries[] = { { &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */ { &vop_read_desc, (vop_t *)ufsfifo_read }, /* read */ { &vop_write_desc, (vop_t *)ufsfifo_write }, /* write */ + { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */ { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */ { &vop_select_desc, (vop_t *)fifo_select }, /* select */ + { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */ { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */ { &vop_fsync_desc, (vop_t *)ffs_fsync }, /* fsync */ { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */ @@ -201,7 +209,7 @@ static struct vnodeopv_entry_desc ffs_fifoop_entries[] = { { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */ { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */ { &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */ - { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */ + { &vop_reclaim_desc, (vop_t *)ffs_reclaim }, /* reclaim */ { &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */ { &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */ { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */ @@ -226,20 +234,16 @@ VNODEOP_SET(ffs_vnodeop_opv_desc); VNODEOP_SET(ffs_specop_opv_desc); VNODEOP_SET(ffs_fifoop_opv_desc); -#ifdef DEBUG /* * Enabling cluster read/write operations. */ -#include int doclusterread = 1; -SYSCTL_INT(_debug, 11, doclusterread, CTLFLAG_RW, &doclusterread, 0, ""); int doclusterwrite = 1; -SYSCTL_INT(_debug, 12, doclusterwrite, CTLFLAG_RW, &doclusterwrite, 0, ""); -#else -/* XXX for ufs_readwrite */ -#define doclusterread 1 -#define doclusterwrite 1 -#endif + +#include +SYSCTL_NODE(_vfs_ffs, MOUNT_UFS, ffs, CTLFLAG_RW, 0, "FFS"); +SYSCTL_INT(_vfs_ffs, FFS_CLUSTERREAD, doclusterread, CTLFLAG_RW, &doclusterread, 0, ""); +SYSCTL_INT(_vfs_ffs, FFS_CLUSTERWRITE, doclusterwrite, CTLFLAG_RW, &doclusterwrite, 0, ""); #include @@ -320,3 +324,24 @@ loop: tv = time; return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT)); } + +/* + * Reclaim an inode so that it can be used for other purposes. + */ +int +ffs_reclaim(ap) + struct vop_reclaim_args /* { + struct vnode *a_vp; + struct proc *a_p; + } */ *ap; +{ + register struct vnode *vp = ap->a_vp; + int error; + + if (error = ufs_reclaim(vp, ap->a_p)) + return (error); + FREE(vp->v_data, VFSTOUFS(vp->v_mount)->um_devvp->v_tag == VT_MFS ? + M_MFSNODE : M_FFSNODE); + vp->v_data = NULL; + return (0); +} diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h index 16862c4..02720da 100644 --- a/sys/ufs/ffs/fs.h +++ b/sys/ufs/ffs/fs.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)fs.h 8.7 (Berkeley) 4/19/94 + * @(#)fs.h 8.13 (Berkeley) 3/21/95 * $FreeBSD$ */ @@ -65,8 +65,8 @@ #define SBSIZE 8192 #define BBOFF ((off_t)(0)) #define SBOFF ((off_t)(BBOFF + BBSIZE)) -#define BBLOCK ((daddr_t)(0)) -#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) +#define BBLOCK ((ufs_daddr_t)(0)) +#define SBLOCK ((ufs_daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) /* * Addresses stored in inodes are capable of addressing fragments @@ -102,12 +102,18 @@ * The path name on which the file system is mounted is maintained * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * the super block for this name. + */ +#define MAXMNTLEN 512 + +/* * The limit on the amount of summary information per file system * is defined by MAXCSBUFS. It is currently parameterized for a - * maximum of two million cylinders. + * size of 128 bytes (2 million cylinder groups on machines with + * 32-bit pointers, and 1 million on 64-bit machines). One pointer + * is taken away to point to an array of cluster sizes that is + * computed as cylinder groups are inspected. */ -#define MAXMNTLEN 512 -#define MAXCSBUFS 32 +#define MAXCSBUFS ((128 / sizeof(void *)) - 1) /* * A summary of contiguous blocks of various sizes is maintained @@ -142,103 +148,105 @@ * the ``fs_cs'' macro to work (see below). */ struct csum { - long cs_ndir; /* number of directories */ - long cs_nbfree; /* number of free blocks */ - long cs_nifree; /* number of free inodes */ - long cs_nffree; /* number of free frags */ + int32_t cs_ndir; /* number of directories */ + int32_t cs_nbfree; /* number of free blocks */ + int32_t cs_nifree; /* number of free inodes */ + int32_t cs_nffree; /* number of free frags */ }; /* - * Super block for a file system. + * Super block for an FFS file system. */ struct fs { - struct fs *fs_link; /* linked list of file systems */ - struct fs *fs_rlink; /* used for incore super blocks */ - daddr_t fs_sblkno; /* addr of super-block in filesys */ - daddr_t fs_cblkno; /* offset of cyl-block in filesys */ - daddr_t fs_iblkno; /* offset of inode-blocks in filesys */ - daddr_t fs_dblkno; /* offset of first data after cg */ - long fs_cgoffset; /* cylinder group offset in cylinder */ - long fs_cgmask; /* used to calc mod fs_ntrak */ - time_t fs_time; /* last time written */ - long fs_size; /* number of blocks in fs */ - long fs_dsize; /* number of data blocks in fs */ - long fs_ncg; /* number of cylinder groups */ - long fs_bsize; /* size of basic blocks in fs */ - long fs_fsize; /* size of frag blocks in fs */ - long fs_frag; /* number of frags in a block in fs */ + int32_t fs_firstfield; /* historic file system linked list, */ + int32_t fs_unused_1; /* used for incore super blocks */ + ufs_daddr_t fs_sblkno; /* addr of super-block in filesys */ + ufs_daddr_t fs_cblkno; /* offset of cyl-block in filesys */ + ufs_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */ + ufs_daddr_t fs_dblkno; /* offset of first data after cg */ + int32_t fs_cgoffset; /* cylinder group offset in cylinder */ + int32_t fs_cgmask; /* used to calc mod fs_ntrak */ + time_t fs_time; /* last time written */ + int32_t fs_size; /* number of blocks in fs */ + int32_t fs_dsize; /* number of data blocks in fs */ + int32_t fs_ncg; /* number of cylinder groups */ + int32_t fs_bsize; /* size of basic blocks in fs */ + int32_t fs_fsize; /* size of frag blocks in fs */ + int32_t fs_frag; /* number of frags in a block in fs */ /* these are configuration parameters */ - long fs_minfree; /* minimum percentage of free blocks */ - long fs_rotdelay; /* num of ms for optimal next block */ - long fs_rps; /* disk revolutions per second */ + int32_t fs_minfree; /* minimum percentage of free blocks */ + int32_t fs_rotdelay; /* num of ms for optimal next block */ + int32_t fs_rps; /* disk revolutions per second */ /* these fields can be computed from the others */ - long fs_bmask; /* ``blkoff'' calc of blk offsets */ - long fs_fmask; /* ``fragoff'' calc of frag offsets */ - long fs_bshift; /* ``lblkno'' calc of logical blkno */ - long fs_fshift; /* ``numfrags'' calc number of frags */ + int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ + int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ + int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ + int32_t fs_fshift; /* ``numfrags'' calc number of frags */ /* these are configuration parameters */ - long fs_maxcontig; /* max number of contiguous blks */ - long fs_maxbpg; /* max number of blks per cyl group */ + int32_t fs_maxcontig; /* max number of contiguous blks */ + int32_t fs_maxbpg; /* max number of blks per cyl group */ /* these fields can be computed from the others */ - long fs_fragshift; /* block to frag shift */ - long fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ - long fs_sbsize; /* actual size of super block */ - long fs_csmask; /* csum block offset */ - long fs_csshift; /* csum block number */ - long fs_nindir; /* value of NINDIR */ - long fs_inopb; /* value of INOPB */ - long fs_nspf; /* value of NSPF */ + int32_t fs_fragshift; /* block to frag shift */ + int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + int32_t fs_sbsize; /* actual size of super block */ + int32_t fs_csmask; /* csum block offset */ + int32_t fs_csshift; /* csum block number */ + int32_t fs_nindir; /* value of NINDIR */ + int32_t fs_inopb; /* value of INOPB */ + int32_t fs_nspf; /* value of NSPF */ /* yet another configuration parameter */ - long fs_optim; /* optimization preference, see below */ + int32_t fs_optim; /* optimization preference, see below */ /* these fields are derived from the hardware */ - long fs_npsect; /* # sectors/track including spares */ - long fs_interleave; /* hardware sector interleave */ - long fs_trackskew; /* sector 0 skew, per track */ - long fs_headswitch; /* head switch time, usec */ - long fs_trkseek; /* track-to-track seek, usec */ + int32_t fs_npsect; /* # sectors/track including spares */ + int32_t fs_interleave; /* hardware sector interleave */ + int32_t fs_trackskew; /* sector 0 skew, per track */ + int32_t fs_headswitch; /* head switch time, usec */ + int32_t fs_trkseek; /* track-to-track seek, usec */ /* sizes determined by number of cylinder groups and their sizes */ - daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ - long fs_cssize; /* size of cyl grp summary area */ - long fs_cgsize; /* cylinder group size */ + ufs_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ + int32_t fs_cssize; /* size of cyl grp summary area */ + int32_t fs_cgsize; /* cylinder group size */ /* these fields are derived from the hardware */ - long fs_ntrak; /* tracks per cylinder */ - long fs_nsect; /* sectors per track */ - long fs_spc; /* sectors per cylinder */ + int32_t fs_ntrak; /* tracks per cylinder */ + int32_t fs_nsect; /* sectors per track */ + int32_t fs_spc; /* sectors per cylinder */ /* this comes from the disk driver partitioning */ - long fs_ncyl; /* cylinders in file system */ + int32_t fs_ncyl; /* cylinders in file system */ /* these fields can be computed from the others */ - long fs_cpg; /* cylinders per group */ - long fs_ipg; /* inodes per group */ - long fs_fpg; /* blocks per group * fs_frag */ + int32_t fs_cpg; /* cylinders per group */ + int32_t fs_ipg; /* inodes per group */ + int32_t fs_fpg; /* blocks per group * fs_frag */ /* this data must be re-computed after crashes */ struct csum fs_cstotal; /* cylinder summary information */ /* these fields are cleared at mount time */ - char fs_fmod; /* super block modified flag */ - char fs_clean; /* file system is clean flag */ - char fs_ronly; /* mounted read-only flag */ - char fs_flags; /* currently unused flag */ - char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ + int8_t fs_fmod; /* super block modified flag */ + int8_t fs_clean; /* file system is clean flag */ + int8_t fs_ronly; /* mounted read-only flag */ + int8_t fs_flags; /* currently unused flag */ + u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ /* these fields retain the current block allocation info */ - long fs_cgrotor; /* last cg searched */ + int32_t fs_cgrotor; /* last cg searched */ struct csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */ - long fs_cpc; /* cyl per cycle in postbl */ - short fs_opostbl[16][8]; /* old rotation block list head */ - long fs_sparecon[50]; /* reserved for future constants */ - long fs_contigsumsize; /* size of cluster summary array */ - long fs_maxsymlinklen; /* max length of an internal symlink */ - long fs_inodefmt; /* format of on-disk inodes */ - u_quad_t fs_maxfilesize; /* maximum representable file size */ - quad_t fs_qbmask; /* ~fs_bmask - for use with quad size */ - quad_t fs_qfmask; /* ~fs_fmask - for use with quad size */ - long fs_state; /* validate fs_clean field */ - long fs_postblformat; /* format of positional layout tables */ - long fs_nrpos; /* number of rotational positions */ - long fs_postbloff; /* (short) rotation block list head */ - long fs_rotbloff; /* (u_char) blocks for each rotation */ - long fs_magic; /* magic number */ - u_char fs_space[1]; /* list of blocks for each rotation */ + int32_t *fs_maxcluster; /* max cluster in each cyl group */ + int32_t fs_cpc; /* cyl per cycle in postbl */ + int16_t fs_opostbl[16][8]; /* old rotation block list head */ + int32_t fs_sparecon[50]; /* reserved for future constants */ + int32_t fs_contigsumsize; /* size of cluster summary array */ + int32_t fs_maxsymlinklen; /* max length of an internal symlink */ + int32_t fs_inodefmt; /* format of on-disk inodes */ + u_int64_t fs_maxfilesize; /* maximum representable file size */ + int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */ + int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */ + int32_t fs_state; /* validate fs_clean field */ + int32_t fs_postblformat; /* format of positional layout tables */ + int32_t fs_nrpos; /* number of rotational positions */ + int32_t fs_postbloff; /* (u_int16) rotation block list head */ + int32_t fs_rotbloff; /* (u_int8) blocks for each rotation */ + int32_t fs_magic; /* magic number */ + u_int8_t fs_space[1]; /* list of blocks for each rotation */ /* actually longer */ }; + /* * Filesystem identification */ @@ -263,11 +271,12 @@ struct fs { #define fs_postbl(fs, cylno) \ (((fs)->fs_postblformat == FS_42POSTBLFMT) \ ? ((fs)->fs_opostbl[cylno]) \ - : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos)) + : ((int16_t *)((u_int8_t *)(fs) + \ + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos)) #define fs_rotbl(fs) \ (((fs)->fs_postblformat == FS_42POSTBLFMT) \ ? ((fs)->fs_space) \ - : ((u_char *)((char *)(fs) + (fs)->fs_rotbloff))) + : ((u_int8_t *)((u_int8_t *)(fs) + (fs)->fs_rotbloff))) /* * The size of a cylinder group is calculated by CGSIZE. The maximum size @@ -276,13 +285,13 @@ struct fs { * cylinder group and the (struct cg) size. */ #define CGSIZE(fs) \ - /* base cg */ (sizeof(struct cg) + sizeof(long) + \ - /* blktot size */ (fs)->fs_cpg * sizeof(long) + \ - /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \ + /* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \ + /* blktot size */ (fs)->fs_cpg * sizeof(int32_t) + \ + /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(int16_t) + \ /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\ /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \ - /* cluster sum */ (fs)->fs_contigsumsize * sizeof(long) + \ + /* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \ /* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY))) /* @@ -297,79 +306,81 @@ struct fs { * Cylinder group block for a file system. */ #define CG_MAGIC 0x090255 -struct cg { - struct cg *cg_link; /* linked list of cyl groups */ - long cg_magic; /* magic number */ - time_t cg_time; /* time last written */ - long cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - long cg_ndblk; /* number of data blocks this cg */ +struct cg { + int32_t cg_firstfield; /* historic cyl groups linked list */ + int32_t cg_magic; /* magic number */ + time_t cg_time; /* time last written */ + int32_t cg_cgx; /* we are the cgx'th cylinder group */ + int16_t cg_ncyl; /* number of cyl's this cg */ + int16_t cg_niblk; /* number of inode blocks this cg */ + int32_t cg_ndblk; /* number of data blocks this cg */ struct csum cg_cs; /* cylinder summary information */ - long cg_rotor; /* position of last used block */ - long cg_frotor; /* position of last used frag */ - long cg_irotor; /* position of last used inode */ - long cg_frsum[MAXFRAG]; /* counts of available frags */ - long cg_btotoff; /* (long) block totals per cylinder */ - long cg_boff; /* (short) free block positions */ - long cg_iusedoff; /* (char) used inode map */ - long cg_freeoff; /* (u_char) free block map */ - long cg_nextfreeoff; /* (u_char) next available space */ - long cg_clustersumoff; /* (long) counts of avail clusters */ - long cg_clusteroff; /* (char) free cluster map */ - long cg_nclusterblks; /* number of clusters this cg */ - long cg_sparecon[13]; /* reserved for future use */ - u_char cg_space[1]; /* space for cylinder group maps */ + int32_t cg_rotor; /* position of last used block */ + int32_t cg_frotor; /* position of last used frag */ + int32_t cg_irotor; /* position of last used inode */ + int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ + int32_t cg_btotoff; /* (int32) block totals per cylinder */ + int32_t cg_boff; /* (u_int16) free block positions */ + int32_t cg_iusedoff; /* (u_int8) used inode map */ + int32_t cg_freeoff; /* (u_int8) free block map */ + int32_t cg_nextfreeoff; /* (u_int8) next available space */ + int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */ + int32_t cg_clusteroff; /* (u_int8) free cluster map */ + int32_t cg_nclusterblks; /* number of clusters this cg */ + int32_t cg_sparecon[13]; /* reserved for future use */ + u_int8_t cg_space[1]; /* space for cylinder group maps */ /* actually longer */ }; + /* * Macros for access to cylinder group array structures */ #define cg_blktot(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_btot) \ - : ((long *)((char *)(cgp) + (cgp)->cg_btotoff))) + : ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_btotoff))) #define cg_blks(fs, cgp, cylno) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_b[cylno]) \ - : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) + : ((int16_t *)((u_int8_t *)(cgp) + \ + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) #define cg_inosused(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_iused) \ - : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff))) + : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff))) #define cg_blksfree(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_free) \ - : ((u_char *)((char *)(cgp) + (cgp)->cg_freeoff))) + : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff))) #define cg_chkmagic(cgp) \ ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) #define cg_clustersfree(cgp) \ - ((u_char *)((char *)(cgp) + (cgp)->cg_clusteroff)) + ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_clusteroff)) #define cg_clustersum(cgp) \ - ((long *)((char *)(cgp) + (cgp)->cg_clustersumoff)) + ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_clustersumoff)) /* * The following structure is defined * for compatibility with old file systems. */ -struct ocg { - struct ocg *cg_link; /* linked list of cyl groups */ - struct ocg *cg_rlink; /* used for incore cyl groups */ - time_t cg_time; /* time last written */ - long cg_cgx; /* we are the cgx'th cylinder group */ - short cg_ncyl; /* number of cyl's this cg */ - short cg_niblk; /* number of inode blocks this cg */ - long cg_ndblk; /* number of data blocks this cg */ +struct ocg { + int32_t cg_firstfield; /* historic linked list of cyl groups */ + int32_t cg_unused_1; /* used for incore cyl groups */ + time_t cg_time; /* time last written */ + int32_t cg_cgx; /* we are the cgx'th cylinder group */ + int16_t cg_ncyl; /* number of cyl's this cg */ + int16_t cg_niblk; /* number of inode blocks this cg */ + int32_t cg_ndblk; /* number of data blocks this cg */ struct csum cg_cs; /* cylinder summary information */ - long cg_rotor; /* position of last used block */ - long cg_frotor; /* position of last used frag */ - long cg_irotor; /* position of last used inode */ - long cg_frsum[8]; /* counts of available frags */ - long cg_btot[32]; /* block totals per cylinder */ - short cg_b[32][8]; /* positions of free blocks */ - char cg_iused[256]; /* used inode map */ - long cg_magic; /* magic number */ - u_char cg_free[1]; /* free block map */ + int32_t cg_rotor; /* position of last used block */ + int32_t cg_frotor; /* position of last used frag */ + int32_t cg_irotor; /* position of last used inode */ + int32_t cg_frsum[8]; /* counts of available frags */ + int32_t cg_btot[32]; /* block totals per cylinder */ + int16_t cg_b[32][8]; /* positions of free blocks */ + u_int8_t cg_iused[256]; /* used inode map */ + int32_t cg_magic; /* magic number */ + u_int8_t cg_free[1]; /* free block map */ /* actually longer */ }; @@ -384,7 +395,7 @@ struct ocg { * Cylinder group macros to locate things in cylinder groups. * They calc file system addresses of cylinder group data structures. */ -#define cgbase(fs, c) ((daddr_t)((fs)->fs_fpg * (c))) +#define cgbase(fs, c) ((ufs_daddr_t)((fs)->fs_fpg * (c))) #define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ #define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ #define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ @@ -400,7 +411,7 @@ struct ocg { */ #define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) #define ino_to_fsba(fs, x) \ - ((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ + ((ufs_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) #define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) @@ -457,7 +468,7 @@ struct ocg { /* * Determine the number of available frags given a - * percentage to hold in reserve + * percentage to hold in reserve. */ #define freespace(fs, percentreserved) \ (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ @@ -476,19 +487,20 @@ struct ocg { : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) /* - * Number of disk sectors per block; assumes DEV_BSIZE byte sector size. + * Number of disk sectors per block/fragment; assumes DEV_BSIZE byte + * sector size. */ #define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) #define NSPF(fs) ((fs)->fs_nspf) /* - * INOPB is the number of inodes in a secondary storage block. + * Number of inodes in a secondary storage block/fragment. */ #define INOPB(fs) ((fs)->fs_inopb) #define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) /* - * NINDIR is the number of indirects in a file system block. + * Number of indirects in a file system block. */ #define NINDIR(fs) ((fs)->fs_nindir) diff --git a/sys/ufs/lfs/lfs_subr.c b/sys/ufs/lfs/lfs_subr.c index 7cd938b..737d2c5 100644 --- a/sys/ufs/lfs/lfs_subr.c +++ b/sys/ufs/lfs/lfs_subr.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)lfs_subr.c 8.2 (Berkeley) 9/21/93 + * @(#)lfs_subr.c 8.4 (Berkeley) 5/8/95 * $FreeBSD$ */ @@ -65,13 +65,13 @@ lfs_blkatoff(ap) register struct lfs *fs; struct inode *ip; struct buf *bp; - daddr_t lbn; + ufs_daddr_t lbn; int bsize, error; ip = VTOI(ap->a_vp); fs = ip->i_lfs; lbn = lblkno(fs, ap->a_offset); - bsize = blksize(fs); + bsize = blksize(fs, ip, lbn); *ap->a_bpp = NULL; if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { @@ -112,7 +112,8 @@ lfs_seglock(fs, flags) sp = fs->lfs_sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK); sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) / - sizeof(daddr_t) + 1) * sizeof(struct buf *), M_SEGMENT, M_WAITOK); + sizeof(ufs_daddr_t) + 1) * sizeof(struct buf *), + M_SEGMENT, M_WAITOK); sp->seg_flags = flags; sp->vp = NULL; (void) lfs_initseg(fs); diff --git a/sys/ufs/lfs/lfs_syscalls.c b/sys/ufs/lfs/lfs_syscalls.c index 01e63e2..6ec1d9e 100644 --- a/sys/ufs/lfs/lfs_syscalls.c +++ b/sys/ufs/lfs/lfs_syscalls.c @@ -115,7 +115,7 @@ lfs_markv(p, uap, retval) if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t))) return (error); - if ((mntp = getvfs(&fsid)) == NULL) + if ((mntp = vfs_getvfs(&fsid)) == NULL) return (EINVAL); cnt = uap->blkcnt; @@ -286,7 +286,7 @@ lfs_bmapv(p, uap, retval) if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t))) return (error); - if ((mntp = getvfs(&fsid)) == NULL) + if ((mntp = vfs_getvfs(&fsid)) == NULL) return (EINVAL); cnt = uap->blkcnt; @@ -347,7 +347,7 @@ lfs_segclean(p, uap, retval) if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t))) return (error); - if ((mntp = getvfs(&fsid)) == NULL) + if ((mntp = vfs_getvfs(&fsid)) == NULL) return (EINVAL); fs = VFSTOUFS(mntp)->um_lfs; @@ -413,14 +413,14 @@ lfs_segwait(p, uap, retval) if (fsid == (fsid_t)-1) addr = &lfs_allclean_wakeup; else { - if ((mntp = getvfs(&fsid)) == NULL) + if ((mntp = vfs_getvfs(&fsid)) == NULL) return (EINVAL); addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg; } #else if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t))) return (error); - if ((mntp = getvfs(&fsid)) == NULL) + if ((mntp = vfs_getvfs(&fsid)) == NULL) addr = &lfs_allclean_wakeup; else addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg; diff --git a/sys/ufs/mfs/mfs_extern.h b/sys/ufs/mfs/mfs_extern.h index e2bd561..1556659 100644 --- a/sys/ufs/mfs/mfs_extern.h +++ b/sys/ufs/mfs/mfs_extern.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mfs_extern.h 8.1 (Berkeley) 6/11/93 + * @(#)mfs_extern.h 8.4 (Berkeley) 3/30/95 * $FreeBSD$ */ @@ -44,4 +44,6 @@ void mfs_doio __P((struct buf *bp, caddr_t base)); int mfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); int mfs_mountroot __P((void)); +#define mfs_revoke vop_revoke + #endif /* !_UFS_MFS_MFS_EXTERN_H_ */ diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c index 372d9db..3847603 100644 --- a/sys/ufs/mfs/mfs_vfsops.c +++ b/sys/ufs/mfs/mfs_vfsops.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mfs_vfsops.c 8.4 (Berkeley) 4/16/94 + * @(#)mfs_vfsops.c 8.11 (Berkeley) 6/19/95 * $FreeBSD$ */ @@ -84,7 +84,7 @@ static int mfs_mount __P((struct mount *mp, static int mfs_start __P((struct mount *mp, int flags, struct proc *p)); static int mfs_statfs __P((struct mount *mp, struct statfs *sbp, struct proc *p)); -static int mfs_init __P((void)); +static int mfs_init __P((struct vfsconf *)); /* * mfs vfs operations. @@ -230,8 +230,8 @@ mfs_mount(mp, path, data, ndp, p) struct vnode *devvp; struct mfs_args args; struct ufsmount *ump; - register struct fs *fs; - register struct mfsnode *mfsp; + struct fs *fs; + struct mfsnode *mfsp; u_int size; int flags, err; @@ -282,8 +282,10 @@ mfs_mount(mp, path, data, ndp, p) /* Get vnode for root device*/ - if( bdevvp( rootdev, &rootvp)) - panic("mfs_mountroot: can't setup bdevvp for rootdev"); + if (error = bdevvp( rootdev, &rootvp)) { + printf("mfs_mountroot: can't setup bdevvp for rootdev"); + return (error); + } /* * FS specific handling @@ -342,12 +344,7 @@ mfs_mount(mp, path, data, ndp, p) flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; - if (vfs_busy(mp)) { - err = EBUSY; - goto error_1; - } err = ffs_flushfiles(mp, flags, p); - vfs_unbusy(mp); if (err) goto error_1; } @@ -503,7 +500,7 @@ mfs_statfs(mp, sbp, p) int error; error = ffs_statfs(mp, sbp, p); - sbp->f_type = MOUNT_MFS; + sbp->f_type = mp->mnt_vfc->vfc_typenum; return (error); } @@ -511,7 +508,8 @@ mfs_statfs(mp, sbp, p) * Memory based filesystem initialization. */ static int -mfs_init() +mfs_init(vfsp) + struct vfsconf *vfsp; { return (0); } diff --git a/sys/ufs/mfs/mfs_vnops.c b/sys/ufs/mfs/mfs_vnops.c index 29eae7d..75ccd85 100644 --- a/sys/ufs/mfs/mfs_vnops.c +++ b/sys/ufs/mfs/mfs_vnops.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mfs_vnops.c 8.3 (Berkeley) 9/21/93 + * @(#)mfs_vnops.c 8.11 (Berkeley) 5/22/95 * $FreeBSD$ */ @@ -51,12 +51,6 @@ #include #include -#if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k) -static int mfsmap_want; /* 1 => need kernel I/O resources */ -struct map mfsmap[MFS_MAPSIZE]; -extern char mfsiobuf[]; -#endif - static int mfs_badop __P((void)); static int mfs_bmap __P((struct vop_bmap_args *)); static int mfs_close __P((struct vop_close_args *)); @@ -84,6 +78,7 @@ static struct vnodeopv_entry_desc mfs_vnodeop_entries[] = { { &vop_write_desc, (vop_t *)mfs_write }, /* write */ { &vop_ioctl_desc, (vop_t *)mfs_ioctl }, /* ioctl */ { &vop_select_desc, (vop_t *)mfs_select }, /* select */ + { &vop_revoke_desc, (vop_t *)mfs_revoke }, /* revoke */ { &vop_mmap_desc, (vop_t *)mfs_mmap }, /* mmap */ { &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */ { &vop_seek_desc, (vop_t *)mfs_seek }, /* seek */ @@ -227,9 +222,9 @@ static int mfs_bmap(ap) struct vop_bmap_args /* { struct vnode *a_vp; - daddr_t a_bn; + ufs_daddr_t a_bn; struct vnode **a_vpp; - daddr_t *a_bnp; + ufs_daddr_t *a_bnp; int *a_runp; } */ *ap; { @@ -300,13 +295,16 @@ static int mfs_inactive(ap) struct vop_inactive_args /* { struct vnode *a_vp; + struct proc *a_p; } */ *ap; { - register struct mfsnode *mfsp = VTOMFS(ap->a_vp); + struct vnode *vp = ap->a_vp; + struct mfsnode *mfsp = VTOMFS(vp); if (!TAILQ_EMPTY(&mfsp->buf_queue)) panic("mfs_inactive: not inactive (next buffer %p)", TAILQ_FIRST(&mfsp->buf_queue)); + VOP_UNLOCK(vp, 0, ap->a_p); return (0); } @@ -319,9 +317,10 @@ mfs_reclaim(ap) struct vnode *a_vp; } */ *ap; { + register struct vnode *vp = ap->a_vp; - FREE(ap->a_vp->v_data, M_MFSNODE); - ap->a_vp->v_data = NULL; + FREE(vp->v_data, M_MFSNODE); + vp->v_data = NULL; return (0); } @@ -351,4 +350,3 @@ mfs_badop() panic("mfs_badop called"); /* NOTREACHED */ } - diff --git a/sys/ufs/mfs/mfsnode.h b/sys/ufs/mfs/mfsnode.h index 29fbd33..403d473 100644 --- a/sys/ufs/mfs/mfsnode.h +++ b/sys/ufs/mfs/mfsnode.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)mfsnode.h 8.2 (Berkeley) 8/11/93 + * @(#)mfsnode.h 8.3 (Berkeley) 5/19/95 * $FreeBSD$ */ @@ -78,9 +78,9 @@ struct mfsnode { #define mfs_readdir ((int (*) __P((struct vop_readdir_args *)))mfs_badop) #define mfs_readlink ((int (*) __P((struct vop_readlink_args *)))mfs_badop) #define mfs_abortop ((int (*) __P((struct vop_abortop_args *)))mfs_badop) -#define mfs_lock ((int (*) __P((struct vop_lock_args *)))nullop) -#define mfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) -#define mfs_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) +#define mfs_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock) +#define mfs_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock) +#define mfs_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked) #define mfs_pathconf ((int (*) __P((struct vop_pathconf_args *)))mfs_badop) #define mfs_advlock ((int (*) __P((struct vop_advlock_args *)))mfs_badop) #define mfs_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))mfs_badop) diff --git a/sys/ufs/ufs/dinode.h b/sys/ufs/ufs/dinode.h index c2fd5bd..461a6c0 100644 --- a/sys/ufs/ufs/dinode.h +++ b/sys/ufs/ufs/dinode.h @@ -51,32 +51,46 @@ #define ROOTINO ((ino_t)2) /* + * The Whiteout inode# is a dummy non-zero inode number which will + * never be allocated to a real file. It is used as a place holder + * in the directory entry which has been tagged as a DT_W entry. + * See the comments about ROOTINO above. + */ +#define WINO ((ino_t)1) + +/* * A dinode contains all the meta-data associated with a UFS file. - * This structure defines the on-disk format of a dinode. + * This structure defines the on-disk format of a dinode. Since + * this structure describes an on-disk structure, all its fields + * are defined by types with precise widths. */ +/* typedef int32_t ufs_daddr_t; */ #define NDADDR 12 /* Direct addresses in inode. */ #define NIADDR 3 /* Indirect addresses in inode. */ struct dinode { - u_short di_mode; /* 0: IFMT and permissions. */ - short di_nlink; /* 2: File link count. */ + u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ union { - u_short oldids[2]; /* 4: Ffs: old user and group ids. */ - ino_t inumber; /* 4: Lfs: inode number. */ + u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */ + int32_t inumber; /* 4: Lfs: inode number. */ } di_u; - u_quad_t di_size; /* 8: File byte count. */ - struct timespec di_atime; /* 16: Last access time. */ - struct timespec di_mtime; /* 24: Last modified time. */ - struct timespec di_ctime; /* 32: Last inode change time. */ - daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */ - daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ - u_long di_flags; /* 100: Status flags (chflags). */ - long di_blocks; /* 104: Blocks actually held. */ - long di_gen; /* 108: Generation number. */ - u_long di_uid; /* 112: File owner. */ - u_long di_gid; /* 116: File group. */ - long di_spare[2]; /* 120: Reserved; currently unused */ + u_int64_t di_size; /* 8: File byte count. */ + int32_t di_atime; /* 16: Last access time. */ + int32_t di_atimensec; /* 20: Last access time. */ + int32_t di_mtime; /* 24: Last modified time. */ + int32_t di_mtimensec; /* 28: Last modified time. */ + int32_t di_ctime; /* 32: Last inode change time. */ + int32_t di_ctimensec; /* 36: Last inode change time. */ + ufs_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */ + ufs_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ + u_int32_t di_flags; /* 100: Status flags (chflags). */ + int32_t di_blocks; /* 104: Blocks actually held. */ + int32_t di_gen; /* 108: Generation number. */ + u_int32_t di_uid; /* 112: File owner. */ + u_int32_t di_gid; /* 116: File group. */ + int32_t di_spare[2]; /* 120: Reserved; currently unused */ }; /* @@ -91,9 +105,9 @@ struct dinode { #define di_ouid di_u.oldids[0] #define di_rdev di_db[0] #define di_shortlink di_db -#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(daddr_t)) +#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(ufs_daddr_t)) -/* File modes. */ +/* File permissions. */ #define IEXEC 0000100 /* Executable. */ #define IWRITE 0000200 /* Writeable. */ #define IREAD 0000400 /* Readable. */ @@ -110,5 +124,6 @@ struct dinode { #define IFREG 0100000 /* Regular file. */ #define IFLNK 0120000 /* Symbolic link. */ #define IFSOCK 0140000 /* UNIX domain socket. */ +#define IFWHT 0160000 /* Whiteout. */ #endif diff --git a/sys/ufs/ufs/dir.h b/sys/ufs/ufs/dir.h index 3a3ceb8..0c8680e 100644 --- a/sys/ufs/ufs/dir.h +++ b/sys/ufs/ufs/dir.h @@ -43,6 +43,17 @@ #define _UFS_UFS_DIR_H_ /* + * Theoretically, directories can be more than 2Gb in length, however, in + * practice this seems unlikely. So, we define the type doff_t as a 32-bit + * quantity to keep down the cost of doing lookup on a 32-bit machine. + */ +#define doff_t int32_t + +#ifdef notused +#define MAXDIRSIZE (0x7fffffff) +#endif + +/* * A directory consists of some number of blocks of DIRBLKSIZ * bytes, where DIRBLKSIZ is chosen such that it can be transferred * to disk in a single atomic operation (e.g. 512 bytes on most machines). @@ -71,11 +82,11 @@ #define MAXNAMLEN 255 struct direct { - u_long d_ino; /* inode number of entry */ - u_short d_reclen; /* length of this record */ - u_char d_type; /* file type, see below */ - u_char d_namlen; /* length of string in d_name */ - char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */ + u_int32_t d_ino; /* inode number of entry */ + u_int16_t d_reclen; /* length of this record */ + u_int8_t d_type; /* file type, see below */ + u_int8_t d_namlen; /* length of string in d_name */ + char d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */ }; /* @@ -89,6 +100,7 @@ struct direct { #define DT_REG 8 #define DT_LNK 10 #define DT_SOCK 12 +#define DT_WHT 14 /* * Convert between stat structure types and directory types. @@ -118,34 +130,33 @@ struct direct { #define NEWDIRFMT 0 /* - * Template for manipulating directories. - * Should use struct direct's, but the name field - * is MAXNAMLEN - 1, and this just won't do. + * Template for manipulating directories. Should use struct direct's, + * but the name field is MAXNAMLEN - 1, and this just won't do. */ struct dirtemplate { - u_long dot_ino; - short dot_reclen; - u_char dot_type; - u_char dot_namlen; - char dot_name[4]; /* must be multiple of 4 */ - u_long dotdot_ino; - short dotdot_reclen; - u_char dotdot_type; - u_char dotdot_namlen; - char dotdot_name[4]; /* ditto */ + u_int32_t dot_ino; + int16_t dot_reclen; + u_int8_t dot_type; + u_int8_t dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + u_int32_t dotdot_ino; + int16_t dotdot_reclen; + u_int8_t dotdot_type; + u_int8_t dotdot_namlen; + char dotdot_name[4]; /* ditto */ }; /* * This is the old format of directories, sanz type element. */ struct odirtemplate { - u_long dot_ino; - short dot_reclen; - u_short dot_namlen; - char dot_name[4]; /* must be multiple of 4 */ - u_long dotdot_ino; - short dotdot_reclen; - u_short dotdot_namlen; - char dotdot_name[4]; /* ditto */ + u_int32_t dot_ino; + int16_t dot_reclen; + u_int16_t dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + u_int32_t dotdot_ino; + int16_t dotdot_reclen; + u_int16_t dotdot_namlen; + char dotdot_name[4]; /* ditto */ }; #endif /* !_DIR_H_ */ diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index dc19d34..438471f 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -35,42 +35,33 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)inode.h 8.4 (Berkeley) 1/21/94 + * @(#)inode.h 8.9 (Berkeley) 5/14/95 * $FreeBSD$ */ #ifndef _UFS_UFS_INODE_H_ #define _UFS_UFS_INODE_H_ +#include #include /* - * Theoretically, directories can be more than 2Gb in length, however, in - * practice this seems unlikely. So, we define the type doff_t as a long - * to keep down the cost of doing lookup on a 32-bit machine. If you are - * porting to a 64-bit architecture, you should make doff_t the same as off_t. - */ -#define doff_t long - -/* - * The inode is used to describe each active (or recently active) - * file in the UFS filesystem. It is composed of two types of - * information. The first part is the information that is needed - * only while the file is active (such as the identity of the file - * and linkage to speed its lookup). The second part is the - * permanent meta-data associated with the file which is read - * in from the permanent dinode from long term storage when the - * file becomes active, and is put back when the file is no longer - * being used. + * The inode is used to describe each active (or recently active) file in the + * UFS filesystem. It is composed of two types of information. The first part + * is the information that is needed only while the file is active (such as + * the identity of the file and linkage to speed its lookup). The second part + * is the permanent meta-data associated with the file which is read in + * from the permanent dinode from long term storage when the file becomes + * active, and is put back when the file is no longer being used. */ struct inode { - struct inode *i_next; /* Hash chain forward. */ - struct inode **i_prev; /* Hash chain back. */ - struct vnode *i_vnode; /* Vnode associated with this inode. */ - struct vnode *i_devvp; /* Vnode for block I/O. */ - u_long i_flag; /* I* flags. */ - dev_t i_dev; /* Device associated with the inode. */ - ino_t i_number; /* The identity of the inode. */ + LIST_ENTRY(inode) i_hash;/* Hash chain. */ + struct vnode *i_vnode;/* Vnode associated with this inode. */ + struct vnode *i_devvp;/* Vnode for block I/O. */ + u_int32_t i_flag; /* flags, see below */ + dev_t i_dev; /* Device associated with the inode. */ + ino_t i_number; /* The identity of the inode. */ + union { /* Associated filesystem. */ struct fs *fs; /* FFS */ struct lfs *lfs; /* LFS */ @@ -79,22 +70,21 @@ struct inode { #define i_fs inode_u.fs #define i_lfs inode_u.lfs #define i_e2fs inode_u.e2fs - struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */ - u_quad_t i_modrev; /* Revision level for lease. */ - struct lockf *i_lockf; /* Head of byte-level lock list. */ - pid_t i_lockholder; /* DEBUG: holder of inode lock. */ - pid_t i_lockwaiter; /* DEBUG: latest blocked for inode lock. */ + struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */ + u_quad_t i_modrev; /* Revision level for NFS lease. */ + struct lockf *i_lockf;/* Head of byte-level lock list. */ + struct lock i_lock; /* Inode lock. */ /* * Side effects; used during directory lookup. */ - long i_count; /* Size of free slot in directory. */ - doff_t i_endoff; /* End of useful stuff in directory. */ - doff_t i_diroff; /* Offset in dir, where we found last entry. */ - doff_t i_offset; /* Offset of free space in directory. */ - ino_t i_ino; /* Inode number of found directory. */ - u_long i_reclen; /* Size of found directory entry. */ - int i_lockcount; /* Process lock count (recursion) */ - long i_spare[10]; /* Spares to round up to 128 bytes. */ + int32_t i_count; /* Size of free slot in directory. */ + doff_t i_endoff; /* End of useful stuff in directory. */ + doff_t i_diroff; /* Offset in dir, where we found last entry. */ + doff_t i_offset; /* Offset of free space in directory. */ + ino_t i_ino; /* Inode number of found directory. */ + u_int32_t i_reclen; /* Size of found directory entry. */ + int i_lockcount; /* Process lock count (recursion) */ + int i_spare[10]; /* XXX spare storage (for ext2fs) */ /* * The on-disk dinode itself. */ @@ -102,8 +92,10 @@ struct inode { }; #define i_atime i_din.di_atime +#define i_atimensec i_din.di_atimensec #define i_blocks i_din.di_blocks #define i_ctime i_din.di_ctime +#define i_ctimensec i_din.di_ctimensec #define i_db i_din.di_db #define i_flags i_din.di_flags #define i_gen i_din.di_gen @@ -111,6 +103,7 @@ struct inode { #define i_ib i_din.di_ib #define i_mode i_din.di_mode #define i_mtime i_din.di_mtime +#define i_mtimensec i_din.di_mtimensec #define i_nlink i_din.di_nlink #define i_rdev i_din.di_rdev #define i_shortlink i_din.di_shortlink @@ -120,15 +113,12 @@ struct inode { /* These flags are kept in i_flag. */ #define IN_ACCESS 0x0001 /* Access time update request. */ #define IN_CHANGE 0x0002 /* Inode change time update request. */ -#define IN_EXLOCK 0x0004 /* File has exclusive lock. */ -#define IN_LOCKED 0x0008 /* Inode lock. */ -#define IN_LWAIT 0x0010 /* Process waiting on file lock. */ -#define IN_MODIFIED 0x0020 /* Inode has been modified. */ -#define IN_RENAME 0x0040 /* Inode is being renamed. */ -#define IN_SHLOCK 0x0080 /* File has shared lock. */ -#define IN_UPDATE 0x0100 /* Modification time update request. */ -#define IN_WANTED 0x0200 /* Inode is wanted by a process. */ -#define IN_RECURSE 0x0400 /* Recursion expected */ +#define IN_UPDATE 0x0004 /* Modification time update request. */ +#define IN_MODIFIED 0x0008 /* Inode has been modified. */ +#define IN_RENAME 0x0010 /* Inode is being renamed. */ +#define IN_SHLOCK 0x0020 /* File has shared lock. */ +#define IN_EXLOCK 0x0040 /* File has exclusive lock. */ +#define IN_RECURSE 0x0080 /* Recursion expected */ #ifdef KERNEL /* @@ -136,7 +126,7 @@ struct inode { * ufs_getlbns and used by truncate and bmap code. */ struct indir { - daddr_t in_lbn; /* Logical block number. */ + ufs_daddr_t in_lbn; /* Logical block number. */ int in_off; /* Offset in buffer. */ int in_exists; /* Flag if the block exists. */ }; @@ -155,25 +145,25 @@ struct indir { if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \ (ip)->i_flag |= IN_MODIFIED; \ if ((ip)->i_flag & IN_ACCESS) \ - (ip)->i_atime.tv_sec \ + (ip)->i_atime \ = ((t1) == &time ? tv_sec : (t1)->tv_sec); \ if ((ip)->i_flag & IN_UPDATE) { \ - (ip)->i_mtime.tv_sec \ + (ip)->i_mtime \ = ((t2) == &time ? tv_sec : (t2)->tv_sec); \ (ip)->i_modrev++; \ } \ if ((ip)->i_flag & IN_CHANGE) \ - (ip)->i_ctime.tv_sec = tv_sec; \ + (ip)->i_ctime = tv_sec; \ (ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \ } \ } /* This overlays the fid structure (see mount.h). */ struct ufid { - u_short ufid_len; /* Length of structure. */ - u_short ufid_pad; /* Force long alignment. */ - ino_t ufid_ino; /* File number (ino). */ - long ufid_gen; /* Generation number. */ + u_int16_t ufid_len; /* Length of structure. */ + u_int16_t ufid_pad; /* Force 32-bit alignment. */ + ino_t ufid_ino; /* File number (ino). */ + int32_t ufid_gen; /* Generation number. */ }; #endif /* KERNEL */ diff --git a/sys/ufs/ufs/quota.h b/sys/ufs/ufs/quota.h index e780865..7b9ff40 100644 --- a/sys/ufs/ufs/quota.h +++ b/sys/ufs/ufs/quota.h @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)quota.h 8.1 (Berkeley) 6/11/93 + * @(#)quota.h 8.3 (Berkeley) 8/19/94 * $FreeBSD$ */ @@ -49,8 +49,8 @@ * failure). The timer is started when the user crosses their soft limit, it * is reset when they go below their soft limit. */ -#define MAX_IQ_TIME (7*24*60*60) /* 1 week */ -#define MAX_DQ_TIME (7*24*60*60) /* 1 week */ +#define MAX_IQ_TIME (7*24*60*60) /* seconds in 1 week */ +#define MAX_DQ_TIME (7*24*60*60) /* seconds in 1 week */ /* * The following constants define the usage of the quota file array in the @@ -97,15 +97,15 @@ * the vnode for each quota file (a pointer is retained in the ufsmount * structure). */ -struct dqblk { - u_long dqb_bhardlimit; /* absolute limit on disk blks alloc */ - u_long dqb_bsoftlimit; /* preferred limit on disk blks */ - u_long dqb_curblocks; /* current block count */ - u_long dqb_ihardlimit; /* maximum # allocated inodes + 1 */ - u_long dqb_isoftlimit; /* preferred inode limit */ - u_long dqb_curinodes; /* current # allocated inodes */ - time_t dqb_btime; /* time limit for excessive disk use */ - time_t dqb_itime; /* time limit for excessive files */ +struct dqblk { + u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */ + u_int32_t dqb_curblocks; /* current block count */ + u_int32_t dqb_ihardlimit; /* maximum # allocated inodes + 1 */ + u_int32_t dqb_isoftlimit; /* preferred inode limit */ + u_int32_t dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive files */ }; /* @@ -114,14 +114,14 @@ struct dqblk { * filesystem for the current user or group. A cache is kept of recently * used entries. */ -struct dquot { - struct dquot *dq_forw, **dq_back; /* hash list */ - struct dquot *dq_freef, **dq_freeb; /* free list */ - short dq_flags; /* flags, see below */ - short dq_cnt; /* count of active references */ - short dq_spare; /* unused spare padding */ - short dq_type; /* quota type of this dquot */ - u_long dq_id; /* identifier this applies to */ +struct dquot { + LIST_ENTRY(dquot) dq_hash; /* hash list */ + TAILQ_ENTRY(dquot) dq_freelist; /* free list */ + u_int16_t dq_flags; /* flags, see below */ + u_int16_t dq_cnt; /* count of active references */ + u_int16_t dq_spare; /* unused spare padding */ + u_int16_t dq_type; /* quota type of this dquot */ + u_int32_t dq_id; /* identifier this applies to */ struct ufsmount *dq_ump; /* filesystem that this is taken from */ struct dqblk dq_dqb; /* actual usage & quotas */ }; @@ -147,11 +147,11 @@ struct dquot { #define dq_itime dq_dqb.dqb_itime /* - * If the system has never checked for a quota for this file, then it is set - * to NODQUOT. Once a write attempt is made the inode pointer is set to - * reference a dquot structure. + * If the system has never checked for a quota for this file, then it is + * set to NODQUOT. Once a write attempt is made the inode pointer is set + * to reference a dquot structure. */ -#define NODQUOT ((struct dquot *) 0) +#define NODQUOT NULL /* * Flags to chkdq() and chkiq() diff --git a/sys/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c index e17b5b7..aef2b83 100644 --- a/sys/ufs/ufs/ufs_bmap.c +++ b/sys/ufs/ufs/ufs_bmap.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94 + * @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95 * $FreeBSD$ */ @@ -63,9 +63,9 @@ int ufs_bmap(ap) struct vop_bmap_args /* { struct vnode *a_vp; - daddr_t a_bn; + ufs_daddr_t a_bn; struct vnode **a_vpp; - daddr_t *a_bnp; + ufs_daddr_t *a_bnp; int *a_runp; int *a_runb; } */ *ap; @@ -100,8 +100,8 @@ ufs_bmap(ap) int ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb) struct vnode *vp; - register daddr_t bn; - daddr_t *bnp; + ufs_daddr_t bn; + ufs_daddr_t *bnp; struct indir *ap; int *nump; int *runp; @@ -113,7 +113,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb) struct mount *mp; struct vnode *devvp; struct indir a[NIADDR+1], *xap; - daddr_t daddr; + ufs_daddr_t daddr; long metalbn; int error, maxrun = 0, num; @@ -209,12 +209,13 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb) } } - daddr = ((daddr_t *)bp->b_data)[xap->in_off]; + daddr = ((ufs_daddr_t *)bp->b_data)[xap->in_off]; if (num == 1 && daddr && runp) { for (bn = xap->in_off + 1; bn < MNINDIR(ump) && *runp < maxrun && - is_sequential(ump, ((daddr_t *)bp->b_data)[bn - 1], - ((daddr_t *)bp->b_data)[bn]); + is_sequential(ump, + ((ufs_daddr_t *)bp->b_data)[bn - 1], + ((ufs_daddr_t *)bp->b_data)[bn]); ++bn, ++*runp); bn = xap->in_off; if (runb && bn) { @@ -245,7 +246,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb) int ufs_getlbns(vp, bn, ap, nump) struct vnode *vp; - register daddr_t bn; + ufs_daddr_t bn; struct indir *ap; int *nump; { diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h index 4c114d9..a450e92 100644 --- a/sys/ufs/ufs/ufs_extern.h +++ b/sys/ufs/ufs/ufs_extern.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_extern.h 8.3 (Berkeley) 4/16/94 + * @(#)ufs_extern.h 8.10 (Berkeley) 5/14/95 * $FreeBSD$ */ @@ -49,8 +49,8 @@ struct proc; struct ucred; struct uio; struct vattr; +struct vfsconf; struct vnode; -struct ufs_args; int ufs_abortop __P((struct vop_abortop_args *)); int ufs_access __P((struct vop_access_args *)); @@ -71,7 +71,7 @@ int ufs_dirremove __P((struct vnode *, struct componentname*)); int ufs_dirrewrite __P((struct inode *, struct inode *, struct componentname *)); int ufs_getattr __P((struct vop_getattr_args *)); -int ufs_getlbns __P((struct vnode *, daddr_t, struct indir *, int *)); +int ufs_getlbns __P((struct vnode *, ufs_daddr_t, struct indir *, int *)); struct vnode * ufs_ihashget __P((dev_t, ino_t)); void ufs_ihashinit __P((void)); @@ -80,9 +80,14 @@ struct vnode * ufs_ihashlookup __P((dev_t, ino_t)); void ufs_ihashrem __P((struct inode *)); int ufs_inactive __P((struct vop_inactive_args *)); -int ufs_init __P((void)); +int ufs_init __P((struct vfsconf *)); int ufs_ioctl __P((struct vop_ioctl_args *)); int ufs_islocked __P((struct vop_islocked_args *)); +#ifdef NFS +#define ufs_lease_check lease_check +#else +#define ufs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop) +#endif int ufs_link __P((struct vop_link_args *)); int ufs_lock __P((struct vop_lock_args *)); int ufs_lookup __P((struct vop_lookup_args *)); @@ -95,9 +100,10 @@ int ufs_pathconf __P((struct vop_pathconf_args *)); int ufs_print __P((struct vop_print_args *)); int ufs_readdir __P((struct vop_readdir_args *)); int ufs_readlink __P((struct vop_readlink_args *)); -int ufs_reclaim __P((struct vop_reclaim_args *)); +int ufs_reclaim __P((struct vnode *, struct proc *)); int ufs_remove __P((struct vop_remove_args *)); int ufs_rename __P((struct vop_rename_args *)); +#define ufs_revoke vop_revoke int ufs_rmdir __P((struct vop_rmdir_args *)); int ufs_root __P((struct mount *, struct vnode **)); int ufs_seek __P((struct vop_seek_args *)); @@ -108,6 +114,7 @@ int ufs_strategy __P((struct vop_strategy_args *)); int ufs_symlink __P((struct vop_symlink_args *)); int ufs_unlock __P((struct vop_unlock_args *)); int ufs_vinit __P((struct mount *, vop_t **, vop_t **, struct vnode **)); +int ufs_whiteout __P((struct vop_whiteout_args *)); int ufsspec_close __P((struct vop_close_args *)); int ufsspec_read __P((struct vop_read_args *)); int ufsspec_write __P((struct vop_write_args *)); diff --git a/sys/ufs/ufs/ufs_ihash.c b/sys/ufs/ufs/ufs_ihash.c index a51af00..ea83308 100644 --- a/sys/ufs/ufs/ufs_ihash.c +++ b/sys/ufs/ufs/ufs_ihash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1982, 1986, 1989, 1991, 1993 + * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93 + * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 * $FreeBSD$ */ @@ -47,9 +47,10 @@ /* * Structures associated with inode cacheing. */ -struct inode **ihashtbl; +LIST_HEAD(ihashhead, inode) *ihashtbl; u_long ihash; /* size of hash table - 1 */ -#define INOHASH(device, inum) (((device) + (inum)) & ihash) +#define INOHASH(device, inum) (&ihashtbl[((device) + (inum)) & ihash]) +struct simplelock ufs_ihash_slock; /* * Initialize inode hash table. @@ -59,6 +60,7 @@ ufs_ihashinit() { ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash); + simple_lock_init(&ufs_ihash_slock); } /* @@ -66,19 +68,21 @@ ufs_ihashinit() * to it. If it is in core, return it, even if it is locked. */ struct vnode * -ufs_ihashlookup(device, inum) - dev_t device; +ufs_ihashlookup(dev, inum) + dev_t dev; ino_t inum; { - register struct inode *ip; + struct inode *ip; - for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) { - if (ip == NULL) - return (NULL); - if (inum == ip->i_number && device == ip->i_dev) - return (ITOV(ip)); - } - /* NOTREACHED */ + simple_lock(&ufs_ihash_slock); + for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) + if (inum == ip->i_number && dev == ip->i_dev) + break; + simple_unlock(&ufs_ihash_slock); + + if (ip) + return (ITOV(ip)); + return (NULLVP); } /* @@ -86,36 +90,28 @@ ufs_ihashlookup(device, inum) * to it. If it is in core, but locked, wait for it. */ struct vnode * -ufs_ihashget(device, inum) - dev_t device; +ufs_ihashget(dev, inum) + dev_t dev; ino_t inum; { - register struct inode *ip; + struct proc *p = curproc; /* XXX */ + struct inode *ip; struct vnode *vp; - for (;;) - for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) { - if (ip == NULL) - return (NULL); - if (inum == ip->i_number && device == ip->i_dev) { - if (ip->i_flag & IN_LOCKED) { - if( curproc->p_pid != ip->i_lockholder) { - ip->i_flag |= IN_WANTED; - (void) tsleep(ip, PINOD, "uihget", 0); - break; - } else if (ip->i_flag & IN_RECURSE) { - ip->i_lockcount++; - } else { - panic("ufs_ihashget: recursive lock not expected -- pid %d\n", ip->i_lockholder); - } - } - vp = ITOV(ip); - if (!vget(vp, 1)) - return (vp); - break; - } +loop: + simple_lock(&ufs_ihash_slock); + for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) { + if (inum == ip->i_number && dev == ip->i_dev) { + vp = ITOV(ip); + simple_lock(&vp->v_interlock); + simple_unlock(&ufs_ihash_slock); + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) + goto loop; + return (vp); } - /* NOTREACHED */ + } + simple_unlock(&ufs_ihash_slock); + return (NULL); } /* @@ -125,26 +121,16 @@ void ufs_ihashins(ip) struct inode *ip; { - struct inode **ipp, *iq; + struct proc *p = curproc; /* XXX */ + struct ihashhead *ipp; - ipp = &ihashtbl[INOHASH(ip->i_dev, ip->i_number)]; - iq = *ipp; - if (iq) - iq->i_prev = &ip->i_next; - ip->i_next = iq; - ip->i_prev = ipp; - *ipp = ip; - if ((ip->i_flag & IN_LOCKED) && - ((ip->i_flag & IN_RECURSE) == 0 || - (!curproc || (curproc && (ip->i_lockholder != curproc->p_pid))))) - panic("ufs_ihashins: already locked"); - if (curproc) { - ip->i_lockcount += 1; - ip->i_lockholder = curproc->p_pid; - } else { - ip->i_lockholder = -1; - } - ip->i_flag |= IN_LOCKED; + /* lock the inode, then put it on the appropriate hash list */ + lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p); + + simple_lock(&ufs_ihash_slock); + ipp = INOHASH(ip->i_dev, ip->i_number); + LIST_INSERT_HEAD(ipp, ip, i_hash); + simple_unlock(&ufs_ihash_slock); } /* @@ -152,16 +138,13 @@ ufs_ihashins(ip) */ void ufs_ihashrem(ip) - register struct inode *ip; + struct inode *ip; { - register struct inode *iq; - - iq = ip->i_next; - if (iq) - iq->i_prev = ip->i_prev; - *ip->i_prev = iq; + simple_lock(&ufs_ihash_slock); + LIST_REMOVE(ip, i_hash); #ifdef DIAGNOSTIC - ip->i_next = NULL; - ip->i_prev = NULL; + ip->i_hash.le_next = NULL; + ip->i_hash.le_prev = NULL; #endif + simple_unlock(&ufs_ihash_slock); } diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c index 45616bb..dd59142 100644 --- a/sys/ufs/ufs/ufs_inode.c +++ b/sys/ufs/ufs/ufs_inode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1991, 1993 + * Copyright (c) 1991, 1993, 1995 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_inode.c 8.4 (Berkeley) 1/21/94 + * @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95 * $FreeBSD$ */ @@ -57,24 +57,6 @@ u_long nextgennumber; /* Next generation number to assign. */ int prtactive = 0; /* 1 => print out reclaim of active vnodes */ -int -ufs_init() -{ - static int first = 1; - - if (!first) - return (0); - first = 0; - -#ifdef DIAGNOSTIC - if ((sizeof(struct inode) - 1) & sizeof(struct inode)) - printf("ufs_init: bad size %d\n", sizeof(struct inode)); -#endif - ufs_ihashinit(); - dqinit(); - return (0); -} - /* * Last reference to an inode. If necessary, write or delete it. */ @@ -82,39 +64,29 @@ int ufs_inactive(ap) struct vop_inactive_args /* { struct vnode *a_vp; + struct proc *a_p; } */ *ap; { - register struct vnode *vp = ap->a_vp; - register struct inode *ip = VTOI(vp); + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + struct proc *p = ap->a_p; struct timeval tv; - int mode, error; + int mode, error = 0; if (prtactive && vp->v_usecount != 0) vprint("ufs_inactive: pushing active", vp); - /* Get rid of inodes related to stale file handles. */ - if (ip->i_mode == 0) { - if ((vp->v_flag & VXLOCK) == 0) - vgone(vp); - return (0); - } - - error = 0; -#ifdef DIAGNOSTIC - if (VOP_ISLOCKED(vp)) - panic("ufs_inactive: locked inode"); - if (curproc) - ip->i_lockholder = curproc->p_pid; - else - ip->i_lockholder = -1; -#endif - ip->i_flag |= IN_LOCKED; + /* + * Ignore inodes related to stale file handles. + */ + if (ip->i_mode == 0) + goto out; if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { #ifdef QUOTA if (!getinoquota(ip)) (void)chkiq(ip, -1, NOCRED, 0); #endif - error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL); + error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, p); ip->i_rdev = 0; mode = ip->i_mode; ip->i_mode = 0; @@ -125,13 +97,14 @@ ufs_inactive(ap) tv = time; VOP_UPDATE(vp, &tv, &tv, 0); } - VOP_UNLOCK(vp); +out: + VOP_UNLOCK(vp, 0, p); /* * If we are done with the inode, reclaim it * so that it can be reused immediately. */ - if (vp->v_usecount == 0 && ip->i_mode == 0) - vgone(vp); + if (ip->i_mode == 0) + vrecycle(vp, (struct simplelock *)0, p); return (error); } @@ -139,14 +112,11 @@ ufs_inactive(ap) * Reclaim an inode so that it can be used for other purposes. */ int -ufs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; +ufs_reclaim(vp, p) + struct vnode *vp; + struct proc *p; { - register struct vnode *vp = ap->a_vp; register struct inode *ip; - int type; #ifdef QUOTA int i; #endif @@ -174,23 +144,5 @@ ufs_reclaim(ap) } } #endif - switch (vp->v_mount->mnt_stat.f_type) { - case MOUNT_EXT2FS: - type = M_FFSNODE; - break; - case MOUNT_UFS: - type = M_FFSNODE; - break; - case MOUNT_MFS: - type = M_MFSNODE; - break; - case MOUNT_LFS: - type = M_LFSNODE; - break; - default: - panic("ufs_reclaim: not ufs file"); - } - FREE(vp->v_data, type); - vp->v_data = NULL; return (0); } diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 4b99584..38fe929 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 + * @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95 * $FreeBSD$ */ @@ -128,6 +128,7 @@ ufs_lookup(ap) struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; int nameiop = cnp->cn_nameiop; + struct proc *p = cnp->cn_proc; bp = NULL; slotoffset = -1; @@ -175,14 +176,14 @@ ufs_lookup(ap) VREF(vdp); error = 0; } else if (flags & ISDOTDOT) { - VOP_UNLOCK(pdp); - error = vget(vdp, 1); + VOP_UNLOCK(pdp, 0, p); + error = vget(vdp, LK_EXCLUSIVE, p); if (!error && lockparent && (flags & ISLASTCN)) - error = VOP_LOCK(pdp); + error = vn_lock(pdp, LK_EXCLUSIVE, p); } else { - error = vget(vdp, 1); + error = vget(vdp, LK_EXCLUSIVE, p); if (!lockparent || error || !(flags & ISLASTCN)) - VOP_UNLOCK(pdp); + VOP_UNLOCK(pdp, 0, p); } /* * Check that the capability number did not change @@ -193,10 +194,9 @@ ufs_lookup(ap) return (0); vput(vdp); if (lockparent && pdp != vdp && (flags & ISLASTCN)) - VOP_UNLOCK(pdp); + VOP_UNLOCK(pdp, 0, p); } - error = VOP_LOCK(pdp); - if (error) + if (error = vn_lock(pdp, LK_EXCLUSIVE, p)) return (error); vdp = pdp; dp = VTOI(pdp); @@ -337,6 +337,17 @@ searchloop: * reclen in ndp->ni_ufs area, and release * directory buffer. */ + if (vdp->v_mount->mnt_maxsymlinklen > 0 && + ep->d_type == DT_WHT) { + slotstatus = FOUND; + slotoffset = dp->i_offset; + slotsize = ep->d_reclen; + dp->i_reclen = slotsize; + enduseful = dp->i_size; + ap->a_cnp->cn_flags |= ISWHITEOUT; + numdirpasses--; + goto notfound; + } dp->i_ino = ep->d_ino; dp->i_reclen = ep->d_reclen; brelse(bp); @@ -349,7 +360,7 @@ searchloop: if (ep->d_ino) enduseful = dp->i_offset; } -/* notfound: */ +notfound: /* * If we started in the middle of the directory and failed * to find our target, we must check the beginning as well. @@ -367,7 +378,10 @@ searchloop: * directory has not been removed, then can consider * allowing file to be created. */ - if ((nameiop == CREATE || nameiop == RENAME) && + if ((nameiop == CREATE || nameiop == RENAME || + (nameiop == DELETE && + (ap->a_cnp->cn_flags & DOWHITEOUT) && + (ap->a_cnp->cn_flags & ISWHITEOUT))) && (flags & ISLASTCN) && dp->i_nlink != 0) { /* * Access for write is interpreted as allowing @@ -389,6 +403,12 @@ searchloop: dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ); dp->i_count = 0; enduseful = dp->i_offset; + } else if (nameiop == DELETE) { + dp->i_offset = slotoffset; + if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) + dp->i_count = 0; + else + dp->i_count = dp->i_offset - prevoff; } else { dp->i_offset = slotoffset; dp->i_count = slotsize; @@ -412,7 +432,7 @@ searchloop: */ cnp->cn_flags |= SAVENAME; if (!lockparent) - VOP_UNLOCK(vdp); + VOP_UNLOCK(vdp, 0, p); return (EJUSTRETURN); } /* @@ -484,13 +504,14 @@ found: if ((dp->i_mode & ISVTX) && cred->cr_uid != 0 && cred->cr_uid != dp->i_uid && + tdp->v_type != VLNK && VTOI(tdp)->i_uid != cred->cr_uid) { vput(tdp); return (EPERM); } *vpp = tdp; if (!lockparent) - VOP_UNLOCK(vdp); + VOP_UNLOCK(vdp, 0, p); return (0); } @@ -500,10 +521,8 @@ found: * Must get inode of directory entry to verify it's a * regular file, or empty directory. */ - if (nameiop == RENAME && wantparent && - (flags & ISLASTCN)) { - error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc); - if (error) + if (nameiop == RENAME && wantparent && (flags & ISLASTCN)) { + if (error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) return (error); /* * Careful about locking second inode. @@ -517,7 +536,7 @@ found: *vpp = tdp; cnp->cn_flags |= SAVENAME; if (!lockparent) - VOP_UNLOCK(vdp); + VOP_UNLOCK(vdp, 0, p); return (0); } @@ -542,14 +561,13 @@ found: */ pdp = vdp; if (flags & ISDOTDOT) { - VOP_UNLOCK(pdp); /* race to get the inode */ - error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); - if (error) { - VOP_LOCK(pdp); + VOP_UNLOCK(pdp, 0, p); /* race to get the inode */ + if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) { + vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p); return (error); } if (lockparent && (flags & ISLASTCN) && - (error = VOP_LOCK(pdp))) { + (error = vn_lock(pdp, LK_EXCLUSIVE, p))) { vput(tdp); return (error); } @@ -562,7 +580,7 @@ found: if (error) return (error); if (!lockparent || !(flags & ISLASTCN)) - VOP_UNLOCK(pdp); + VOP_UNLOCK(pdp, 0, p); *vpp = tdp; } @@ -621,6 +639,8 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock) printf("First bad\n"); goto bad; } + if (ep->d_ino == 0) + return (0); for (i = 0; i < namlen; i++) if (ep->d_name[i] == '\0') { /*return (1); */ @@ -629,9 +649,9 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock) } if (ep->d_name[i]) goto bad; - return (ep->d_name[i]); + return (0); bad: - return(1); + return (1); } /* @@ -648,15 +668,8 @@ ufs_direnter(ip, dvp, cnp) struct vnode *dvp; register struct componentname *cnp; { - register struct direct *ep, *nep; register struct inode *dp; - struct buf *bp; struct direct newdir; - struct iovec aiov; - struct uio auio; - u_int dsize; - int error, loc, newentrysize, spacefree; - char *dirbuf; #ifdef DIAGNOSTIC if ((cnp->cn_flags & SAVENAME) == 0) @@ -676,7 +689,33 @@ ufs_direnter(ip, dvp, cnp) newdir.d_type = tmp; } # endif } - newentrysize = DIRSIZ(OFSFMT(dvp), &newdir); + return (ufs_direnter2(dvp, &newdir, cnp->cn_cred, cnp->cn_proc)); +} + +/* + * Common entry point for directory entry removal used by ufs_direnter + * and ufs_whiteout + */ +int +ufs_direnter2(dvp, dirp, cr, p) + struct vnode *dvp; + struct direct *dirp; + struct ucred *cr; + struct proc *p; +{ + int newentrysize; + struct inode *dp; + struct buf *bp; + struct iovec aiov; + struct uio auio; + u_int dsize; + struct direct *ep, *nep; + int error, loc, spacefree; + char *dirbuf; + + dp = VTOI(dvp); + newentrysize = DIRSIZ(OFSFMT(dvp), dirp); + if (dp->i_count == 0) { /* * If dp->i_count is 0, then namei could find no @@ -685,22 +724,22 @@ ufs_direnter(ip, dvp, cnp) * new entry into a fresh block. */ if (dp->i_offset & (DIRBLKSIZ - 1)) - panic("ufs_direnter: newblk"); + panic("ufs_direnter2: newblk"); auio.uio_offset = dp->i_offset; - newdir.d_reclen = DIRBLKSIZ; + dirp->d_reclen = DIRBLKSIZ; auio.uio_resid = newentrysize; aiov.iov_len = newentrysize; - aiov.iov_base = (caddr_t)&newdir; + aiov.iov_base = (caddr_t)dirp; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_WRITE; auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = (struct proc *)0; - error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred); + error = VOP_WRITE(dvp, &auio, IO_SYNC, cr); if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) /* XXX should grow with balloc() */ - panic("ufs_direnter: frag size"); + panic("ufs_direnter2: frag size"); else if (!error) { dp->i_size = roundup2(dp->i_size, DIRBLKSIZ); dp->i_flag |= IN_CHANGE; @@ -761,18 +800,20 @@ ufs_direnter(ip, dvp, cnp) * Update the pointer fields in the previous entry (if any), * copy in the new entry, and write out the block. */ - if (ep->d_ino == 0) { + if (ep->d_ino == 0 || + (ep->d_ino == WINO && + bcmp(ep->d_name, dirp->d_name, dirp->d_namlen) == 0)) { if (spacefree + dsize < newentrysize) - panic("ufs_direnter: compact1"); - newdir.d_reclen = spacefree + dsize; + panic("ufs_direnter2: compact1"); + dirp->d_reclen = spacefree + dsize; } else { if (spacefree < newentrysize) - panic("ufs_direnter: compact2"); - newdir.d_reclen = spacefree; + panic("ufs_direnter2: compact2"); + dirp->d_reclen = spacefree; ep->d_reclen = dsize; ep = (struct direct *)((char *)ep + dsize); } - bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize); + bcopy((caddr_t)dirp, (caddr_t)ep, (u_int)newentrysize); if (dvp->v_mount->mnt_flag & MNT_ASYNC) { bdwrite(bp); @@ -782,8 +823,7 @@ ufs_direnter(ip, dvp, cnp) } dp->i_flag |= IN_CHANGE | IN_UPDATE; if (!error && dp->i_endoff && dp->i_endoff < dp->i_size) - error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, - cnp->cn_cred, cnp->cn_proc); + error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr, p); return (error); } @@ -810,6 +850,21 @@ ufs_dirremove(dvp, cnp) int error; dp = VTOI(dvp); + + if (cnp->cn_flags & DOWHITEOUT) { + /* + * Whiteout entry: set d_ino to WINO. + */ + if (error = + VOP_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp)) + return (error); + ep->d_ino = WINO; + ep->d_type = DT_WHT; + error = VOP_BWRITE(bp); + dp->i_flag |= IN_CHANGE | IN_UPDATE; + return (error); + } + if (dp->i_count == 0) { /* * First entry in block: set d_ino to zero. @@ -906,7 +961,7 @@ ufs_dirempty(ip, parentino, cred) if (dp->d_reclen == 0) return (0); /* skip empty entries */ - if (dp->d_ino == 0) + if (dp->d_ino == 0 || dp->d_ino == WINO) continue; /* accept only "." and ".." */ # if (BYTE_ORDER == LITTLE_ENDIAN) diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 88d659d..6d69a98 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1982, 1986, 1990, 1993 + * Copyright (c) 1982, 1986, 1990, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_quota.c 8.2 (Berkeley) 12/30/93 + * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 * $FreeBSD$ */ @@ -379,8 +379,8 @@ quotaon(p, mp, type, fname) register int type; caddr_t fname; { - register struct ufsmount *ump = VFSTOUFS(mp); - register struct vnode *vp, **vpp; + struct ufsmount *ump = VFSTOUFS(mp); + struct vnode *vp, **vpp; struct vnode *nextvp; struct dquot *dq; int error; @@ -392,15 +392,11 @@ quotaon(p, mp, type, fname) if (error) return (error); vp = nd.ni_vp; - VOP_UNLOCK(vp); + VOP_UNLOCK(vp, 0, p); if (vp->v_type != VREG) { (void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p); return (EACCES); } - if (vfs_busy(mp)) { - (void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p); - return (EBUSY); - } if (*vpp != vp) quotaoff(p, mp, type); ump->um_qflags[type] |= QTF_OPENING; @@ -432,7 +428,7 @@ again: nextvp = vp->v_mntvnodes.le_next; if (vp->v_writecount == 0) continue; - if (vget(vp, 1)) + if (vget(vp, LK_EXCLUSIVE, p)) goto again; error = getinoquota(VTOI(vp)); if (error) { @@ -446,7 +442,6 @@ again: ump->um_qflags[type] &= ~QTF_OPENING; if (error) quotaoff(p, mp, type); - vfs_unbusy(mp); return (error); } @@ -459,15 +454,13 @@ quotaoff(p, mp, type) struct mount *mp; register int type; { - register struct vnode *vp; + struct vnode *vp; struct vnode *qvp, *nextvp; struct ufsmount *ump = VFSTOUFS(mp); - register struct dquot *dq; - register struct inode *ip; + struct dquot *dq; + struct inode *ip; int error; - if ((mp->mnt_flag & MNT_MPBUSY) == 0) - panic("quotaoff: not busy"); if ((qvp = ump->um_quotas[type]) == NULLVP) return (0); ump->um_qflags[type] |= QTF_CLOSING; @@ -478,7 +471,7 @@ quotaoff(p, mp, type) again: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) { nextvp = vp->v_mntvnodes.le_next; - if (vget(vp, 1)) + if (vget(vp, LK_EXCLUSIVE, p)) goto again; ip = VTOI(vp); dq = ip->i_dquot[type]; @@ -641,16 +634,15 @@ qsync(mp) struct mount *mp; { struct ufsmount *ump = VFSTOUFS(mp); - register struct vnode *vp, *nextvp; - register struct dquot *dq; - register int i; + struct proc *p = curproc; /* XXX */ + struct vnode *vp, *nextvp; + struct dquot *dq; + int i, error; /* * Check if the mount point has any quotas. * If not, simply return. */ - if ((mp->mnt_flag & MNT_MPBUSY) == 0) - panic("qsync: not busy"); for (i = 0; i < MAXQUOTAS; i++) if (ump->um_quotas[i] != NULLVP) break; @@ -660,36 +652,48 @@ qsync(mp) * Search vnodes associated with this mount point, * synchronizing any modified dquot structures. */ + simple_lock(&mntvnode_slock); again: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) { + if (vp->v_mount != mp) + goto again; nextvp = vp->v_mntvnodes.le_next; - if (VOP_ISLOCKED(vp)) + simple_lock(&vp->v_interlock); + simple_unlock(&mntvnode_slock); + error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); + if (error) { + simple_lock(&mntvnode_slock); + if (error == ENOENT) + goto again; continue; - if (vget(vp, 1)) - goto again; + } for (i = 0; i < MAXQUOTAS; i++) { dq = VTOI(vp)->i_dquot[i]; if (dq != NODQUOT && (dq->dq_flags & DQ_MOD)) dqsync(vp, dq); } vput(vp); - if (vp->v_mntvnodes.le_next != nextvp || vp->v_mount != mp) + simple_lock(&mntvnode_slock); + if (vp->v_mntvnodes.le_next != nextvp) goto again; } + simple_unlock(&mntvnode_slock); return (0); } /* * Code pertaining to management of the in-core dquot data structures. */ -static struct dquot **dqhashtbl; +#define DQHASH(dqvp, id) \ + (&dqhashtbl[((((int)(dqvp)) >> 8) + id) & dqhash]) +static LIST_HEAD(dqhash, dquot) *dqhashtbl; static u_long dqhash; /* * Dquot free list. */ #define DQUOTINC 5 /* minimum free dquots desired */ -static struct dquot *dqfreel, **dqback = &dqfreel; +TAILQ_HEAD(dqfreelist, dquot) dqfreelist; static long numdquot, desireddquot = DQUOTINC; /* @@ -700,6 +704,7 @@ dqinit() { dqhashtbl = hashinit(desiredvnodes, M_DQUOT, &dqhash); + TAILQ_INIT(&dqfreelist); } /* @@ -714,8 +719,10 @@ dqget(vp, id, ump, type, dqp) register int type; struct dquot **dqp; { - register struct dquot *dq, *dp, **dpp; - register struct vnode *dqvp; + struct proc *p = curproc; /* XXX */ + struct dquot *dq; + struct dqhash *dqh; + struct vnode *dqvp; struct iovec aiov; struct uio auio; int error; @@ -728,8 +735,8 @@ dqget(vp, id, ump, type, dqp) /* * Check the cache first. */ - dpp = &dqhashtbl[((((int)(dqvp)) >> 8) + id) & dqhash]; - for (dq = *dpp; dq; dq = dq->dq_forw) { + dqh = DQHASH(dqvp, id); + for (dq = dqh->lh_first; dq; dq = dq->dq_hash.le_next) { if (dq->dq_id != id || dq->dq_ump->um_quotas[dq->dq_type] != dqvp) continue; @@ -737,13 +744,8 @@ dqget(vp, id, ump, type, dqp) * Cache hit with no references. Take * the structure off the free list. */ - if (dq->dq_cnt == 0) { - if ((dp = dq->dq_freef) != NODQUOT) - dp->dq_freeb = dq->dq_freeb; - else - dqback = dq->dq_freeb; - *dq->dq_freeb = dp; - } + if (dq->dq_cnt == 0) + TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); DQREF(dq); *dqp = dq; return (0); @@ -751,43 +753,30 @@ dqget(vp, id, ump, type, dqp) /* * Not in cache, allocate a new one. */ - if (dqfreel == NODQUOT && numdquot < MAXQUOTAS * desiredvnodes) + if (dqfreelist.tqh_first == NODQUOT && + numdquot < MAXQUOTAS * desiredvnodes) desireddquot += DQUOTINC; if (numdquot < desireddquot) { dq = (struct dquot *)malloc(sizeof *dq, M_DQUOT, M_WAITOK); bzero((char *)dq, sizeof *dq); numdquot++; } else { - if ((dq = dqfreel) == NULL) { + if ((dq = dqfreelist.tqh_first) == NULL) { tablefull("dquot"); *dqp = NODQUOT; return (EUSERS); } if (dq->dq_cnt || (dq->dq_flags & DQ_MOD)) panic("free dquot isn't"); - if ((dp = dq->dq_freef) != NODQUOT) - dp->dq_freeb = &dqfreel; - else - dqback = &dqfreel; - dqfreel = dp; - dq->dq_freef = NULL; - dq->dq_freeb = NULL; - dp = dq->dq_forw; - if (dp) - dp->dq_back = dq->dq_back; - *dq->dq_back = dp; + TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); + LIST_REMOVE(dq, dq_hash); } /* * Initialize the contents of the dquot structure. */ if (vp != dqvp) - VOP_LOCK(dqvp); - dp = *dpp; - if (dp) - dp->dq_back = &dq->dq_forw; - dq->dq_forw = dp; - dq->dq_back = dpp; - *dpp = dq; + vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p); + LIST_INSERT_HEAD(dqh, dq, dq_hash); DQREF(dq); dq->dq_flags = DQ_LOCK; dq->dq_id = id; @@ -806,7 +795,7 @@ dqget(vp, id, ump, type, dqp) if (auio.uio_resid == sizeof(struct dqblk) && error == 0) bzero((caddr_t)&dq->dq_dqb, sizeof(struct dqblk)); if (vp != dqvp) - VOP_UNLOCK(dqvp); + VOP_UNLOCK(dqvp, 0, p); if (dq->dq_flags & DQ_WANT) wakeup((caddr_t)dq); dq->dq_flags = 0; @@ -815,12 +804,7 @@ dqget(vp, id, ump, type, dqp) * quota structure and reflect problem to caller. */ if (error) { - dp = dq->dq_forw; - if (dp) - dp->dq_back = dq->dq_back; - *dq->dq_back = dp; - dq->dq_forw = NULL; - dq->dq_back = NULL; + LIST_REMOVE(dq, dq_hash); dqrele(vp, dq); *dqp = NODQUOT; return (error); @@ -874,15 +858,7 @@ dqrele(vp, dq) (void) dqsync(vp, dq); if (--dq->dq_cnt > 0) return; - if (dqfreel != NODQUOT) { - *dqback = dq; - dq->dq_freeb = dqback; - } else { - dqfreel = dq; - dq->dq_freeb = &dqfreel; - } - dq->dq_freef = NODQUOT; - dqback = &dq->dq_freef; + TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist); } /* @@ -891,8 +867,9 @@ dqrele(vp, dq) static int dqsync(vp, dq) struct vnode *vp; - register struct dquot *dq; + struct dquot *dq; { + struct proc *p = curproc; /* XXX */ struct vnode *dqvp; struct iovec aiov; struct uio auio; @@ -905,13 +882,13 @@ dqsync(vp, dq) if ((dqvp = dq->dq_ump->um_quotas[dq->dq_type]) == NULLVP) panic("dqsync: file"); if (vp != dqvp) - VOP_LOCK(dqvp); + vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p); while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; (void) tsleep((caddr_t)dq, PINOD+2, "dqsync", 0); if ((dq->dq_flags & DQ_MOD) == 0) { if (vp != dqvp) - VOP_UNLOCK(dqvp); + VOP_UNLOCK(dqvp, 0, p); return (0); } } @@ -932,7 +909,7 @@ dqsync(vp, dq) wakeup((caddr_t)dq); dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT); if (vp != dqvp) - VOP_UNLOCK(dqvp); + VOP_UNLOCK(dqvp, 0, p); return (error); } @@ -943,26 +920,22 @@ static void dqflush(vp) register struct vnode *vp; { - register struct dquot *dq, *dp, **dpp, *nextdq; + register struct dquot *dq, *nextdq; + struct dqhash *dqh; /* * Move all dquot's that used to refer to this quota * file off their hash chains (they will eventually * fall off the head of the free list and be re-used). */ - for (dpp = &dqhashtbl[dqhash]; dpp >= dqhashtbl; dpp--) { - for (dq = *dpp; dq; dq = nextdq) { - nextdq = dq->dq_forw; + for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) { + for (dq = dqh->lh_first; dq; dq = nextdq) { + nextdq = dq->dq_hash.le_next; if (dq->dq_ump->um_quotas[dq->dq_type] != vp) continue; if (dq->dq_cnt) panic("dqflush: stray dquot"); - dp = dq->dq_forw; - if (dp) - dp->dq_back = dq->dq_back; - *dq->dq_back = dp; - dq->dq_forw = NULL; - dq->dq_back = NULL; + LIST_REMOVE(dq, dq_hash); dq->dq_ump = (struct ufsmount *)0; } } diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c index 99497e6..c83ba17 100644 --- a/sys/ufs/ufs/ufs_readwrite.c +++ b/sys/ufs/ufs/ufs_readwrite.c @@ -30,12 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_readwrite.c 8.7 (Berkeley) 1/21/94 + * @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95 * $FreeBSD$ */ #ifdef LFS_READWRITE -#define BLKSIZE(a, b, c) blksize(a) +#define BLKSIZE(a, b, c) blksize(a, b, c) #define FS struct lfs #define I_FS i_lfs #define READ lfs_read @@ -75,7 +75,7 @@ READ(ap) register struct uio *uio; register FS *fs; struct buf *bp; - daddr_t lbn, nextlbn; + ufs_daddr_t lbn, nextlbn; off_t bytesinfile; long size, xfersize, blkoffset; int error; @@ -99,7 +99,7 @@ READ(ap) panic("%s: type %d", READ_S, vp->v_type); #endif fs = ip->I_FS; - if ((u_quad_t)uio->uio_offset > fs->fs_maxfilesize) + if ((u_int64_t)uio->uio_offset > fs->fs_maxfilesize) return (EFBIG); for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { @@ -189,7 +189,7 @@ WRITE(ap) register FS *fs; struct buf *bp; struct proc *p; - daddr_t lbn; + ufs_daddr_t lbn; off_t osize; int blkoffset, error, flags, ioflag, resid, size, xfersize; struct timeval tv; @@ -223,7 +223,7 @@ WRITE(ap) fs = ip->I_FS; if (uio->uio_offset < 0 || - (u_quad_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize) + (u_int64_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize) return (EFBIG); /* * Maybe this should be above the vnode op call, but so long as @@ -253,7 +253,7 @@ WRITE(ap) #ifdef LFS_READWRITE (void)lfs_check(vp, lbn); - error = lfs_balloc(vp, xfersize, lbn, &bp); + error = lfs_balloc(vp, blkoffset, xfersize, lbn, &bp); #else if (fs->fs_bsize > xfersize) flags |= B_CLRBUF; diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c index 7ae2a27..a0d6af5 100644 --- a/sys/ufs/ufs/ufs_vfsops.c +++ b/sys/ufs/ufs/ufs_vfsops.c @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_vfsops.c 8.4 (Berkeley) 4/16/94 + * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95 * $FreeBSD$ */ @@ -57,11 +57,6 @@ #include /* - * Flag to permit forcible unmounting. - */ -int doforce = 1; - -/* * Make a filesystem operational. * Nothing to do at the moment. */ @@ -129,40 +124,61 @@ ufs_quotactl(mp, cmds, uid, arg, p) type = cmds & SUBCMDMASK; if ((u_int)type >= MAXQUOTAS) return (EINVAL); + if (vfs_busy(mp, LK_NOWAIT, 0, p)) + return (0); switch (cmd) { case Q_QUOTAON: - return (quotaon(p, mp, type, arg)); + error = quotaon(p, mp, type, arg); + break; case Q_QUOTAOFF: - if (vfs_busy(mp)) - return (0); error = quotaoff(p, mp, type); - vfs_unbusy(mp); - return (error); + break; case Q_SETQUOTA: - return (setquota(mp, uid, type, arg)); + error = setquota(mp, uid, type, arg); + break; case Q_SETUSE: - return (setuse(mp, uid, type, arg)); + error = setuse(mp, uid, type, arg); + break; case Q_GETQUOTA: - return (getquota(mp, uid, type, arg)); + error = getquota(mp, uid, type, arg); + break; case Q_SYNC: - if (vfs_busy(mp)) - return (0); error = qsync(mp); - vfs_unbusy(mp); - return (error); + break; default: - return (EINVAL); + error = EINVAL; + break; } - /* NOTREACHED */ + vfs_unbusy(mp, p); + return (error); +#endif +} + +/* + * Initial UFS filesystems, done only once. + */ +int +ufs_init(vfsp) + struct vfsconf *vfsp; +{ + static int done; + + if (done) + return (0); + done = 1; + ufs_ihashinit(); +#ifdef QUOTA + dqinit(); #endif + return (0); } /* diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index edc022f..66527c1 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1982, 1986, 1989, 1993 + * Copyright (c) 1982, 1986, 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed @@ -35,7 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_vnops.c 8.10 (Berkeley) 4/1/94 + * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 * $FreeBSD$ */ @@ -80,8 +80,8 @@ static int ufs_chown #endif /* EXT2FS */ union _qcvt { - quad_t qcvt; - long val[2]; + int64_t qcvt; + int32_t val[2]; }; #define SETHIGH(q, h) { \ union _qcvt tmp; \ @@ -204,8 +204,10 @@ ufs_close(ap) register struct vnode *vp = ap->a_vp; register struct inode *ip = VTOI(vp); - if (vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) + simple_lock(&vp->v_interlock); + if (vp->v_usecount > 1) ITIMES(ip, &time, &time); + simple_unlock(&vp->v_interlock); return (0); } @@ -317,9 +319,12 @@ ufs_getattr(ap) vap->va_gid = ip->i_gid; vap->va_rdev = (dev_t)ip->i_rdev; vap->va_size = ip->i_din.di_size; - vap->va_atime = ip->i_atime; - vap->va_mtime = ip->i_mtime; - vap->va_ctime = ip->i_ctime; + vap->va_atime.tv_sec = ip->i_atime; + vap->va_atime.tv_nsec = ip->i_atimensec; + vap->va_mtime.tv_sec = ip->i_mtime; + vap->va_mtime.tv_nsec = ip->i_mtimensec; + vap->va_ctime.tv_sec = ip->i_ctime; + vap->va_ctime.tv_nsec = ip->i_ctimensec; vap->va_flags = ip->i_flags; vap->va_gen = ip->i_gen; /* this doesn't belong here */ @@ -329,7 +334,7 @@ ufs_getattr(ap) vap->va_blocksize = MAXBSIZE; else vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; - vap->va_bytes = dbtob(ip->i_blocks); + vap->va_bytes = dbtob((u_quad_t)ip->i_blocks); vap->va_type = vp->v_type; vap->va_filerev = ip->i_modrev; return (0); @@ -376,7 +381,8 @@ ufs_setattr(ap) return (EPERM); ip->i_flags = vap->va_flags; } else { - if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) + if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND) || + (vap->va_flags & UF_SETTABLE) != vap->va_flags) return (EPERM); ip->i_flags &= SF_SETTABLE; ip->i_flags |= (vap->va_flags & UF_SETTABLE); @@ -393,8 +399,7 @@ ufs_setattr(ap) if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p); - if (error) + if (error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p)) return (error); } if (vap->va_size != VNOVAL) { @@ -412,8 +417,7 @@ ufs_setattr(ap) return (EROFS); break; } - error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p); - if (error) + if (error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p)) return (error); } ip = VTOI(vp); @@ -711,6 +715,7 @@ ufs_link(ap) struct vnode *vp = ap->a_vp; struct vnode *tdvp = ap->a_tdvp; struct componentname *cnp = ap->a_cnp; + struct proc *p = cnp->cn_proc; struct inode *ip; struct timeval tv; int error; @@ -719,12 +724,12 @@ ufs_link(ap) if ((cnp->cn_flags & HASBUF) == 0) panic("ufs_link: no name"); #endif - if (vp->v_mount != tdvp->v_mount) { + if (tdvp->v_mount != vp->v_mount) { VOP_ABORTOP(tdvp, cnp); error = EXDEV; goto out2; } - if (vp != tdvp && (error = VOP_LOCK(vp))) { + if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) { VOP_ABORTOP(tdvp, cnp); goto out2; } @@ -761,13 +766,69 @@ ufs_link(ap) } FREE(cnp->cn_pnbuf, M_NAMEI); out1: - if (vp != tdvp) - VOP_UNLOCK(vp); + if (tdvp != vp) + VOP_UNLOCK(vp, 0, p); out2: vput(tdvp); return (error); } +/* + * whiteout vnode call + */ +int +ufs_whiteout(ap) + struct vop_whiteout_args /* { + struct vnode *a_dvp; + struct componentname *a_cnp; + int a_flags; + } */ *ap; +{ + struct vnode *dvp = ap->a_dvp; + struct componentname *cnp = ap->a_cnp; + struct direct newdir; + int error = 0; + + switch (ap->a_flags) { + case LOOKUP: + /* 4.4 format directories support whiteout operations */ + if (dvp->v_mount->mnt_maxsymlinklen > 0) + return (0); + return (EOPNOTSUPP); + + case CREATE: + /* create a new directory whiteout */ +#ifdef DIAGNOSTIC + if ((cnp->cn_flags & SAVENAME) == 0) + panic("ufs_whiteout: missing name"); + if (dvp->v_mount->mnt_maxsymlinklen <= 0) + panic("ufs_whiteout: old format filesystem"); +#endif + + newdir.d_ino = WINO; + newdir.d_namlen = cnp->cn_namelen; + bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1); + newdir.d_type = DT_WHT; + error = ufs_direnter2(dvp, &newdir, cnp->cn_cred, cnp->cn_proc); + break; + + case DELETE: + /* remove an existing directory whiteout */ +#ifdef DIAGNOSTIC + if (dvp->v_mount->mnt_maxsymlinklen <= 0) + panic("ufs_whiteout: old format filesystem"); +#endif + + cnp->cn_flags &= ~DOWHITEOUT; + error = ufs_dirremove(dvp, cnp); + break; + } + if (cnp->cn_flags & HASBUF) { + FREE(cnp->cn_pnbuf, M_NAMEI); + cnp->cn_flags &= ~HASBUF; + } + return (error); +} /* * Rename system call. @@ -810,6 +871,7 @@ ufs_rename(ap) struct vnode *fdvp = ap->a_fdvp; struct componentname *tcnp = ap->a_tcnp; struct componentname *fcnp = ap->a_fcnp; + struct proc *p = fcnp->cn_proc; struct inode *ip, *xp, *dp; struct dirtemplate dirbuf; struct timeval tv; @@ -899,13 +961,12 @@ abortit: } return (VOP_REMOVE(fdvp, fvp, fcnp)); } - error = VOP_LOCK(fvp); - if (error) + if (error = vn_lock(fvp, LK_EXCLUSIVE, p)) goto abortit; dp = VTOI(fdvp); ip = VTOI(fvp); if ((ip->i_flags & (IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) { - VOP_UNLOCK(fvp); + VOP_UNLOCK(fvp, 0, p); error = EPERM; goto abortit; } @@ -916,7 +977,7 @@ abortit: if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT || (ip->i_flag & IN_RENAME)) { - VOP_UNLOCK(fvp); + VOP_UNLOCK(fvp, 0, p); error = EINVAL; goto abortit; } @@ -944,9 +1005,8 @@ abortit: ip->i_nlink++; ip->i_flag |= IN_CHANGE; tv = time; - error = VOP_UPDATE(fvp, &tv, &tv, 1); - if (error) { - VOP_UNLOCK(fvp); + if (error = VOP_UPDATE(fvp, &tv, &tv, 1)) { + VOP_UNLOCK(fvp, 0, p); goto bad; } @@ -961,7 +1021,7 @@ abortit: * call to checkpath(). */ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); - VOP_UNLOCK(fvp); + VOP_UNLOCK(fvp, 0, p); if (oldparent != dp->i_number) newparent = dp->i_number; if (doingdirectory && newparent) { @@ -1235,7 +1295,9 @@ bad: vput(ITOV(xp)); vput(ITOV(dp)); out: - if (VOP_LOCK(fvp) == 0) { + if (doingdirectory) + ip->i_flag &= ~IN_RENAME; + if (vn_lock(fvp, LK_EXCLUSIVE, p) == 0) { ip->i_nlink--; ip->i_flag |= IN_CHANGE; ip->i_flag &= ~IN_RENAME; @@ -1314,6 +1376,8 @@ ufs_mkdir(ap) ip->i_mode = dmode; tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ ip->i_nlink = 2; + if (cnp->cn_flags & ISWHITEOUT) + ip->i_flags |= UF_OPAQUE; tv = time; error = VOP_UPDATE(tvp, &tv, &tv, 1); @@ -1545,13 +1609,15 @@ ufs_readdir(ap) struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; - int *a_ncookies; - u_int **cookies; + int *a_eofflag; + int *ncookies; + u_long **a_cookies; } */ *ap; { register struct uio *uio = ap->a_uio; + int error; + size_t count, lost; off_t off; - int count, lost, error; if (ap->a_ncookies != NULL) /* @@ -1561,10 +1627,11 @@ ufs_readdir(ap) uio->uio_offset &= ~(DIRBLKSIZ - 1); off = uio->uio_offset; count = uio->uio_resid; - count &= ~(DIRBLKSIZ - 1); - lost = uio->uio_resid - count; - if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1))) + /* Make sure we don't return partial entries. */ + count -= (uio->uio_offset + count) & (DIRBLKSIZ -1); + if (count <= 0) return (EINVAL); + lost = uio->uio_resid - count; uio->uio_resid = count; uio->uio_iov->iov_len = count; # if (BYTE_ORDER == LITTLE_ENDIAN) @@ -1614,8 +1681,8 @@ ufs_readdir(ap) struct dirent* dpEnd; struct dirent* dp; int ncookies; - u_int *cookies; - u_int *cookiep; + u_long *cookies; + u_long *cookiep; if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) panic("ufs_readdir: unexpected uio from NFS server"); @@ -1626,20 +1693,20 @@ ufs_readdir(ap) dp < dpEnd; dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) ncookies++; - MALLOC(cookies, u_int *, ncookies * sizeof(u_int), - M_TEMP, M_WAITOK); + MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, + M_WAITOK); for (dp = dpStart, cookiep = cookies; dp < dpEnd; dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) { off += dp->d_reclen; - *cookiep++ = (u_int) off; + *cookiep++ = (u_long) off; } *ap->a_ncookies = ncookies; *ap->a_cookies = cookies; } + uio->uio_resid += lost; if (ap->a_eofflag) *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; - uio->uio_resid += lost; return (error); } @@ -1691,95 +1758,31 @@ int ufs_lock(ap) struct vop_lock_args /* { struct vnode *a_vp; + int a_flags; + struct proc *a_p; } */ *ap; { - struct proc *p = curproc; - register struct vnode *vp = ap->a_vp; - register struct inode *ip; - -start: - while (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - (void) tsleep((caddr_t)vp, PINOD, "ufslk1", 0); - } - if (vp->v_tag == VT_NON) - return (ENOENT); - ip = VTOI(vp); - if (ip->i_flag & IN_LOCKED) { - if (p->p_pid == ip->i_lockholder) { - if( (ip->i_flag & IN_RECURSE) == 0) - panic("ufs_lock: recursive lock not expected, pid: %d\n", - ip->i_lockholder); - } else { - ip->i_flag |= IN_WANTED; -#ifdef DIAGNOSTIC - if (p) - ip->i_lockwaiter = p->p_pid; - else - ip->i_lockwaiter = -1; -#endif - (void) tsleep((caddr_t)ip, PINOD, "ufslk2", 0); - goto start; - } - } -#ifdef DIAGNOSTIC - ip->i_lockwaiter = 0; - if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0)) - panic("lockholder (%d) != 0", ip->i_lockholder); - if (p && p->p_pid == 0) - printf("locking by process 0\n"); -#endif - - if ((ip->i_flag & IN_RECURSE) == 0) - ip->i_lockcount = 1; - else - ++ip->i_lockcount; + struct vnode *vp = ap->a_vp; - if (p) - ip->i_lockholder = p->p_pid; - else - ip->i_lockholder = -1; - ip->i_flag |= IN_LOCKED; - return (0); + return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock, + ap->a_p)); } /* - * Unlock an inode. If WANT bit is on, wakeup. + * Unlock an inode. */ -int lockcount = 90; int ufs_unlock(ap) struct vop_unlock_args /* { struct vnode *a_vp; + int a_flags; + struct proc *a_p; } */ *ap; { - register struct inode *ip = VTOI(ap->a_vp); - -#ifdef DIAGNOSTIC - struct proc *p = curproc; + struct vnode *vp = ap->a_vp; - if ((ip->i_flag & IN_LOCKED) == 0) { - vprint("ufs_unlock: unlocked inode", ap->a_vp); - panic("ufs_unlock NOT LOCKED"); - } - if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 && - ip->i_lockholder > -1 && lockcount++ < 100) - panic("unlocker (%d) != lock holder (%d)", - p->p_pid, ip->i_lockholder); -#endif - if (--ip->i_lockcount > 0) { - if ((ip->i_flag & IN_RECURSE) == 0) - panic("ufs_unlock: recursive lock prematurely released, pid=%d\n", - ip->i_lockholder); - return (0); - } - ip->i_lockholder = 0; - ip->i_flag &= ~(IN_LOCKED|IN_RECURSE); - if (ip->i_flag & IN_WANTED) { - ip->i_flag &= ~IN_WANTED; - wakeup((caddr_t)ip); - } - return (0); + return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, + &vp->v_interlock, ap->a_p)); } /* @@ -1792,9 +1795,7 @@ ufs_islocked(ap) } */ *ap; { - if (VTOI(ap->a_vp)->i_flag & IN_LOCKED) - return (1); - return (0); + return (lockstatus(&VTOI(ap->a_vp)->i_lock)); } /* @@ -1850,14 +1851,11 @@ ufs_print(ap) printf("tag VT_UFS, ino %ld, on dev %d, %d", ip->i_number, major(ip->i_dev), minor(ip->i_dev)); +#ifdef FIFO if (vp->v_type == VFIFO) fifo_printinfo(vp); - printf("%s\n", (ip->i_flag & IN_LOCKED) ? " (LOCKED)" : ""); - if (ip->i_lockholder == 0) - return (0); - printf("\towner pid %lu", (u_long)ip->i_lockholder); - if (ip->i_lockwaiter) - printf(" waiting pid %lu", (u_long)ip->i_lockwaiter); +#endif /* FIFO */ + lockmgr_printinfo(&ip->i_lock); printf("\n"); return (0); } @@ -1916,10 +1914,13 @@ ufsspec_close(ap) struct proc *a_p; } */ *ap; { - register struct inode *ip = VTOI(ap->a_vp); + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); - if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) + simple_lock(&vp->v_interlock); + if (ap->a_vp->v_usecount > 1) ITIMES(ip, &time, &time); + simple_unlock(&vp->v_interlock); return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap)); } @@ -1975,10 +1976,13 @@ ufsfifo_close(ap) struct proc *a_p; } */ *ap; { - register struct inode *ip = VTOI(ap->a_vp); + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); - if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED)) + simple_lock(&vp->v_interlock); + if (ap->a_vp->v_usecount > 1) ITIMES(ip, &time, &time); + simple_unlock(&vp->v_interlock); return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap)); } @@ -2061,9 +2065,9 @@ ufs_vinit(mntp, specops, fifoops, vpp) if (nvp) { /* * Discard unneeded vnode, but save its inode. + * Note that the lock is carried over in the inode + * to the replacement vnode. */ - ufs_ihashrem(ip); - VOP_UNLOCK(vp); nvp->v_data = vp->v_data; vp->v_data = NULL; vp->v_op = spec_vnodeop_p; @@ -2074,7 +2078,6 @@ ufs_vinit(mntp, specops, fifoops, vpp) */ vp = nvp; ip->i_vnode = vp; - ufs_ihashins(ip); } break; case VFIFO: @@ -2149,6 +2152,9 @@ ufs_makeinode(mode, dvp, vpp, cnp) suser(cnp->cn_cred, NULL)) ip->i_mode &= ~ISGID; + if (cnp->cn_flags & ISWHITEOUT) + ip->i_flags |= UF_OPAQUE; + /* * Make sure inode goes to disk before directory entry. */ diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h index d7b7b28..87041a6 100644 --- a/sys/ufs/ufs/ufsmount.h +++ b/sys/ufs/ufs/ufsmount.h @@ -30,13 +30,34 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufsmount.h 8.2 (Berkeley) 1/12/94 + * @(#)ufsmount.h 8.6 (Berkeley) 3/30/95 * $FreeBSD$ */ #ifndef _UFS_UFS_UFSMOUNT_H_ #define _UFS_UFS_UFSMOUNT_H_ +/* + * Arguments to mount UFS-based filesystems + */ +struct ufs_args { + char *fspec; /* block special device to mount */ + struct export_args export; /* network export information */ +}; + +#ifdef MFS +/* + * Arguments to mount MFS + */ +struct mfs_args { + char *fspec; /* name to export for statfs */ + struct export_args export; /* if exported MFSes are supported */ + caddr_t base; /* base of file system in memory */ + u_long size; /* size of file system */ +}; +#endif /* MFS */ + +#ifdef KERNEL struct buf; struct inode; struct nameidata; @@ -51,6 +72,7 @@ struct ufsmount { struct mount *um_mountp; /* filesystem vfs structure */ dev_t um_dev; /* device mounted */ struct vnode *um_devvp; /* block device mounted vnode */ + union { /* pointer to superblock */ struct lfs *lfs; /* LFS */ struct fs *fs; /* FFS */ @@ -60,6 +82,7 @@ struct ufsmount { #define um_lfs ufsmount_u.lfs #define um_e2fs ufsmount_u.e2fs #define um_e2fsb ufsmount_u.e2fs->s_es + struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */ struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */ u_long um_nindir; /* indirect ptrs per block */ @@ -69,7 +92,9 @@ struct ufsmount { time_t um_itime[MAXQUOTAS]; /* inode quota time limit */ char um_qflags[MAXQUOTAS]; /* quota specific flags */ struct netexport um_export; /* export information */ + int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */ }; + /* * Flags describing the state of quotas. */ @@ -83,8 +108,9 @@ struct ufsmount { * Macros to access file system parameters in the ufsmount structure. * Used by ufs_bmap. */ -#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb) -#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc) -#define MNINDIR(ump) ((ump)->um_nindir) +#define MNINDIR(ump) ((ump)->um_nindir) +#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb) +#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc) +#endif /* KERNEL */ #endif -- cgit v1.1