fixes to interactions of new fs and buffer cache with partial blocks
authorBill Joy <root@ucbvax.Berkeley.EDU>
Tue, 15 Jun 1982 14:00:02 +0000 (06:00 -0800)
committerBill Joy <root@ucbvax.Berkeley.EDU>
Tue, 15 Jun 1982 14:00:02 +0000 (06:00 -0800)
including removal of superblocks from cache and refined readahead and
brealloc routine

SCCS-vsn: sys/ufs/ffs/ffs_alloc.c 2.7
SCCS-vsn: sys/ufs/lfs/lfs_alloc.c 2.7
SCCS-vsn: sys/kern/vfs_bio.c 4.34
SCCS-vsn: sys/kern/vfs_cluster.c 4.34
SCCS-vsn: sys/kern/init_main.c 4.31

usr/src/sys/kern/init_main.c
usr/src/sys/kern/vfs_bio.c
usr/src/sys/kern/vfs_cluster.c
usr/src/sys/ufs/ffs/ffs_alloc.c
usr/src/sys/ufs/lfs/lfs_alloc.c

index 1da27e5..88ab9e8 100644 (file)
@@ -1,4 +1,4 @@
-/*     init_main.c     4.30    82/05/31        */
+/*     init_main.c     4.31    82/06/14        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -45,7 +45,7 @@ main(firstaddr)
 {
        register int i;
        register struct proc *p;
 {
        register int i;
        register struct proc *p;
-       struct fs *fsp;
+       struct fs *fs;
 
        rqinit();
 #include "loop.h"
 
        rqinit();
 #include "loop.h"
@@ -96,12 +96,19 @@ main(firstaddr)
        bhinit();
        binit();
        bswinit();
        bhinit();
        binit();
        bswinit();
-       iinit();
-       fsp = getfs(rootdev);
-       rootdir = iget(rootdev, fsp, (ino_t)ROOTINO);
-       rootdir->i_flag &= ~ILOCK;
-       u.u_cdir = iget(rootdev, fsp, (ino_t)ROOTINO);
-       u.u_cdir->i_flag &= ~ILOCK;
+
+       fs = mountfs(rootdev, 0, 0);
+       if (fs == 0)
+               panic("iinit");
+       bcopy("/", fs->fs_fsmnt, 2);
+       clkinit(fs->fs_time);
+       bootime = time;
+
+       rootdir = iget(rootdev, fs, (ino_t)ROOTINO);
+       iunlock(rootdir);
+       u.u_cdir = iget(rootdev, fs, (ino_t)ROOTINO);
+       iunlock(u.u_cdir);
+
        u.u_rdir = NULL;
        u.u_dmap = zdmap;
        u.u_smap = zdmap;
        u.u_rdir = NULL;
        u.u_dmap = zdmap;
        u.u_smap = zdmap;
@@ -148,56 +155,6 @@ main(firstaddr)
        sched();
 }
 
        sched();
 }
 
-/*
- * iinit is called once (from main)
- * very early in initialization.
- * It reads the root's super block
- * and initializes the current date
- * from the last modified date.
- *
- * panic: iinit -- cannot read the super
- * block. Usually because of an IO error.
- */
-iinit()
-{
-       register struct buf *bp;
-       register struct fs *fp;
-       register int i;
-       int blks;
-
-       (*bdevsw[major(rootdev)].d_open)(rootdev, 1);
-       bp = bread(rootdev, SBLOCK, SBSIZE);
-       if(u.u_error)
-               panic("iinit");
-       bp->b_flags |= B_LOCKED;                /* block can never be re-used */
-       brelse(bp);
-       mount[0].m_dev = rootdev;
-       mount[0].m_bufp = bp;
-       fp = bp->b_un.b_fs;
-       if (fp->fs_magic != FS_MAGIC)
-               panic("root bad magic number");
-       if (fp->fs_bsize > MAXBSIZE)
-               panic("root fs_bsize too big");
-       fp->fs_ronly = 0;
-       fp->fs_fsmnt[0] = '/';
-       for (i = 1; i < sizeof(fp->fs_fsmnt); i++)
-               fp->fs_fsmnt[i] = 0;
-       blks = howmany(fp->fs_cssize, fp->fs_fsize);
-       for (i = 0; i < blks; i += fp->fs_frag) {
-               bp = bread(rootdev, fsbtodb(fp, fp->fs_csaddr + i),
-                   blks - i < fp->fs_frag ?
-                       (blks - i) * fp->fs_fsize :
-                       fp->fs_bsize);
-               if (u.u_error)
-                       panic("root can't read csum");
-               fp->fs_csp[i / fp->fs_frag] = bp->b_un.b_cs;
-               bp->b_flags |= B_LOCKED;
-               brelse(bp);
-       }
-       clkinit(fp->fs_time);
-       bootime = time;
-}
-
 /*
  * Initialize hash links for buffers.
  */
 /*
  * Initialize hash links for buffers.
  */
index 2898f65..8df106d 100644 (file)
@@ -1,4 +1,4 @@
-/*     vfs_bio.c       4.33    82/06/07        */
+/*     vfs_bio.c       4.34    82/06/14        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -12,6 +12,8 @@
 #include "../h/vm.h"
 #include "../h/trace.h"
 
 #include "../h/vm.h"
 #include "../h/trace.h"
 
+int bioprintfs = 0;
+
 /*
  * Read in (if necessary) the block and return a buffer pointer.
  */
 /*
  * Read in (if necessary) the block and return a buffer pointer.
  */
@@ -107,6 +109,8 @@ bwrite(bp)
        if ((flag&B_DELWRI) == 0)
                u.u_vm.vm_oublk++;              /* noone paid yet */
        trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
        if ((flag&B_DELWRI) == 0)
                u.u_vm.vm_oublk++;              /* noone paid yet */
        trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
+if (bioprintfs)
+printf("write %x blk %d count %d\n", bp->b_dev, bp->b_blkno, bp->b_bcount);
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
 
        /*
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
 
        /*
@@ -277,7 +281,8 @@ loop:
                }
                splx(s);
                notavail(bp);
                }
                splx(s);
                notavail(bp);
-               brealloc(bp, size);
+               if (brealloc(bp, size) == 0)
+                       goto loop;
                bp->b_flags |= B_CACHE;
                return(bp);
        }
                bp->b_flags |= B_CACHE;
                return(bp);
        }
@@ -312,7 +317,8 @@ loop:
        binshash(bp, dp);
        bp->b_dev = dev;
        bp->b_blkno = blkno;
        binshash(bp, dp);
        bp->b_dev = dev;
        bp->b_blkno = blkno;
-       brealloc(bp, size);
+       if (brealloc(bp, size) == 0)
+               goto loop;
        return(bp);
 }
 
        return(bp);
 }
 
@@ -351,7 +357,8 @@ loop:
        bremhash(bp);
        binshash(bp, dp);
        bp->b_dev = (dev_t)NODEV;
        bremhash(bp);
        binshash(bp, dp);
        bp->b_dev = (dev_t)NODEV;
-       brealloc(bp, size);
+       if (brealloc(bp, size) == 0)
+               goto loop;
        return(bp);
 }
 
        return(bp);
 }
 
@@ -372,23 +379,44 @@ brealloc(bp, size)
         * is dispatched with.
         */
        if (size == bp->b_bcount)
         * is dispatched with.
         */
        if (size == bp->b_bcount)
-               return;
-       if (size < bp->b_bcount || bp->b_dev == NODEV)
+               return (1);
+       if (size < bp->b_bcount) { 
+               if (bp->b_flags & B_DELWRI) {
+                       bwrite(bp);
+                       return (0);
+               }
+               if (bp->b_flags & B_LOCKED)
+                       panic("brealloc");
                goto allocit;
                goto allocit;
-
-       start = bp->b_blkno + (bp->b_bcount / DEV_BSIZE);
-       last = bp->b_blkno + (size / DEV_BSIZE) - 1;
-       if (bp->b_bcount == 0) {
-               start++;
-               if (start == last)
-                       goto allocit;
        }
        }
+       bp->b_flags &= ~B_DONE;
+       if (bp->b_dev == NODEV)
+               goto allocit;
+
+       /*
+        * Search cache for any buffers that overlap the one that we
+        * are trying to allocate. Overlapping buffers must be marked
+        * invalid, after being written out if they are dirty. (indicated
+        * by B_DELWRI) A disk block must be mapped by at most one buffer
+        * at any point in time. Care must be taken to avoid deadlocking
+        * when two buffer are trying to get the same set of disk blocks.
+        */
+       start = bp->b_blkno;
+       last = start + (size / DEV_BSIZE) - 1;
        dp = BUFHASH(bp->b_dev, bp->b_blkno);
 loop:
        for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
        dp = BUFHASH(bp->b_dev, bp->b_blkno);
 loop:
        for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
-               if (ep->b_blkno < start || ep->b_blkno > last ||
-                   ep->b_dev != bp->b_dev || ep->b_flags&B_INVAL)
+               if (ep == bp || ep->b_dev != bp->b_dev || (ep->b_flags&B_INVAL))
+                       continue;
+               /* look for overlap */
+               if (ep->b_bcount == 0 || ep->b_blkno > last ||
+                   ep->b_blkno + (ep->b_bcount / DEV_BSIZE) <= start)
                        continue;
                        continue;
+if (bioprintfs)
+if (ep->b_flags&B_BUSY)
+printf("sleeping on:dev 0x%x, blks %d-%d, flg 0%o allocing dev 0x%x, blks %d-%d, flg 0%o\n",
+ep->b_dev, ep->b_blkno, ep->b_blkno + (ep->b_bcount / DEV_BSIZE) - 1,
+ep->b_flags, bp->b_dev, start, last, bp->b_flags);
                s = spl6();
                if (ep->b_flags&B_BUSY) {
                        ep->b_flags |= B_WANTED;
                s = spl6();
                if (ep->b_flags&B_BUSY) {
                        ep->b_flags |= B_WANTED;
@@ -397,18 +425,17 @@ loop:
                        goto loop;
                }
                (void) splx(s);
                        goto loop;
                }
                (void) splx(s);
-               /*
-                * What we would really like to do is kill this
-                * I/O since it is now useless. We cannot do that
-                * so we force it to complete, so that it cannot
-                * over-write our useful data later.
-                */
+               notavail(ep);
                if (ep->b_flags & B_DELWRI) {
                if (ep->b_flags & B_DELWRI) {
-                       notavail(ep);
-                       ep->b_flags |= B_ASYNC;
+if (bioprintfs)
+printf("DELWRI:dev 0x%x, blks %d-%d, flg 0%o allocing dev 0x%x, blks %d-%d, flg 0%o\n",
+ep->b_dev, ep->b_blkno, ep->b_blkno + (ep->b_bcount / DEV_BSIZE) - 1,
+ep->b_flags, bp->b_dev, start, last, bp->b_flags);
                        bwrite(ep);
                        goto loop;
                }
                        bwrite(ep);
                        goto loop;
                }
+               ep->b_flags |= B_INVAL;
+               brelse(ep);
        }
 allocit:
        /*
        }
 allocit:
        /*
@@ -417,6 +444,7 @@ allocit:
         * management scheme will be implemented.
         */
        bp->b_bcount = size;
         * management scheme will be implemented.
         */
        bp->b_bcount = size;
+       return (1);
 }
 
 /*
 }
 
 /*
index 02c6db1..8de8b75 100644 (file)
@@ -1,4 +1,4 @@
-/*     vfs_cluster.c   4.33    82/06/07        */
+/*     vfs_cluster.c   4.34    82/06/14        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -12,6 +12,8 @@
 #include "../h/vm.h"
 #include "../h/trace.h"
 
 #include "../h/vm.h"
 #include "../h/trace.h"
 
+int bioprintfs = 0;
+
 /*
  * Read in (if necessary) the block and return a buffer pointer.
  */
 /*
  * Read in (if necessary) the block and return a buffer pointer.
  */
@@ -107,6 +109,8 @@ bwrite(bp)
        if ((flag&B_DELWRI) == 0)
                u.u_vm.vm_oublk++;              /* noone paid yet */
        trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
        if ((flag&B_DELWRI) == 0)
                u.u_vm.vm_oublk++;              /* noone paid yet */
        trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
+if (bioprintfs)
+printf("write %x blk %d count %d\n", bp->b_dev, bp->b_blkno, bp->b_bcount);
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
 
        /*
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
 
        /*
@@ -277,7 +281,8 @@ loop:
                }
                splx(s);
                notavail(bp);
                }
                splx(s);
                notavail(bp);
-               brealloc(bp, size);
+               if (brealloc(bp, size) == 0)
+                       goto loop;
                bp->b_flags |= B_CACHE;
                return(bp);
        }
                bp->b_flags |= B_CACHE;
                return(bp);
        }
@@ -312,7 +317,8 @@ loop:
        binshash(bp, dp);
        bp->b_dev = dev;
        bp->b_blkno = blkno;
        binshash(bp, dp);
        bp->b_dev = dev;
        bp->b_blkno = blkno;
-       brealloc(bp, size);
+       if (brealloc(bp, size) == 0)
+               goto loop;
        return(bp);
 }
 
        return(bp);
 }
 
@@ -351,7 +357,8 @@ loop:
        bremhash(bp);
        binshash(bp, dp);
        bp->b_dev = (dev_t)NODEV;
        bremhash(bp);
        binshash(bp, dp);
        bp->b_dev = (dev_t)NODEV;
-       brealloc(bp, size);
+       if (brealloc(bp, size) == 0)
+               goto loop;
        return(bp);
 }
 
        return(bp);
 }
 
@@ -372,23 +379,44 @@ brealloc(bp, size)
         * is dispatched with.
         */
        if (size == bp->b_bcount)
         * is dispatched with.
         */
        if (size == bp->b_bcount)
-               return;
-       if (size < bp->b_bcount || bp->b_dev == NODEV)
+               return (1);
+       if (size < bp->b_bcount) { 
+               if (bp->b_flags & B_DELWRI) {
+                       bwrite(bp);
+                       return (0);
+               }
+               if (bp->b_flags & B_LOCKED)
+                       panic("brealloc");
                goto allocit;
                goto allocit;
-
-       start = bp->b_blkno + (bp->b_bcount / DEV_BSIZE);
-       last = bp->b_blkno + (size / DEV_BSIZE) - 1;
-       if (bp->b_bcount == 0) {
-               start++;
-               if (start == last)
-                       goto allocit;
        }
        }
+       bp->b_flags &= ~B_DONE;
+       if (bp->b_dev == NODEV)
+               goto allocit;
+
+       /*
+        * Search cache for any buffers that overlap the one that we
+        * are trying to allocate. Overlapping buffers must be marked
+        * invalid, after being written out if they are dirty. (indicated
+        * by B_DELWRI) A disk block must be mapped by at most one buffer
+        * at any point in time. Care must be taken to avoid deadlocking
+        * when two buffer are trying to get the same set of disk blocks.
+        */
+       start = bp->b_blkno;
+       last = start + (size / DEV_BSIZE) - 1;
        dp = BUFHASH(bp->b_dev, bp->b_blkno);
 loop:
        for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
        dp = BUFHASH(bp->b_dev, bp->b_blkno);
 loop:
        for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
-               if (ep->b_blkno < start || ep->b_blkno > last ||
-                   ep->b_dev != bp->b_dev || ep->b_flags&B_INVAL)
+               if (ep == bp || ep->b_dev != bp->b_dev || (ep->b_flags&B_INVAL))
+                       continue;
+               /* look for overlap */
+               if (ep->b_bcount == 0 || ep->b_blkno > last ||
+                   ep->b_blkno + (ep->b_bcount / DEV_BSIZE) <= start)
                        continue;
                        continue;
+if (bioprintfs)
+if (ep->b_flags&B_BUSY)
+printf("sleeping on:dev 0x%x, blks %d-%d, flg 0%o allocing dev 0x%x, blks %d-%d, flg 0%o\n",
+ep->b_dev, ep->b_blkno, ep->b_blkno + (ep->b_bcount / DEV_BSIZE) - 1,
+ep->b_flags, bp->b_dev, start, last, bp->b_flags);
                s = spl6();
                if (ep->b_flags&B_BUSY) {
                        ep->b_flags |= B_WANTED;
                s = spl6();
                if (ep->b_flags&B_BUSY) {
                        ep->b_flags |= B_WANTED;
@@ -397,18 +425,17 @@ loop:
                        goto loop;
                }
                (void) splx(s);
                        goto loop;
                }
                (void) splx(s);
-               /*
-                * What we would really like to do is kill this
-                * I/O since it is now useless. We cannot do that
-                * so we force it to complete, so that it cannot
-                * over-write our useful data later.
-                */
+               notavail(ep);
                if (ep->b_flags & B_DELWRI) {
                if (ep->b_flags & B_DELWRI) {
-                       notavail(ep);
-                       ep->b_flags |= B_ASYNC;
+if (bioprintfs)
+printf("DELWRI:dev 0x%x, blks %d-%d, flg 0%o allocing dev 0x%x, blks %d-%d, flg 0%o\n",
+ep->b_dev, ep->b_blkno, ep->b_blkno + (ep->b_bcount / DEV_BSIZE) - 1,
+ep->b_flags, bp->b_dev, start, last, bp->b_flags);
                        bwrite(ep);
                        goto loop;
                }
                        bwrite(ep);
                        goto loop;
                }
+               ep->b_flags |= B_INVAL;
+               brelse(ep);
        }
 allocit:
        /*
        }
 allocit:
        /*
@@ -417,6 +444,7 @@ allocit:
         * management scheme will be implemented.
         */
        bp->b_bcount = size;
         * management scheme will be implemented.
         */
        bp->b_bcount = size;
+       return (1);
 }
 
 /*
 }
 
 /*
index 16891d1..fb02bc5 100644 (file)
@@ -1,4 +1,4 @@
-/*     ffs_alloc.c     2.6     82/06/07        */
+/*     ffs_alloc.c     2.7     82/06/14        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -119,12 +119,14 @@ realloccg(ip, bprev, bpref, osize, nsize)
        cg = dtog(fs, bprev);
        bno = fragextend(ip, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
        cg = dtog(fs, bprev);
        bno = fragextend(ip, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
-               bp = bread(ip->i_dev, fsbtodb(fs, bno), osize);
-               if (bp->b_flags & B_ERROR) {
-                       brelse(bp);
-                       return (NULL);
-               }
-               brealloc(bp, nsize);
+               do {
+                       bp = bread(ip->i_dev, fsbtodb(fs, bno), osize);
+                       if (bp->b_flags & B_ERROR) {
+                               brelse(bp);
+                               return (NULL);
+                       }
+               } while (brealloc(bp, nsize) == 0);
+               bp->b_flags |= B_DONE;
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
        }
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
        }
@@ -489,10 +491,14 @@ alloccgblk(fs, cgp, bpref)
        /*
         * if the requested block is available, use it
         */
        /*
         * if the requested block is available, use it
         */
+/*
+ * disallow sequential layout.
+ *
        if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
                bno = bpref;
                goto gotit;
        }
        if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
                bno = bpref;
                goto gotit;
        }
+ */
        /*
         * check for a block available on the same cylinder
         */
        /*
         * check for a block available on the same cylinder
         */
@@ -1002,27 +1008,13 @@ update(flag)
                fs = mp->m_bufp->b_un.b_fs;
                if (fs->fs_fmod == 0)
                        continue;
                fs = mp->m_bufp->b_un.b_fs;
                if (fs->fs_fmod == 0)
                        continue;
-               if (fs->fs_ronly != 0) {
+               if (fs->fs_ronly != 0) {                /* ### */
                        printf("fs = %s\n", fs->fs_fsmnt);
                        panic("update: rofs mod");
                }
                        printf("fs = %s\n", fs->fs_fsmnt);
                        panic("update: rofs mod");
                }
-               bp = getblk(mp->m_dev, SBLOCK, SBSIZE);
-               if (bp->b_un.b_fs != fs || fs->fs_magic != FS_MAGIC) {
-                       printf("fs = %s\n", fs->fs_fsmnt);
-                       panic("update: bad b_fs");
-               }
                fs->fs_fmod = 0;
                fs->fs_time = time;
                fs->fs_fmod = 0;
                fs->fs_time = time;
-               bwrite(bp);
-               blks = howmany(fs->fs_cssize, fs->fs_fsize);
-               for (i = 0; i < blks; i += fs->fs_frag) {
-                       bp = getblk(mp->m_dev,
-                           fsbtodb(fs, fs->fs_csaddr + i),
-                           blks - i < fs->fs_frag ? 
-                               (blks - i) * fs->fs_fsize :
-                               fs->fs_bsize);
-                       bwrite(bp);
-               }
+               sbupdate(mp);
        }
        /*
         * Write back each (modified) inode.
        }
        /*
         * Write back each (modified) inode.
index 5a7cb2f..369da1d 100644 (file)
@@ -1,4 +1,4 @@
-/*     lfs_alloc.c     2.6     82/06/07        */
+/*     lfs_alloc.c     2.7     82/06/14        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -119,12 +119,14 @@ realloccg(ip, bprev, bpref, osize, nsize)
        cg = dtog(fs, bprev);
        bno = fragextend(ip, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
        cg = dtog(fs, bprev);
        bno = fragextend(ip, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
-               bp = bread(ip->i_dev, fsbtodb(fs, bno), osize);
-               if (bp->b_flags & B_ERROR) {
-                       brelse(bp);
-                       return (NULL);
-               }
-               brealloc(bp, nsize);
+               do {
+                       bp = bread(ip->i_dev, fsbtodb(fs, bno), osize);
+                       if (bp->b_flags & B_ERROR) {
+                               brelse(bp);
+                               return (NULL);
+                       }
+               } while (brealloc(bp, nsize) == 0);
+               bp->b_flags |= B_DONE;
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
        }
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
        }
@@ -489,10 +491,14 @@ alloccgblk(fs, cgp, bpref)
        /*
         * if the requested block is available, use it
         */
        /*
         * if the requested block is available, use it
         */
+/*
+ * disallow sequential layout.
+ *
        if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
                bno = bpref;
                goto gotit;
        }
        if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
                bno = bpref;
                goto gotit;
        }
+ */
        /*
         * check for a block available on the same cylinder
         */
        /*
         * check for a block available on the same cylinder
         */
@@ -1002,27 +1008,13 @@ update(flag)
                fs = mp->m_bufp->b_un.b_fs;
                if (fs->fs_fmod == 0)
                        continue;
                fs = mp->m_bufp->b_un.b_fs;
                if (fs->fs_fmod == 0)
                        continue;
-               if (fs->fs_ronly != 0) {
+               if (fs->fs_ronly != 0) {                /* ### */
                        printf("fs = %s\n", fs->fs_fsmnt);
                        panic("update: rofs mod");
                }
                        printf("fs = %s\n", fs->fs_fsmnt);
                        panic("update: rofs mod");
                }
-               bp = getblk(mp->m_dev, SBLOCK, SBSIZE);
-               if (bp->b_un.b_fs != fs || fs->fs_magic != FS_MAGIC) {
-                       printf("fs = %s\n", fs->fs_fsmnt);
-                       panic("update: bad b_fs");
-               }
                fs->fs_fmod = 0;
                fs->fs_time = time;
                fs->fs_fmod = 0;
                fs->fs_time = time;
-               bwrite(bp);
-               blks = howmany(fs->fs_cssize, fs->fs_fsize);
-               for (i = 0; i < blks; i += fs->fs_frag) {
-                       bp = getblk(mp->m_dev,
-                           fsbtodb(fs, fs->fs_csaddr + i),
-                           blks - i < fs->fs_frag ? 
-                               (blks - i) * fs->fs_fsize :
-                               fs->fs_bsize);
-                       bwrite(bp);
-               }
+               sbupdate(mp);
        }
        /*
         * Write back each (modified) inode.
        }
        /*
         * Write back each (modified) inode.