In message <[EMAIL PROTECTED]>, Ian Dowse writes:
>
>The fix should be relatively straightforward - either the code should
>avoid linking new indirection blocks until all allocations succeed,
>or it should back out the changes on failure.

Here's one patch that seems to fix the problem. It may not be the best
approach though?

Ian

--- ffs_balloc.c.orig   Thu Feb 24 00:44:32 2000
+++ ffs_balloc.c        Thu Feb 24 01:45:46 2000
@@ -71,7 +71,7 @@
        int flags;
        struct fs *fs;
        ufs_daddr_t nb;
-       struct buf *bp, *nbp;
+       struct buf *bp, *nbp, *allocbp;
        struct vnode *vp;
        struct indir indirs[NIADDR + 2];
        ufs_daddr_t newb, *bap, pref;
@@ -197,6 +197,7 @@
        --num;
        nb = ip->i_ib[indirs[0].in_off];
        allocib = NULL;
+       allocbp = NULL;
        allocblk = allociblk;
        if (nb == 0) {
                pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
@@ -272,6 +273,17 @@
                        }
                }
                bap[indirs[i - 1].in_off] = nb;
+               if (allocib == NULL) {
+                       /* 
+                        * Writing bp would link in the newly allocated
+                        * blocks; hold off in case of allocation failure
+                        * later.
+                        */
+                       allocib = &bap[indirs[i - 1].in_off];
+                       allocbp = bp;
+                       continue;
+               }
+
                /*
                 * If required, write synchronously, otherwise use
                 * delayed write.
@@ -316,8 +328,7 @@
                                bp->b_flags |= B_CLUSTEROK;
                        bdwrite(bp);
                }
-               *ap->a_bpp = nbp;
-               return (0);
+               goto success;
        }
        brelse(bp);
        if (flags & B_CLRBUF) {
@@ -330,6 +341,22 @@
                nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
                nbp->b_blkno = fsbtodb(fs, nb);
        }
+success:
+       if (allocbp != NULL) {
+               /*
+                * It is safe to write allocbp now.
+                *
+                * If required, write synchronously, otherwise use
+                * delayed write.
+                */
+               if (flags & B_SYNC) {
+                       bwrite(allocbp);
+               } else {
+                       if (allocbp->b_bufsize == fs->fs_bsize)
+                               allocbp->b_flags |= B_CLUSTEROK;
+                       bdwrite(allocbp);
+               }
+       }
        *ap->a_bpp = nbp;
        return (0);
 fail:
@@ -349,8 +376,11 @@
                ffs_blkfree(ip, *blkp, fs->fs_bsize);
                deallocated += fs->fs_bsize;
        }
-       if (allocib != NULL)
+       if (allocib != NULL) {
                *allocib = 0;
+               if (allocbp != NULL)
+                       brelse(allocbp);
+       }
        if (deallocated) {
 #ifdef QUOTA
                /*


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to