summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs/ffs_balloc.c
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-02-10 02:22:35 +0000
committerdyson <dyson@FreeBSD.org>1997-02-10 02:22:35 +0000
commit10f666af84d48e89e4e2960415c9b616fce4077f (patch)
tree88a944de263165091f0a18abeedbaaccec532407 /sys/ufs/ffs/ffs_balloc.c
parent0960d7e91af3428ffba89b42228d82d8afaa0389 (diff)
downloadFreeBSD-src-10f666af84d48e89e4e2960415c9b616fce4077f.zip
FreeBSD-src-10f666af84d48e89e4e2960415c9b616fce4077f.tar.gz
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 <hsu@freebsd.org>
Diffstat (limited to 'sys/ufs/ffs/ffs_balloc.c')
-rw-r--r--sys/ufs/ffs/ffs_balloc.c116
1 files changed, 68 insertions, 48 deletions
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);
}
OpenPOWER on IntegriCloud