summaryrefslogtreecommitdiff
path: root/sys/ufs/ffs/ffs_alloc.c
diff options
context:
space:
mode:
authorConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1997-10-06 15:27:41 +0000
committerConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>1997-10-06 15:27:41 +0000
commit62c64950f8e658fa60106b4d32e70ae3b6156d0d (patch)
tree744cdeb111ee67810449481a1420174c49e0ef8d /sys/ufs/ffs/ffs_alloc.c
parentcc87020169150a242c9019d00234c378942f5e88 (diff)
VFS Lite2 Changes
Diffstat (limited to 'sys/ufs/ffs/ffs_alloc.c')
-rw-r--r--sys/ufs/ffs/ffs_alloc.c210
1 files changed, 175 insertions, 35 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index e25073d6715..e4bf9e3d285 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_alloc.c,v 1.7 1997/07/22 10:31:50 deraadt Exp $ */
+/* $OpenBSD: ffs_alloc.c,v 1.8 1997/10/06 15:26:28 csapuntz Exp $ */
/* $NetBSD: ffs_alloc.c,v 1.11 1996/05/11 18:27:09 mycroft Exp $ */
/*
@@ -59,7 +59,7 @@
extern u_long nextgennumber;
static daddr_t ffs_alloccg __P((struct inode *, int, daddr_t, int));
-static daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, daddr_t));
+static daddr_t ffs_alloccgblk __P((struct inode *, struct buf *, daddr_t));
static daddr_t ffs_clusteralloc __P((struct inode *, int, daddr_t, int));
static ino_t ffs_dirpref __P((struct fs *));
static daddr_t ffs_fragextend __P((struct inode *, int, long, int, int));
@@ -70,6 +70,11 @@ static u_long ffs_hashalloc __P((struct inode *, int, long, int,
static daddr_t ffs_nodealloccg __P((struct inode *, int, daddr_t, int));
static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int));
+#ifdef DIAGNOSTIC
+static int ffs_checkblk __P((struct inode *, daddr_t, long));
+#endif
+int ffs_freefile __P((struct vop_vfree_args *));
+
/*
* Allocate a block in the file system.
*
@@ -272,7 +277,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
if (bno > 0) {
bp->b_blkno = fsbtodb(fs, bno);
(void) vnode_pager_uncache(ITOV(ip));
- ffs_blkfree(ip, bprev, (long)osize);
+ if (!DOINGSOFTDEP(ITOV(ip)))
+ ffs_blkfree(ip, bprev, (long)osize);
if (nsize < request)
ffs_blkfree(ip, bno + numfrags(fs, nsize),
(long)(request - nsize));
@@ -314,15 +320,10 @@ nospace:
* Note that the error return is not reflected back to the user. Rather
* the previous block allocation will be used.
*/
-#ifdef DEBUG
-#include <sys/sysctl.h>
+
int doasyncfree = 1;
-struct ctldebug debug14 = { "doasyncfree", &doasyncfree };
+int doreallocblks = 1;
int prtrealloc = 0;
-struct ctldebug debug15 = { "prtrealloc", &prtrealloc };
-#else
-#define doasyncfree 1
-#endif
int
ffs_reallocblks(v)
@@ -343,6 +344,9 @@ ffs_reallocblks(v)
int i, len, start_lvl, end_lvl, pref, ssize;
struct timespec ts;
+ if (doreallocblks == 0)
+ return (ENOSPC);
+
vp = ap->a_vp;
ip = VTOI(vp);
fs = ip->i_fs;
@@ -352,10 +356,22 @@ ffs_reallocblks(v)
len = buflist->bs_nchildren;
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
@@ -422,9 +438,14 @@ ffs_reallocblks(v)
#endif
blkno = newblk;
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
- if (i == ssize)
+ if (i == ssize) {
bap = ebap;
+ soff = -i;
+ }
#ifdef DIAGNOSTIC
+ 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
@@ -432,6 +453,17 @@ ffs_reallocblks(v)
if (prtrealloc)
printf(" %d,", *bap);
#endif
+ if (DOINGSOFTDEP(vp)) {
+ if (sbap == &ip->i_ffs_db[0] && i < ssize)
+ softdep_setup_allocdirect(ip, start_lbn + i,
+ blkno, *bap, fs->fs_bsize, fs->fs_bsize,
+ buflist->bs_children[i]);
+ else
+ softdep_setup_allocindir_page(ip, start_lbn + i,
+ i < ssize ? sbp : ebp, soff + i, blkno,
+ *bap, buflist->bs_children[i]);
+ }
+
*bap++ = blkno;
}
/*
@@ -473,10 +505,15 @@ ffs_reallocblks(v)
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);
+ if (!DOINGSOFTDEP(vp))
+ 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
@@ -815,6 +852,9 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
fs->fs_cs(fs, cg).cs_nffree--;
}
fs->fs_fmod = 1;
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_blkmapdep(bp, fs, bprev);
+
bdwrite(bp);
return (bprev);
}
@@ -835,8 +875,8 @@ ffs_alloccg(ip, cg, bpref, size)
register struct fs *fs;
register struct cg *cgp;
struct buf *bp;
- register int i;
- int error, bno, frags, allocsiz;
+ daddr_t bno, blkno;
+ int error, i, frags, allocsiz;
fs = ip->i_fs;
if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
@@ -855,7 +895,7 @@ ffs_alloccg(ip, cg, bpref, size)
}
cgp->cg_time = time.tv_sec;
if (size == fs->fs_bsize) {
- bno = ffs_alloccgblk(fs, cgp, bpref);
+ bno = ffs_alloccgblk(ip, bp, bpref);
bdwrite(bp);
return (bno);
}
@@ -877,7 +917,7 @@ ffs_alloccg(ip, cg, bpref, size)
brelse(bp);
return (NULL);
}
- bno = ffs_alloccgblk(fs, cgp, bpref);
+ bno = ffs_alloccgblk(ip, bp, bpref);
bpref = dtogd(fs, bno);
for (i = frags; i < fs->fs_frag; i++)
setbit(cg_blksfree(cgp), bpref + i);
@@ -904,8 +944,12 @@ ffs_alloccg(ip, cg, bpref, size)
cgp->cg_frsum[allocsiz]--;
if (frags != allocsiz)
cgp->cg_frsum[allocsiz - frags]++;
- bdwrite(bp);
- return (cg * fs->fs_fpg + bno);
+
+ blkno = cg * fs->fs_fpg + bno;
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_blkmapdep(bp, fs, blkno);
+ bdwrite(bp);
+ return ((u_long)blkno);
}
/*
@@ -920,16 +964,20 @@ ffs_alloccg(ip, cg, bpref, size)
* blocks may be fragmented by the routine that allocates them.
*/
static daddr_t
-ffs_alloccgblk(fs, cgp, bpref)
- register struct fs *fs;
- register struct cg *cgp;
+ffs_alloccgblk(ip, bp, bpref)
+ struct inode *ip;
+ struct buf *bp;
daddr_t bpref;
{
+ struct fs *fs;
+ struct cg *cgp;
daddr_t bno, blkno;
int cylno, pos, delta;
short *cylbp;
register int i;
+ fs = ip->i_fs;
+ cgp = (struct cg *)bp->b_data;
if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) {
bpref = cgp->cg_rotor;
goto norot;
@@ -1020,7 +1068,10 @@ gotit:
cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--;
cg_blktot(cgp)[cylno]--;
fs->fs_fmod = 1;
- return (cgp->cg_cgx * fs->fs_fpg + bno);
+ blkno = cgp->cg_cgx * fs->fs_fpg + bno;
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_blkmapdep(bp, fs, blkno);
+ return (blkno);
}
/*
@@ -1040,7 +1091,7 @@ ffs_clusteralloc(ip, cg, bpref, 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;
@@ -1094,7 +1145,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 {
@@ -1102,22 +1153,32 @@ 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);
+#ifdef DIAGNOSTIC
+ for (i = 1; i <= len; i++)
+ if (!ffs_isblock(fs, cg_blksfree(cgp), got - run + i))
+ panic("ffs_clusteralloc: map mismatch");
+#endif
+ bno = cg * fs->fs_fpg + blkstofrags(fs, got - run + 1);
+#ifdef DIAGNOSTIC
+ if (dtog(fs, bno) != cg)
+ panic("ffs_clusteralloc: allocated out of group");
+#endif
+
len = blkstofrags(fs, len);
for (i = 0; i < len; i += fs->fs_frag)
- if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i)
+ if (ffs_alloccgblk(ip, bp, bno + i) != bno + i)
panic("ffs_clusteralloc: lost block");
bdwrite(bp);
return (bno);
@@ -1195,6 +1256,9 @@ ffs_nodealloccg(ip, cg, ipref, mode)
panic("ffs_nodealloccg: block not in map");
/* NOTREACHED */
gotit:
+ if (DOINGSOFTDEP(ITOV(ip)))
+ softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref);
+
setbit(cg_inosused(cgp), ipref);
cgp->cg_cs.cs_nifree--;
fs->fs_cstotal.cs_nifree--;
@@ -1229,7 +1293,8 @@ ffs_blkfree(ip, bno, size)
int i, error, cg, blk, frags, bbase;
fs = ip->i_fs;
- if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
+ if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
+ fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
printf("dev = 0x%x, bsize = %d, size = %ld, fs = %s\n",
ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
panic("blkfree: bad size");
@@ -1255,7 +1320,7 @@ ffs_blkfree(ip, bno, size)
bno = dtogd(fs, bno);
if (size == fs->fs_bsize) {
blkno = fragstoblks(fs, bno);
- if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) {
+ if (!ffs_isfreeblock(fs, cg_blksfree(cgp), blkno)) {
printf("dev = 0x%x, block = %d, fs = %s\n",
ip->i_dev, bno, fs->fs_fsmnt);
panic("blkfree: freeing free block");
@@ -1318,8 +1383,6 @@ ffs_blkfree(ip, bno, size)
/*
* Free an inode.
- *
- * The specified inode is placed back in the free map.
*/
int
ffs_vfree(v)
@@ -1330,6 +1393,28 @@ ffs_vfree(v)
ino_t a_ino;
int a_mode;
} */ *ap = v;
+
+
+ if (DOINGSOFTDEP(ap->a_pvp)) {
+ softdep_freefile(ap);
+ return (0);
+ }
+
+ return (ffs_freefile(ap));
+}
+
+/*
+ * Do the actual free operation.
+ * The specified inode is placed back in the free map.
+ */
+int
+ffs_freefile(ap)
+ struct vop_vfree_args /* {
+ struct vnode *a_pvp;
+ ino_t a_ino;
+ int a_mode;
+ } */ *ap;
+{
register struct fs *fs;
register struct cg *cgp;
register struct inode *pip;
@@ -1347,7 +1432,7 @@ ffs_vfree(v)
(int)fs->fs_cgsize, NOCRED, &bp);
if (error) {
brelse(bp);
- return (0);
+ return (error);
}
cgp = (struct cg *)bp->b_data;
if (!cg_chkmagic(cgp)) {
@@ -1378,6 +1463,60 @@ ffs_vfree(v)
return (0);
}
+#ifdef DIAGNOSTIC
+/*
+ * Verify allocation of a block or fragment. Returns true if block or
+ * fragment is allocated, false if it is free.
+ */
+int
+ffs_checkblk(ip, bno, size)
+ struct inode *ip;
+ 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) {
+ /* XXX -probably should pannic here */
+ brelse(bp);
+ return (-1);
+ }
+ cgp = (struct cg *)bp->b_data;
+ if (!cg_chkmagic(cgp)) {
+ /* XXX -probably should pannic here */
+ brelse(bp);
+ return (-1);
+ }
+ 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 */
+
+
/*
* Find a block of the specified size in the specified cylinder group.
*
@@ -1550,3 +1689,4 @@ ffs_fserr(fs, uid, cp)
log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp);
}
+