tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

resize_ffs(8) patch for ufs2 grow and byteswap support



As some are aware, I've been hacking on resize_ffs(8) lately to add the
functionality that's been lacking, and that caused such a kerfuffle on this
list back in October.  While I'm not done with everything I wanted to
do, I find my interest waning somewhat, and wanted to get the code
as it stands in front of some other people in case I get completely distracted.

The attached patch does the following:

 - Adds support for byteswapped file systems (BE FS on LE host and
        vice versa). Fixes PR#44203.
 - Adds support for growing UFS2 file systems. Partially fixes PR#44205.


There is also a fair amount of reformatting and stuff like bcopy()->memcpy()
mixed in - sorry about that, but I don't at the moment have the energy to
separate it all out, and hope that people can see beyond it to review the code
itself.

While I have done some fairly extensive testing on this (using extended
versions of the tests I committed to src/tests/sbin/resize_ffs) and
am reasonably confident in its ability to not screw up your data, I would
appreciate it if folks would refrain from using it to alter any non-backed-up
data until it has received a more thorough review from the community at large.
While working on this, I discovered (and have already committed a fix for) at
least one problem which would corrupt data on grow - so be careful! This
patch does not yet fix PR#44204 - but that's a fairly minor problem
that I'll get to later.

I fully expect that there will be criticism of my changes and/or coding style.
That's fine, and I'm happy to adjust things within reason.

I have not included the extended tests in this patch, because I'm not happy
with them from a code abstraction standpoint yet, but they exercise all
8:1 blocksize/fragsize combinations, and verify actual data in the file system
after resize.  The tests include ffsv1 with v1 superblock (newfs -O0),
ffsv1 with updated sblock (newfs -O1) and ffsv2 (newfs -O2) with host-order
and swapped byte ordering, and I'm reasonably confident I haven't introduced
any regressions.  

Enjoy, and be kind!  ;)

+j

? .gdbinit
? _MTN
? debug.c
? debug.h
? fs
? fsdir
? img
? patch.20101219
? preimg
? resize_ffs
? resize_ffs-byteswap-ufs2.patch
? resize_ffs.c.1.22
? resize_ffs.cat8
? resize_ffs.html8
? rs.diff
? shrinkufs2
? testimage
? ufs2.patch
Index: Makefile
===================================================================
RCS file: /cvsroot/src/sbin/resize_ffs/Makefile,v
retrieving revision 1.2
diff -u -r1.2 Makefile
--- Makefile    26 Apr 2009 05:57:48 -0000      1.2
+++ Makefile    21 Dec 2010 20:17:58 -0000
@@ -1,8 +1,13 @@
 #      $NetBSD: Makefile,v 1.2 2009/04/26 05:57:48 lukem Exp $
 
+.include <bsd.own.mk>
+
 WARNS?=        3       # XXX: sign-compare issues
 
 PROG=resize_ffs
 MAN=resize_ffs.8
+SRCS=resize_ffs.c ffs_bswap.c
+
+.PATH: ${NETBSDSRCDIR}/sys/ufs/ffs
 
 .include <bsd.prog.mk>
Index: TODO
===================================================================
RCS file: /cvsroot/src/sbin/resize_ffs/TODO,v
retrieving revision 1.7
diff -u -r1.7 TODO
--- TODO        8 Dec 2010 15:23:53 -0000       1.7
+++ TODO        21 Dec 2010 20:17:58 -0000
@@ -1,6 +1,6 @@
 resize_ffs(8) TODO list
 
-* Add support for swapped byte order
-* Fix support for disk blocks of size other than 512 bytes
-* Extend to support UFS2.  Probably growth first, then shrinking separately.
+* Test and likely fix support for disk blocks of size other than 512 bytes
+* Support shrinking UFS2 file systems
+* Make the output a bit more verbose, similar to newfs(8)
 * Expand the testing done in src/tests/sbin/resize_ffs
Index: resize_ffs.8
===================================================================
RCS file: /cvsroot/src/sbin/resize_ffs/resize_ffs.8,v
retrieving revision 1.9
diff -u -r1.9 resize_ffs.8
--- resize_ffs.8        20 Dec 2010 00:49:23 -0000      1.9
+++ resize_ffs.8        21 Dec 2010 20:17:58 -0000
@@ -9,22 +9,22 @@
 .\"  X  Against HTML               mouse%rodents.montreal.qc.ca@localhost
 .\" / \ Email!           7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B
 .\"
-.Dd October 30, 2010
+.Dd December 21, 2010
 .Dt RESIZE_FFS 8
 .Os
 .Sh NAME
 .Nm resize_ffs
-.Nd resize an on-disk file system
+.Nd resize a file system on disk or in a file
 .Sh SYNOPSIS
 .Nm
 .Op Fl y
 .Op Fl s Ar size
-.Ar file-system-raw-device
+.Ar special
 .Sh DESCRIPTION
 .Nm
-resizes a file system on disk.
-.Ar file-system-raw-device
-is the name of the raw disk device where the file system resides;
+resizes a file system.
+.Ar special
+is the name of the raw disk device or file where the file system resides;
 (Sectors are almost always 512 bytes, and
 .Nm
 can both grow and shrink file systems.
@@ -53,7 +53,7 @@
 .Nm
 will grow the file system to the underlying device size which is
 determined from
-.Ar file-system-raw-device .
+.Ar special .
 .Pp
 The options are as follows:
 .Bl -tag -width indent
@@ -66,10 +66,6 @@
 .Nm .
 .El
 .Sh WARNING
-.Nm
-should still be considered experimental.
-It still needs to be validated with a rigorous regression test
-suite.
 .Em Interrupting
 .Nm
 .Em "may leave your file system in an inconsistent state and require a"
@@ -88,16 +84,7 @@
 It's probably wise to
 .Xr fsck 8
 the file system before and after, just to be safe.
-.\" Remove this when (if) fsck gets fixed.
-.Pp
-There is a bug somewhere in
-.Xr fsck 8 ;
-it does not check certain data structures enough.
-A past version of this program had a bug that produced corrupted
-rotation layout summary tables, which would panic the kernel.
-This bug is believed fixed, and there are currently no
-known bugs in the program.
-However, you should be aware that just because
+You should be aware that just because
 .Xr fsck 8
 is happy with the file system does not mean it is intact.
 .Sh EXIT STATUS
@@ -127,15 +114,16 @@
 .Sh AUTHORS
 .An der Mouse
 .Aq mouse%rodents.montreal.qc.ca@localhost
+(primary author)
+.An Jeff Rizzo
+.Aq riz%NetBSD.org@localhost
+(Byteswapped file system and UFS2 support)
 .Pp
 A big bug-finding kudos goes to John Kohl for finding the rotational
 layout bug referred to in the
 .Sx WARNING
 section above.
 .Sh BUGS
-Has not been tested and probably won't work on opposite-endian file
-systems.
-.Pp
 Can fail to shrink a file system when there actually is enough space,
 because it does not distinguish between a block allocated as a block
 and a block fully occupied by two or more frags.
@@ -146,4 +134,4 @@
 Has no intelligence whatever when it comes to allocating blocks to copy
 data into when shrinking.
 .Pp
-Doesn't work with FFSv2 file systems.
+Doesn't currently support shrinking FFSv2 file systems.
Index: resize_ffs.c
===================================================================
RCS file: /cvsroot/src/sbin/resize_ffs/resize_ffs.c,v
retrieving revision 1.24
diff -u -r1.24 resize_ffs.c
--- resize_ffs.c        14 Dec 2010 21:49:21 -0000      1.24
+++ resize_ffs.c        21 Dec 2010 20:17:58 -0000
@@ -27,11 +27,6 @@
  *  definitions (which in at least a few cases depend on the lexical
  *  scoping gcc provides, so they can't be trivially moved outside).
  *
- * It will not do anything useful with file systems in other than
- *  host-native byte order.  This really should be fixed (it's largely
- *  a historical accident; the original version of this program is
- *  older than bi-endian support in FFS).
- *
  * Many thanks go to John Kohl <jtk%NetBSD.org@localhost> for finding bugs: the
  *  one responsible for the "realloccgblk: can't find blk in cyl"
  *  problem and a more minor one which left fs_dsize wrong when
@@ -49,6 +44,7 @@
 #include <sys/mman.h>
 #include <sys/param.h>         /* MAXFRAG */
 #include <ufs/ffs/fs.h>
+#include <ufs/ffs/ffs_extern.h>
 #include <ufs/ufs/dir.h>
 #include <ufs/ufs/dinode.h>
 #include <ufs/ufs/ufs_bswap.h> /* ufs_rw32 */
@@ -62,7 +58,7 @@
 #include <unistd.h>
 
 /* new size of file system, in sectors */
-static uint32_t newsize;
+static uint64_t newsize;
 
 /* fd open onto disk device or file */
 static int fd;
@@ -85,6 +81,22 @@
 static char sbbuf[2 * SBLOCKSIZE]
        __attribute__((__aligned__(__alignof__(struct fs))));
 
+union dinode {
+       struct ufs1_dinode dp1;
+       struct ufs2_dinode dp2;
+};
+#define DIP(dp, field)                                                       \
+       ((is_ufs2) ?                                                          \
+           (dp)->dp2.field : (dp)->dp1.field)
+
+#define DIP_ASSIGN(dp, field, value)                                         \
+       do {                                                                  \
+               if (is_ufs2)                                                  \
+                       (dp)->dp2.field = (value);                            \
+               else                                                          \
+                       (dp)->dp1.field = (value);                            \
+       } while (0)
+
 /* a cg's worth of brand new squeaky-clean inodes */
 static struct ufs1_dinode *zinodes;
 
@@ -108,7 +120,12 @@
 static unsigned int *inomove;
 
 /* in-core copies of all inodes in the fs, indexed by inumber */
-static struct ufs1_dinode *inodes;
+union dinode *inodes;
+
+void *ibuf;    /* ptr to fs block-sized buffer for reading/writing inodes */
+
+/* byteswapped inodes */
+union dinode *sinodes;
 
 /* per-inode flags, indexed by inumber */
 static unsigned char *iflags;
@@ -119,17 +136,16 @@
 
 /* resize_ffs works directly on dinodes, adapt blksize() */
 #define dblksize(fs, dip, lbn) \
-    (((lbn) >= NDADDR || (dip)->di_size >= lblktosize(fs, (lbn) + 1)) \
-    ? (fs)->fs_bsize \
-    : (fragroundup(fs, blkoff(fs, (dip)->di_size))))
+       (((lbn) >= NDADDR || DIP((dip), di_size) >= lblktosize(fs, (lbn) + 1)) \
+           ? (fs)->fs_bsize                                                   \
+           : (fragroundup(fs, blkoff(fs, DIP((dip), di_size)))))
 
 
 /*
- * Number of disk sectors per block/fragment; assumes DEV_BSIZE byte
- * sector size. 
+ * Number of disk sectors per block/fragment
  */ 
-#define NSPB(fs)       ((fs)->fs_old_nspf << (fs)->fs_fragshift)
-#define NSPF(fs)       ((fs)->fs_old_nspf)
+#define NSPB(fs)       (fsbtodb((fs),1) << (fs)->fs_fragshift)
+#define NSPF(fs)       (fsbtodb((fs),1))
 
 /* global flags */
 int is_ufs2 = 0;
@@ -198,7 +214,8 @@
                if (rv < 0)
                        err(EXIT_FAILURE, "read failed");
                if (rv != size)
-                       errx(EXIT_FAILURE, "read: wanted %d, got %d", size, rv);
+                       errx(EXIT_FAILURE, "read: wanted %d, got %d",
+                           size, rv);
        }
 }
 /*
@@ -310,10 +327,14 @@
        for (cg = 0; cg < oldsb->fs_ncg; cg++) {
                cgs[cg] = (struct cg *) cgp;
                readat(fsbtodb(oldsb, cgtod(oldsb, cg)), cgp, cgblksz);
+               if (needswap)
+                       ffs_cg_swap(cgs[cg],cgs[cg],oldsb);
                cgflags[cg] = 0;
                cgp += cgblksz;
        }
        readat(fsbtodb(oldsb, oldsb->fs_csaddr), csums, oldsb->fs_cssize);
+       if (needswap)
+               ffs_csum_swap(csums,csums,oldsb->fs_cssize);
 }
 /*
  * Set n bits, starting with bit #base, in the bitmap pointed to by
@@ -363,7 +384,7 @@
                base = (base & ~7) + 8;
        }
        if (n >= 8) {
-               bzero(bitvec + (base >> 3), n >> 3);
+               memset(bitvec + (base >> 3), 0, n >> 3);
                base += n & ~7;
                n &= 7;
        }
@@ -437,6 +458,7 @@
        int dmax;               /* Offset of end of post-inode data area */
        int i;                  /* Generic loop index */
        int n;                  /* Generic count */
+       int start;              /* start of cg maps */
 
        cg = cgs[cgn];
        /* Place the data areas */
@@ -446,49 +468,64 @@
        dmax = newsb->fs_size - base;
        if (dmax > newsb->fs_fpg)
                dmax = newsb->fs_fpg;
+       start = &cg->cg_space[0] - (unsigned char *) cg;
        /*
          * Clear out the cg - assumes all-0-bytes is the correct way
          * to initialize fields we don't otherwise touch, which is
          * perhaps not the right thing to do, but it's what fsck and
          * mkfs do.
          */
-       bzero(cg, newsb->fs_cgsize);
-       cg->cg_old_time = newsb->fs_time;
+       memset(cg, 0, newsb->fs_cgsize);
        if (newsb->fs_old_flags & FS_FLAGS_UPDATED)
                cg->cg_time = newsb->fs_time;
        cg->cg_magic = CG_MAGIC;
        cg->cg_cgx = cgn;
-       cg->cg_old_ncyl = newsb->fs_old_cpg;
-       /* Update the cg_old_ncyl value for the last cylinder. */
-       if (cgn == newsb->fs_ncg - 1) {
-               if ((newsb->fs_old_flags & FS_FLAGS_UPDATED) == 0)
-                       cg->cg_old_ncyl = newsb->fs_old_ncyl % 
newsb->fs_old_cpg;
-       }
-       cg->cg_old_niblk = newsb->fs_ipg;
+       cg->cg_niblk = newsb->fs_ipg;
        cg->cg_ndblk = dmax;
-       /* Set up the bitmap pointers.  We have to be careful to lay out the
-        * cg _exactly_ the way mkfs and fsck do it, since fsck compares the
-        * _entire_ cg against a recomputed cg, and whines if there is any
-        * mismatch, including the bitmap offsets. */
-       /* XXX update this comment when fsck is fixed */
-       cg->cg_old_btotoff = &cg->cg_space[0] - (unsigned char *) cg;
-       cg->cg_old_boff = cg->cg_old_btotoff
-           + (newsb->fs_old_cpg * sizeof(int32_t));
-       cg->cg_iusedoff = cg->cg_old_boff +
-           (newsb->fs_old_cpg * newsb->fs_old_nrpos * sizeof(int16_t));
+
+       if (is_ufs2) {
+               cg->cg_time = newsb->fs_time;
+               cg->cg_initediblk = newsb->fs_ipg < 2 * INOPB(newsb) ?
+                   newsb->fs_ipg : 2 * INOPB(newsb);
+               cg->cg_iusedoff = start;
+       } else {
+               cg->cg_old_time = newsb->fs_time;
+               cg->cg_old_niblk = cg->cg_niblk;
+               cg->cg_niblk = 0;
+               cg->cg_initediblk = 0;
+       
+       
+               cg->cg_old_ncyl = newsb->fs_old_cpg;
+               /* Update the cg_old_ncyl value for the last cylinder. */
+               if (cgn == newsb->fs_ncg - 1) {
+                       if ((newsb->fs_old_flags & FS_FLAGS_UPDATED) == 0)
+                               cg->cg_old_ncyl = newsb->fs_old_ncyl %
+                                   newsb->fs_old_cpg;
+               }
+
+               /* Set up the bitmap pointers.  We have to be careful
+                * to lay out the cg _exactly_ the way mkfs and fsck
+                * do it, since fsck compares the _entire_ cg against
+                * a recomputed cg, and whines if there is any
+                * mismatch, including the bitmap offsets. */
+               /* XXX update this comment when fsck is fixed */
+               cg->cg_old_btotoff = start;
+               cg->cg_old_boff = cg->cg_old_btotoff
+                   + (newsb->fs_old_cpg * sizeof(int32_t));
+               cg->cg_iusedoff = cg->cg_old_boff +
+                   (newsb->fs_old_cpg * newsb->fs_old_nrpos * sizeof(int16_t));
+       }
        cg->cg_freeoff = cg->cg_iusedoff + howmany(newsb->fs_ipg, NBBY);
        if (newsb->fs_contigsumsize > 0) {
                cg->cg_nclusterblks = cg->cg_ndblk / newsb->fs_frag;
                cg->cg_clustersumoff = cg->cg_freeoff +
-                   howmany(newsb->fs_old_cpg * newsb->fs_old_spc / NSPF(newsb),
-                   NBBY) - sizeof(int32_t);
+                   howmany(newsb->fs_fpg, NBBY) - sizeof(int32_t);
                cg->cg_clustersumoff =
                    roundup(cg->cg_clustersumoff, sizeof(int32_t));
                cg->cg_clusteroff = cg->cg_clustersumoff +
                    ((newsb->fs_contigsumsize + 1) * sizeof(int32_t));
                cg->cg_nextfreeoff = cg->cg_clusteroff +
-                   howmany(newsb->fs_old_cpg * newsb->fs_old_spc / NSPB(newsb),
-                   NBBY);
+                   howmany(fragstoblks(newsb,newsb->fs_fpg), NBBY);
                n = dlow / newsb->fs_frag;
                if (n > 0) {
                        set_bits(cg_clustersfree(cg, 0), 0, n);
@@ -497,11 +534,10 @@
                }
        } else {
                cg->cg_nextfreeoff = cg->cg_freeoff +
-                   howmany(newsb->fs_old_cpg * newsb->fs_old_spc / NSPF(newsb),
-                   NBBY);
+                   howmany(newsb->fs_fpg, NBBY);
        }
        /* Mark the data areas as free; everything else is marked busy by the
-        * bzero up at the top. */
+        * memset() up at the top. */
        set_bits(cg_blksfree(cg, 0), 0, dlow);
        set_bits(cg_blksfree(cg, 0), dhigh, dmax - dhigh);
        /* Initialize summary info */
@@ -509,19 +545,23 @@
        cg->cg_cs.cs_nifree = newsb->fs_ipg;
        cg->cg_cs.cs_nbfree = dlow / newsb->fs_frag;
        cg->cg_cs.cs_nffree = 0;
-
-       /* This is the simplest way of doing this; we perhaps could compute
-        * the correct cg_blktot()[] and cg_blks()[] values other ways, but it
-        * would be complicated and hardly seems worth the effort.  (The
-        * reason there isn't frag-at-beginning and frag-at-end code here,
-        * like the code below for the post-inode data area, is that the
-        * pre-sb data area always starts at 0, and thus is block-aligned, and
+       
+       /* This is the simplest way of doing this; we perhaps could
+        * compute the correct cg_blktot()[] and cg_blks()[] values
+        * other ways, but it would be complicated and hardly seems
+        * worth the effort.  (The reason there isn't
+        * frag-at-beginning and frag-at-end code here, like the code
+        * below for the post-inode data area, is that the pre-sb data
+        * area always starts at 0, and thus is block-aligned, and
         * always ends at the sb, which is block-aligned.) */
-       for (i = 0; i < dlow; i += newsb->fs_frag) {
-               old_cg_blktot(cg, 0)[old_cbtocylno(newsb, i)]++;
-               old_cg_blks(newsb, cg,
-                   old_cbtocylno(newsb, i), 0)[old_cbtorpos(newsb, i)]++;
-       }
+       if ((newsb->fs_old_flags & FS_FLAGS_UPDATED) == 0)      
+               for (i = 0; i < dlow; i += newsb->fs_frag) {
+                       old_cg_blktot(cg, 0)[old_cbtocylno(newsb, i)]++;
+                       old_cg_blks(newsb, cg,
+                           old_cbtocylno(newsb, i),
+                           0)[old_cbtorpos(newsb, i)]++;
+               }
+
        /* Deal with a partial block at the beginning of the post-inode area.
         * I'm not convinced this can happen - I think the inodes are always
         * block-aligned and always an integral number of blocks - but it's
@@ -542,28 +582,34 @@
                        cg_clustersum(cg, 0)[(n > newsb->fs_contigsumsize) ?
                            newsb->fs_contigsumsize : n]++;
                }
-               for (i = n; i > 0; i--) {
-                       old_cg_blktot(cg, 0)[old_cbtocylno(newsb, dhigh)]++;
-                       old_cg_blks(newsb, cg,
-                           old_cbtocylno(newsb, dhigh), 0)[old_cbtorpos(newsb,
-                               dhigh)]++;
-                       dhigh += newsb->fs_frag;
-               }
+               if (is_ufs2 == 0)
+                       for (i = n; i > 0; i--) {
+                               old_cg_blktot(cg, 0)[old_cbtocylno(newsb,
+                                           dhigh)]++;
+                               old_cg_blks(newsb, cg,
+                                   old_cbtocylno(newsb, dhigh),
+                                   0)[old_cbtorpos(newsb,
+                                           dhigh)]++;
+                               dhigh += newsb->fs_frag;
+                       }
        }
-       /* Deal with any leftover frag at the end of the cg. */
-       i = dmax - dhigh;
-       if (i) {
-               cg->cg_frsum[i]++;
-               cg->cg_cs.cs_nffree += i;
+       if (is_ufs2 == 0) {
+               /* Deal with any leftover frag at the end of the cg. */
+               i = dmax - dhigh;
+               if (i) {
+                       cg->cg_frsum[i]++;
+                       cg->cg_cs.cs_nffree += i;
+               }
        }
        /* Update the csum info. */
        csums[cgn] = cg->cg_cs;
        newsb->fs_cstotal.cs_nffree += cg->cg_cs.cs_nffree;
        newsb->fs_cstotal.cs_nbfree += cg->cg_cs.cs_nbfree;
        newsb->fs_cstotal.cs_nifree += cg->cg_cs.cs_nifree;
-       /* Write out the cleared inodes. */
-       writeat(fsbtodb(newsb, cgimin(newsb, cgn)), zinodes,
-           newsb->fs_ipg * sizeof(struct ufs1_dinode));
+       if (is_ufs2 == 0)
+               /* Write out the cleared inodes. */
+               writeat(fsbtodb(newsb, cgimin(newsb, cgn)), zinodes,
+                   newsb->fs_ipg * sizeof(struct ufs1_dinode));
        /* Dirty the cg. */
        cgflags[cgn] |= CGF_DIRTY;
 }
@@ -802,7 +848,8 @@
                if (j <= 0) {
                        /* Win win - all the frags we want are free. Allocate
                         * 'em and we're all done.  */
-                       for ((i = newsb->fs_csaddr + ntot - nnew), (j = nnew); 
j > 0; i++, j--) {
+                       for ((i = newsb->fs_csaddr + ntot - nnew),
+                                (j = nnew); j > 0; i++, j--) {
                                alloc_frag(i);
                        }
                        return;
@@ -879,7 +926,7 @@
        /* Allocate and clear the new-inode area, in case we add any cgs. */
        zinodes = alloconce(newsb->fs_ipg * sizeof(struct ufs1_dinode),
                             "zeroed inodes");
-       bzero(zinodes, newsb->fs_ipg * sizeof(struct ufs1_dinode));
+       memset(zinodes, 0, newsb->fs_ipg * sizeof(struct ufs1_dinode));
        /* Update the size. */
        newsb->fs_size = dbtofsb(newsb, newsize);
        /* Did we actually not grow?  (This can happen if newsize is less than
@@ -896,10 +943,15 @@
         * what to write is irrelevant; it's just something handy that's known
         * to be at least one frag in size.) */
        writeat(fsbtodb(newsb,newsb->fs_size - 1), &sbbuf, newsb->fs_fsize);
-       /* Update fs_old_ncyl and fs_ncg. */
-       newsb->fs_old_ncyl = howmany(newsb->fs_size * NSPF(newsb),
-           newsb->fs_old_spc);
-       newsb->fs_ncg = howmany(newsb->fs_old_ncyl, newsb->fs_old_cpg);
+       if (is_ufs2)
+               newsb->fs_ncg = howmany(newsb->fs_size, newsb->fs_fpg);
+       else {
+               /* Update fs_old_ncyl and fs_ncg. */
+               newsb->fs_old_ncyl = howmany(newsb->fs_size * NSPF(newsb),
+                   newsb->fs_old_spc);
+               newsb->fs_ncg = howmany(newsb->fs_old_ncyl, newsb->fs_old_cpg);
+       }
+       
        /* Does the last cg end before the end of its inode area? There is no
         * reason why this couldn't be handled, but it would complicate a lot
         * of code (in all file system code - fsck, kernel, etc) because of the
@@ -919,13 +971,15 @@
            newsb->fs_ncg * sizeof(struct csum));
        if (newsb->fs_cssize > oldsb->fs_cssize)
                csums = nfrealloc(csums, newsb->fs_cssize, "new cg summary");
-       /* If we're adding any cgs, realloc structures and set up the new cgs. 
*/
+       /* If we're adding any cgs, realloc structures and set up the new
+          cgs. */
        if (newsb->fs_ncg > oldsb->fs_ncg) {
                char *cgp;
                cgs = nfrealloc(cgs, newsb->fs_ncg * sizeof(struct cg *),
                                 "cg pointers");
                cgflags = nfrealloc(cgflags, newsb->fs_ncg, "cg flags");
-               bzero(cgflags + oldsb->fs_ncg, newsb->fs_ncg - oldsb->fs_ncg);
+               memset(cgflags + oldsb->fs_ncg, 0,
+                   newsb->fs_ncg - oldsb->fs_ncg);
                cgp = alloconce((newsb->fs_ncg - oldsb->fs_ncg) * cgblksz,
                                 "cgs");
                for (i = oldsb->fs_ncg; i < newsb->fs_ncg; i++) {
@@ -965,7 +1019,7 @@
  *  over either the old or the new file system's set of inodes.
  */
 static void
-map_inodes(void (*fn) (struct ufs1_dinode * di, unsigned int, void *arg),
+map_inodes(void (*fn) (union dinode * di, unsigned int, void *arg),
           int ncg, void *cbarg) {
        int i;
        int ni;
@@ -992,14 +1046,14 @@
  * function and returns number of bytes occupied in file (actually,
  * rounded up to a frag boundary).  The name is historical.  */
 static int
-markblk(mark_callback_t fn, struct ufs1_dinode * di, int bn, off_t o)
+markblk(mark_callback_t fn, union dinode * di, int bn, off_t o)
 {
        int sz;
        int nb;
-       if (o >= di->di_size)
+       if (o >= DIP(di,di_size))
                return (0);
        sz = dblksize(newsb, di, lblkno(newsb, o));
-       nb = (sz > di->di_size - o) ? di->di_size - o : sz;
+       nb = (sz > DIP(di,di_size) - o) ? DIP(di,di_size) - o : sz;
        if (bn)
                (*fn) (bn, numfrags(newsb, sz), nb, MDB_DATA);
        return (sz);
@@ -1011,7 +1065,7 @@
  * For the sake of update_for_data_move(), we read the indirect block
  * _after_ making the _PRE callback.  The name is historical.  */
 static int
-markiblk(mark_callback_t fn, struct ufs1_dinode * di, int bn, off_t o, int lev)
+markiblk(mark_callback_t fn, union dinode * di, int bn, off_t o, int lev)
 {
        int i;
        int j;
@@ -1032,6 +1086,9 @@
        }
        (*fn) (bn, newsb->fs_frag, newsb->fs_bsize, MDB_INDIR_PRE);
        readat(fsbtodb(newsb, bn), indirblks[lev], newsb->fs_bsize);
+       if (needswap)
+               for (i = 0; i < howmany(MAXBSIZE, sizeof(int32_t)); i++)
+                       indirblks[lev][i] = bswap32(indirblks[lev][i]);
        tot = 0;
        for (i = 0; i < NINDIR(newsb); i++) {
                j = markiblk(fn, di, indirblks[lev][i], o, lev - 1);
@@ -1058,7 +1115,7 @@
  *  of a file).
  */
 static void
-map_inode_data_blocks(struct ufs1_dinode * di, mark_callback_t fn)
+map_inode_data_blocks(union dinode * di, mark_callback_t fn)
 {
        off_t o;                /* offset within  inode */
        int inc;                /* increment for o - maybe should be off_t? */
@@ -1067,7 +1124,7 @@
        /* Scan the direct blocks... */
        o = 0;
        for (b = 0; b < NDADDR; b++) {
-               inc = markblk(fn, di, di->di_db[b], o);
+               inc = markblk(fn, di, DIP(di,di_db[b]), o);
                if (inc == 0)
                        break;
                o += inc;
@@ -1075,7 +1132,7 @@
        /* ...and the indirect blocks. */
        if (inc) {
                for (b = 0; b < NIADDR; b++) {
-                       inc = markiblk(fn, di, di->di_ib[b], o, b);
+                       inc = markiblk(fn, di, DIP(di,di_ib[b]), o, b);
                        if (inc == 0)
                                return;
                        o += inc;
@@ -1084,13 +1141,13 @@
 }
 
 static void
-dblk_callback(struct ufs1_dinode * di, unsigned int inum, void *arg)
+dblk_callback(union dinode * di, unsigned int inum, void *arg)
 {
        mark_callback_t fn;
        fn = (mark_callback_t) arg;
-       switch (di->di_mode & IFMT) {
+       switch (DIP(di,di_mode) & IFMT) {
        case IFLNK:
-               if (di->di_size > newsb->fs_maxsymlinklen) {
+               if (DIP(di,di_size) > newsb->fs_maxsymlinklen) {
        case IFDIR:
        case IFREG:
                        map_inode_data_blocks(di, fn);
@@ -1129,18 +1186,53 @@
 static void
 loadinodes(void)
 {
-       int cg;
-       struct ufs1_dinode *iptr;
+       int imax, ino, i, j;
+       struct ufs1_dinode *dp1 = NULL;
+       struct ufs2_dinode *dp2 = NULL;
+       
+
+       /* read inodes one fs block at a time and copy them */
 
        inodes = alloconce(oldsb->fs_ncg * oldsb->fs_ipg *
-           sizeof(struct ufs1_dinode), "inodes");
+           sizeof(union dinode), "inodes");
        iflags = alloconce(oldsb->fs_ncg * oldsb->fs_ipg, "inode flags");
-       bzero(iflags, oldsb->fs_ncg * oldsb->fs_ipg);
-       iptr = inodes;
-       for (cg = 0; cg < oldsb->fs_ncg; cg++) {
-               readat(fsbtodb(oldsb, cgimin(oldsb, cg)), iptr,
-                   oldsb->fs_ipg * sizeof(struct ufs1_dinode));
-               iptr += oldsb->fs_ipg;
+       memset(iflags, 0, oldsb->fs_ncg * oldsb->fs_ipg);
+       
+       ibuf = nfmalloc(oldsb->fs_bsize,"inode block buf");
+       if (is_ufs2)
+               dp2 = (struct ufs2_dinode *)ibuf;
+       else
+               dp1 = (struct ufs1_dinode *)ibuf;
+       
+       for (ino = 0,imax = oldsb->fs_ipg * oldsb->fs_ncg; ino < imax; ) {
+               readat(fsbtodb(oldsb, ino_to_fsba(oldsb, ino)), ibuf,
+                   oldsb->fs_bsize);
+
+               for (i = 0; i < oldsb->fs_inopb; i++) {
+                       if (is_ufs2) {
+                               if (needswap) {
+                                       ffs_dinode2_swap(&(dp2[i]), &(dp2[i]));
+                                       for (j = 0; j < NDADDR + NIADDR; j++)
+                                               dp2[i].di_db[j] =
+                                                   bswap32(dp2[i].di_db[j]);
+                               }
+                               memcpy(&inodes[ino].dp2, &dp2[i],
+                                   sizeof(struct ufs2_dinode));
+                       } else {
+                               if (needswap) {
+                                       ffs_dinode1_swap(&(dp1[i]), &(dp1[i]));
+                                       for (j = 0; j < NDADDR + NIADDR; j++)
+                                               dp1[i].di_db[j] =
+                                                   bswap32(dp1[i].di_db[j]);
+                               }
+                               memcpy(&inodes[ino].dp1, &dp1[i],
+                                   sizeof(struct ufs1_dinode));
+                       }
+                           if (++ino > imax)
+                                   errx(EXIT_FAILURE,
+                                       "Exceeded number of inodes");
+               }
+
        }
 }
 /*
@@ -1204,23 +1296,24 @@
 static void
 evict_data(struct cg * cg, unsigned int minfrag, unsigned int nfrag)
 {
-       int base;               /* base of cg (in frags from beginning of fs) */
+       int base;       /* base of cg (in frags from beginning of fs) */
 
 
        base = cgbase(oldsb, cg->cg_cgx);
-       /* Does the boundary fall in the middle of a block?  To avoid breaking
-        * between frags allocated as consecutive, we always evict the whole
-        * block in this case, though one could argue we should check to see
-        * if the frag before or after the break is unallocated. */
+       /* Does the boundary fall in the middle of a block?  To avoid
+        * breaking between frags allocated as consecutive, we always
+        * evict the whole block in this case, though one could argue
+        * we should check to see if the frag before or after the
+        * break is unallocated. */
        if (minfrag % oldsb->fs_frag) {
                int n;
                n = minfrag % oldsb->fs_frag;
                minfrag -= n;
                nfrag += n;
        }
-       /* Do whole blocks.  If a block is wholly free, skip it; if wholly
-        * allocated, move it in toto.  If neither, call fragmove() to move
-        * the frags to new locations. */
+       /* Do whole blocks.  If a block is wholly free, skip it; if
+        * wholly allocated, move it in toto.  If neither, call
+        * fragmove() to move the frags to new locations. */
        while (nfrag >= oldsb->fs_frag) {
                if (!blk_is_set(cg_blksfree(cg, 0), minfrag, oldsb->fs_frag)) {
                        if (blk_is_clr(cg_blksfree(cg, 0), minfrag,
@@ -1314,7 +1407,6 @@
 movemap_blocks(int32_t * vec, int n)
 {
        int rv;
-
        rv = 0;
        for (; n > 0; n--, vec++) {
                if (blkmove[*vec] != *vec) {
@@ -1325,19 +1417,27 @@
        return (rv);
 }
 static void
-moveblocks_callback(struct ufs1_dinode * di, unsigned int inum, void *arg)
+moveblocks_callback(union dinode * di, unsigned int inum, void *arg)
 {
-       switch (di->di_mode & IFMT) {
+       void *dblkptr, *iblkptr; /* XXX */
+       switch (DIP(di,di_mode) & IFMT) {
        case IFLNK:
-               if (di->di_size > oldsb->fs_maxsymlinklen) {
+               if (DIP(di,di_size) > oldsb->fs_maxsymlinklen) {
        case IFDIR:
        case IFREG:
-                       /* don't || these two calls; we need their
-                        * side-effects */
-                       if (movemap_blocks(&di->di_db[0], NDADDR)) {
+               if (is_ufs2) {
+                       dblkptr = &(di->dp2.di_db[0]);
+                       iblkptr = &(di->dp2.di_ib[0]);
+               } else {
+                       dblkptr = &(di->dp1.di_db[0]);
+                       iblkptr = &(di->dp1.di_ib[0]);
+               }
+               /* don't || these two calls; we need their
+                * side-effects */
+               if (movemap_blocks(dblkptr, NDADDR)) {
                                iflags[inum] |= IF_DIRTY;
                        }
-                       if (movemap_blocks(&di->di_ib[0], NIADDR)) {
+               if (movemap_blocks(iblkptr, NIADDR)) {
                                iflags[inum] |= IF_DIRTY;
                        }
                }
@@ -1349,10 +1449,18 @@
 moveindir_callback(unsigned int off, unsigned int nfrag, unsigned int nbytes,
                   int kind)
 {
+       int i;
        if (kind == MDB_INDIR_PRE) {
                int32_t blk[howmany(MAXBSIZE, sizeof(int32_t))];
                readat(fsbtodb(oldsb, off), &blk[0], oldsb->fs_bsize);
+               if (needswap)
+                       for (i = 0; i < howmany(MAXBSIZE, sizeof(int32_t)); i++)
+                               blk[i] = bswap32(blk[i]);
                if (movemap_blocks(&blk[0], NINDIR(oldsb))) {
+                       if (needswap)
+                               for (i = 0; i < howmany(MAXBSIZE,
+                                       sizeof(int32_t)); i++)
+                                       blk[i] = bswap32(blk[i]);
                        writeat(fsbtodb(oldsb, off), &blk[0], oldsb->fs_bsize);
                }
        }
@@ -1390,10 +1498,11 @@
 static void
 flush_inodes(void)
 {
-       int i;
-       int ni;
-       int m;
+       int i, j, k, na, ni, m;
+       struct ufs1_dinode *dp1 = NULL;
+       struct ufs2_dinode *dp2 = NULL;
 
+       na = NDADDR + NIADDR;
        ni = newsb->fs_ipg * newsb->fs_ncg;
        m = INOPB(newsb) - 1;
        for (i = 0; i < ni; i++) {
@@ -1402,10 +1511,39 @@
                }
        }
        m++;
+
+       if (is_ufs2)
+               dp2 = (struct ufs2_dinode *)ibuf;
+       else
+               dp1 = (struct ufs1_dinode *)ibuf;
+       
        for (i = 0; i < ni; i += m) {
                if (iflags[i] & IF_BDIRTY) {
+                       if (is_ufs2)
+                               for (j = 0; j < m; j++) {
+                                       dp2[j] = inodes[i + j].dp2;
+                                       if (needswap) {
+                                               for (k = 0; k < na; k++)
+                                                       dp2[j].di_db[k]=
+                                                           
bswap32(dp2[j].di_db[k]);
+                                               ffs_dinode2_swap(&dp2[j],
+                                                   &dp2[j]);
+                                       }
+                               }
+                       else
+                               for (j = 0; j < m; j++) {
+                                       dp1[j] = inodes[i + j].dp1;
+                                       if (needswap) {
+                                               for (k = 0; k < na; k++)
+                                                       dp1[j].di_db[k]=
+                                                           
bswap32(dp1[j].di_db[k]);
+                                               ffs_dinode1_swap(&dp1[j],
+                                                   &dp1[j]);
+                                       }
+                               }
+                               
                        writeat(fsbtodb(newsb, ino_to_fsba(newsb, i)),
-                           inodes + i, newsb->fs_bsize);
+                           ibuf, newsb->fs_bsize);
                }
        }
 }
@@ -1425,7 +1563,7 @@
 
        inum = newsb->fs_ipg * cg->cg_cgx;
        for (i = 0; i < newsb->fs_ipg; i++, inum++) {
-               if (inodes[inum].di_mode != 0) {
+               if (DIP(inodes + inum,di_mode) != 0) {
                        fi = find_freeinode();
                        if (fi < 0) {
                                printf("Sorry, inodes evaporated - "
@@ -1473,18 +1611,22 @@
 {
        int rv;
 #define d ((struct direct *)buf)
-
+#define s32(x) (needswap?bswap32((x)):(x))
+#define s16(x) (needswap?bswap16((x)):(x))
+       
        rv = 0;
        while (nb > 0) {
-               if (inomove[d->d_ino] != d->d_ino) {
+               if (inomove[s32(d->d_ino)] != s32(d->d_ino)) {
                        rv++;
-                       d->d_ino = inomove[d->d_ino];
+                       d->d_ino = s32(inomove[s32(d->d_ino)]);
                }
-               nb -= d->d_reclen;
-               buf += d->d_reclen;
+               nb -= s16(d->d_reclen);
+               buf += s16(d->d_reclen);
        }
        return (rv);
 #undef d
+#undef s32
+#undef s16
 }
 /*
  * Callback function for map_inode_data_blocks, for updating a
@@ -1506,9 +1648,9 @@
        }
 }
 static void
-dirmove_callback(struct ufs1_dinode * di, unsigned int inum, void *arg)
+dirmove_callback(union dinode * di, unsigned int inum, void *arg)
 {
-       switch (di->di_mode & IFMT) {
+       switch (DIP(di,di_mode) & IFMT) {
        case IFDIR:
                map_inode_data_blocks(di, &update_dir_data);
                break;
@@ -1536,23 +1678,32 @@
        newsb->fs_time = timestamp();
        /* Update the size figures. */
        newsb->fs_size = dbtofsb(newsb, newsize);
-       newsb->fs_old_ncyl = howmany(newsb->fs_size * NSPF(newsb),
-           newsb->fs_old_spc);
-       newsb->fs_ncg = howmany(newsb->fs_old_ncyl, newsb->fs_old_cpg);
+       if (is_ufs2)
+               newsb->fs_ncg = howmany(newsb->fs_size, newsb->fs_fpg);
+       else {
+               newsb->fs_old_ncyl = howmany(newsb->fs_size * NSPF(newsb),
+                   newsb->fs_old_spc);
+               newsb->fs_ncg = howmany(newsb->fs_old_ncyl, newsb->fs_old_cpg);
+       }
        /* Does the (new) last cg end before the end of its inode area?  See
         * the similar code in grow() for more on this. */
        if (cgdmin(newsb, newsb->fs_ncg - 1) > newsb->fs_size) {
                newsb->fs_ncg--;
-               newsb->fs_old_ncyl = newsb->fs_ncg * newsb->fs_old_cpg;
-               newsb->fs_size = (newsb->fs_old_ncyl * newsb->fs_old_spc) /
-                   NSPF(newsb);
+               if (is_ufs2 == 0) {
+                       newsb->fs_old_ncyl = newsb->fs_ncg * newsb->fs_old_cpg;
+                       newsb->fs_size = (newsb->fs_old_ncyl *
+                           newsb->fs_old_spc) / NSPF(newsb);
+               } else
+                       newsb->fs_size = newsb->fs_ncg * newsb->fs_fpg;
+               
                printf("Warning: last cylinder group is too small;\n");
                printf("    dropping it.  New size = %lu.\n",
                    (unsigned long int) fsbtodb(newsb, newsb->fs_size));
        }
        /* Let's make sure we're not being shrunk into oblivion. */
        if (newsb->fs_ncg < 1) {
-               printf("Size too small - file system would have no 
cylinders\n");
+               printf("Size too small - file system would "
+                   "have no cylinders\n");
                exit(EXIT_FAILURE);
        }
        /* Initialize for block motion. */
@@ -1598,9 +1749,9 @@
                evict_data(cg, newcgsize, oldcgsize - newcgsize);
                clr_bits(cg_blksfree(cg, 0), newcgsize, oldcgsize - newcgsize);
        }
-       /* Find out whether we would run out of inodes.  (Note we haven't
-        * actually done anything to the file system yet; all those evict_data
-        * calls just update blkmove.) */
+       /* Find out whether we would run out of inodes.  (Note we
+        * haven't actually done anything to the file system yet; all
+        * those evict_data calls just update blkmove.) */
        {
                int slop;
                slop = 0;
@@ -1613,12 +1764,12 @@
                        exit(EXIT_FAILURE);
                }
        }
-       /* Copy data, then update pointers to data.  See the comment header on
-        * perform_data_move for ordering considerations. */
+       /* Copy data, then update pointers to data.  See the comment
+        * header on perform_data_move for ordering considerations. */
        perform_data_move();
        update_for_data_move();
-       /* Now do inodes.  Initialize, evict, move, update - see the comment
-        * header on perform_inode_move. */
+       /* Now do inodes.  Initialize, evict, move, update - see the
+        * comment header on perform_inode_move. */
        inomove_init();
        for (i = newsb->fs_ncg; i < oldsb->fs_ncg; i++)
                evict_inodes(cgs[i]);
@@ -1660,24 +1811,29 @@
        /* Clear counters and bitmaps. */
        cg->cg_cs.cs_nffree = 0;
        cg->cg_cs.cs_nbfree = 0;
-       bzero(&cg->cg_frsum[0], MAXFRAG * sizeof(cg->cg_frsum[0]));
-       bzero(&old_cg_blktot(cg, 0)[0],
+       memset(&cg->cg_frsum[0], 0, MAXFRAG * sizeof(cg->cg_frsum[0]));
+       memset(&old_cg_blktot(cg, 0)[0], 0,
            newsb->fs_old_cpg * sizeof(old_cg_blktot(cg, 0)[0]));
-       bzero(&old_cg_blks(newsb, cg, 0, 0)[0],
+       memset(&old_cg_blks(newsb, cg, 0, 0)[0], 0,
            newsb->fs_old_cpg * newsb->fs_old_nrpos *
            sizeof(old_cg_blks(newsb, cg, 0, 0)[0]));
        if (newsb->fs_contigsumsize > 0) {
                cg->cg_nclusterblks = cg->cg_ndblk / newsb->fs_frag;
-               bzero(&cg_clustersum(cg, 0)[1],
+               memset(&cg_clustersum(cg, 0)[1], 0,
                    newsb->fs_contigsumsize *
                    sizeof(cg_clustersum(cg, 0)[1]));
-               bzero(&cg_clustersfree(cg, 0)[0],
-                   howmany((newsb->fs_old_cpg * newsb->fs_old_spc) /
-                   NSPB(newsb), NBBY));
-       }
-       /* Scan the free-frag bitmap.  Runs of free frags are kept track of
-        * with fragrun, and recorded into cg_frsum[] and cg_cs.cs_nffree; on
-        * each block boundary, entire free blocks are recorded as well. */
+               if (is_ufs2)
+                       memset(&cg_clustersfree(cg, 0)[0], 0,
+                           howmany(newsb->fs_fpg / NSPB(newsb), NBBY));
+               else
+                       memset(&cg_clustersfree(cg, 0)[0], 0,
+                           howmany((newsb->fs_old_cpg * newsb->fs_old_spc) /
+                               NSPB(newsb), NBBY));
+       }
+       /* Scan the free-frag bitmap.  Runs of free frags are kept
+        * track of with fragrun, and recorded into cg_frsum[] and
+        * cg_cs.cs_nffree; on each block boundary, entire free blocks
+        * are recorded as well. */
        blkfree = 1;
        blkrun = 0;
        fragrun = 0;
@@ -1702,12 +1858,16 @@
                                cg->cg_cs.cs_nbfree++;
                                if (newsb->fs_contigsumsize > 0)
                                        set_bits(cg_clustersfree(cg, 0), b, 1);
-                               old_cg_blktot(cg, 0)[old_cbtocylno(newsb,
-                                   f - newsb->fs_frag)]++;
-                               old_cg_blks(newsb, cg,
-                                   old_cbtocylno(newsb, f - newsb->fs_frag),
-                                   0)[old_cbtorpos(newsb,
-                                   f - newsb->fs_frag)]++;
+                               if (is_ufs2 == 0) {
+                                       old_cg_blktot(cg, 0)[
+                                               old_cbtocylno(newsb,
+                                                   f - newsb->fs_frag)]++;
+                                       old_cg_blks(newsb, cg,
+                                           old_cbtocylno(newsb,
+                                               f - newsb->fs_frag),
+                                           0)[old_cbtorpos(newsb,
+                                                   f - newsb->fs_frag)]++;
+                               }
                                blkrun++;
                        } else {
                                if (fragrun > 0) {
@@ -1763,7 +1923,7 @@
        newsb->fs_cstotal.cs_nifree -= cg->cg_cs.cs_nifree;
        cg->cg_cs.cs_ndir = 0;
        cg->cg_cs.cs_nifree = 0;
-       bzero(&cg_inosused(cg, 0)[0], howmany(newsb->fs_ipg, NBBY));
+       memset(&cg_inosused(cg, 0)[0], 0, howmany(newsb->fs_ipg, NBBY));
        inum = cgn * newsb->fs_ipg;
        if (cgn == 0) {
                set_bits(cg_inosused(cg, 0), 0, 2);
@@ -1773,7 +1933,7 @@
                iwc = 0;
        }
        for (; iwc < newsb->fs_ipg; iwc++, inum++) {
-               switch (inodes[inum].di_mode & IFMT) {
+               switch (DIP(inodes + inum, di_mode) & IFMT) {
                case 0:
                        cg->cg_cs.cs_nifree++;
                        break;
@@ -1809,10 +1969,14 @@
                        cgs[i]->cg_rotor = 0;
                        cgs[i]->cg_frotor = 0;
                        cgs[i]->cg_irotor = 0;
+                       if (needswap)
+                               ffs_cg_swap(cgs[i],cgs[i],newsb);
                        writeat(fsbtodb(newsb, cgtod(newsb, i)), cgs[i],
                            cgblksz);
                }
        }
+       if (needswap)
+               ffs_csum_swap(csums,csums,newsb->fs_cssize);
        writeat(fsbtodb(newsb, newsb->fs_csaddr), csums, newsb->fs_cssize);
 }
 /*
@@ -1836,9 +2000,14 @@
                newsb->fs_old_cstotal.cs_nffree = newsb->fs_cstotal.cs_nffree;
                /* fill fs_old_postbl_start with 256 bytes of 0xff? */
        }
+       /* copy newsb back to oldsb, so we can use it for offsets if
+          newsb has been swapped for writing to disk */
+       memcpy(oldsb, newsb, SBLOCKSIZE);
+       if (needswap)
+               ffs_sb_swap(newsb,newsb);
        writeat(where /  DEV_BSIZE, newsb, SBLOCKSIZE);
-       for (i = 0; i < newsb->fs_ncg; i++) {
-               writeat(fsbtodb(newsb, cgsblock(newsb, i)), newsb, SBLOCKSIZE);
+       for (i = 0; i < oldsb->fs_ncg; i++) {
+               writeat(fsbtodb(oldsb, cgsblock(oldsb, i)), newsb, SBLOCKSIZE);
        }
 }
 
@@ -1960,6 +2129,8 @@
        }
        if (where == (off_t)-1)
                errx(EXIT_FAILURE, "Bad magic number");
+       if (needswap)
+               ffs_sb_swap(oldsb,oldsb);
        if (oldsb->fs_magic == FS_UFS1_MAGIC &&
            (oldsb->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
                oldsb->fs_csaddr = oldsb->fs_old_csaddr;
@@ -1972,11 +2143,7 @@
                /* any others? */
                printf("Resizing with ffsv1 superblock\n");
        }
-       if (is_ufs2)
-               errx(EXIT_FAILURE, "ffsv2 file systems currently unsupported.");
-       if (needswap)
-               errx(EXIT_FAILURE, "Swapped byte order file system detected"
-                   " - currently unsupported.");
+
        oldsb->fs_qbmask = ~(int64_t) oldsb->fs_bmask;
        oldsb->fs_qfmask = ~(int64_t) oldsb->fs_fmask;
        if (oldsb->fs_ipg % INOPB(oldsb)) {
@@ -1984,15 +2151,17 @@
                    (int) oldsb->fs_ipg, (int) INOPB(oldsb));
                exit(EXIT_FAILURE);
        }
-       /* The superblock is bigger than struct fs (there are trailing tables,
-        * of non-fixed size); make sure we copy the whole thing.  SBLOCKSIZE 
may
-        * be an over-estimate, but we do this just once, so being generous is
-        * cheap. */
-       bcopy(oldsb, newsb, SBLOCKSIZE);
+       /* The superblock is bigger than struct fs (there are trailing
+        * tables, of non-fixed size); make sure we copy the whole
+        * thing.  SBLOCKSIZE may be an over-estimate, but we do this
+        * just once, so being generous is cheap. */
+       memcpy(newsb, oldsb, SBLOCKSIZE);
        loadcgs();
        if (newsize > fsbtodb(oldsb, oldsb->fs_size)) {
                grow();
        } else if (newsize < fsbtodb(oldsb, oldsb->fs_size)) {
+               if (is_ufs2)
+                       errx(EXIT_FAILURE,"shrinking not supported for ufs2");
                shrink();
        }
        flush_cgs();
@@ -2006,6 +2175,7 @@
 usage(void)
 {
 
-       (void)fprintf(stderr, "usage: %s [-y] [-s size] special\n", 
getprogname());
+       (void)fprintf(stderr, "usage: %s [-y] [-s size] special\n",
+           getprogname());
        exit(EXIT_FAILURE);
 }


Home | Main Index | Thread Index | Old Index