summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs/ffs_balloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs/ffs/ffs_balloc.c')
-rw-r--r--sys/ufs/ffs/ffs_balloc.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index 6d5f27c..4775768 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -105,6 +105,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
ufs2_daddr_t *lbns_remfree, lbns[NIADDR + 1];
int unwindidx = -1;
int saved_inbdflush;
+ int reclaimed;
ip = VTOI(vp);
dp = ip->i_din1;
@@ -112,6 +113,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
ump = ip->i_ump;
lbn = lblkno(fs, startoffset);
size = blkoff(fs, startoffset) + size;
+ reclaimed = 0;
if (size > fs->fs_bsize)
panic("ffs_balloc_ufs1: blk too big");
*bpp = NULL;
@@ -276,6 +278,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
/*
* Fetch through the indirect blocks, allocating as necessary.
*/
+retry:
for (i = 1;;) {
error = bread(vp,
indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
@@ -296,8 +299,15 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
if (pref == 0)
pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0);
if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
- flags, cred, &newb)) != 0) {
+ flags | IO_BUFLOCKED, cred, &newb)) != 0) {
brelse(bp);
+ if (++reclaimed == 1) {
+ UFS_LOCK(ump);
+ softdep_request_cleanup(fs, vp, cred,
+ FLUSH_BLOCKS_WAIT);
+ UFS_UNLOCK(ump);
+ goto retry;
+ }
goto fail;
}
nb = newb;
@@ -349,10 +359,17 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
if (nb == 0) {
UFS_LOCK(ump);
pref = ffs_blkpref_ufs1(ip, lbn, indirs[i].in_off, &bap[0]);
- error = ffs_alloc(ip,
- lbn, pref, (int)fs->fs_bsize, flags, cred, &newb);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
+ flags | IO_BUFLOCKED, cred, &newb);
if (error) {
brelse(bp);
+ if (++reclaimed == 1) {
+ UFS_LOCK(ump);
+ softdep_request_cleanup(fs, vp, cred,
+ FLUSH_BLOCKS_WAIT);
+ UFS_UNLOCK(ump);
+ goto retry;
+ }
goto fail;
}
nb = newb;
@@ -506,6 +523,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
int deallocated, osize, nsize, num, i, error;
int unwindidx = -1;
int saved_inbdflush;
+ int reclaimed;
ip = VTOI(vp);
dp = ip->i_din2;
@@ -513,6 +531,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
ump = ip->i_ump;
lbn = lblkno(fs, startoffset);
size = blkoff(fs, startoffset) + size;
+ reclaimed = 0;
if (size > fs->fs_bsize)
panic("ffs_balloc_ufs2: blk too big");
*bpp = NULL;
@@ -787,6 +806,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
/*
* Fetch through the indirect blocks, allocating as necessary.
*/
+retry:
for (i = 1;;) {
error = bread(vp,
indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
@@ -807,8 +827,15 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
if (pref == 0)
pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0);
if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
- flags, cred, &newb)) != 0) {
+ flags | IO_BUFLOCKED, cred, &newb)) != 0) {
brelse(bp);
+ if (++reclaimed == 1) {
+ UFS_LOCK(ump);
+ softdep_request_cleanup(fs, vp, cred,
+ FLUSH_BLOCKS_WAIT);
+ UFS_UNLOCK(ump);
+ goto retry;
+ }
goto fail;
}
nb = newb;
@@ -860,10 +887,17 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
if (nb == 0) {
UFS_LOCK(ump);
pref = ffs_blkpref_ufs2(ip, lbn, indirs[i].in_off, &bap[0]);
- error = ffs_alloc(ip,
- lbn, pref, (int)fs->fs_bsize, flags, cred, &newb);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
+ flags | IO_BUFLOCKED, cred, &newb);
if (error) {
brelse(bp);
+ if (++reclaimed == 1) {
+ UFS_LOCK(ump);
+ softdep_request_cleanup(fs, vp, cred,
+ FLUSH_BLOCKS_WAIT);
+ UFS_UNLOCK(ump);
+ goto retry;
+ }
goto fail;
}
nb = newb;
OpenPOWER on IntegriCloud