11 January 2011

Recreate a Solaris UFS FS

Have you ever wondered what options were used to create a UFS filesystem
(FS) on a Solaris host?  Normally when you ask that question, it
seems someone will refer you to passing '-N' to 'newfs'.  Unfortunately,
this response will only provide you with default parameters to build a
generic FS, not the one you are concerned with.  Our host details for
this scenario are:
        HOST:           snorkle
        PROMPT:         snorkle [0]
        OS:             Solaris 10
        CTDS:           c1t3d0s0
To start, the following uses 'newfs' to create a generic filesystem on
'c1t3d0s0':
        snorkle [0] echo "y" | /usr/sbin/newfs /dev/rdsk/c1t3d0s0
        pfexec mkfs -F ufs /dev/rdsk/c1t3d0s0 1040384 32 64 8192 1024 16 10 546 2048 t 0 -1 8 32 n
        /dev/rdsk/c1t3d0s0:     1040384 sectors in 508 cylinders of 64 tracks, 32 sectors
                508.0MB in 32 cyl groups (16 c/g, 16.00MB/g, 7680 i/g)
        super-block backups (for fsck -F ufs -o b=#) at:
         32, 32832, 65632, 98432, 131232, 164032, 196832, 229632, 262432, 295232,
         721632, 754432, 787232, 820032, 852832, 885632, 918432, 951232, 984032,
         1016832
No problems here, let's run 'newfs' again to see what it says about the
the FS options.  So that it doesn't create a new FS, we'll pass '-N' to
'newfs':
        snorkle [0] /usr/sbin/newfs -Nv /dev/rdsk/c1t3d0s0
        pfexec mkfs -F ufs -o N /dev/rdsk/c1t3d0s0 1040384 32 64 8192 1024 16 10 546 2048 t 0 -1 8 32 n
        /dev/rdsk/c1t3d0s0:     1040384 sectors in 508 cylinders of 64 tracks, 32 sectors
                508.0MB in 32 cyl groups (16 c/g, 16.00MB/g, 7680 i/g)
        super-block backups (for fsck -F ufs -o b=#) at:
         32, 32832, 65632, 98432, 131232, 164032, 196832, 229632, 262432, 295232,
         721632, 754432, 787232, 820032, 852832, 885632, 918432, 951232, 984032,
         1016832
Great, at first glance it looks like 'newfs' does work.  To illustrate
why it doesn't, we'll create a new FS on 'c1t3d0s0', though setting
some optional parameters to 'newfs'.  As an aside, the parameters that
I chose are not necessarily sane for a normal environment and are only
used to illustrate the point:
        snorkle [0] echo "y" | /usr/sbin/newfs -v -a 2 -b 4096 -c 12 -C 11 -f 512 -i 4096 -m 3 -n 6\
                -o space /dev/rdsk/c1t3d0s0
        newfs: construct a new file system /dev/rdsk/c1t3d0s0: (y/n)? y
        pfexec mkfs -F ufs /dev/rdsk/c1t3d0s0 1040384 32 64 4096 512 12 3 546 4096 s 2 -1 6 11 n
        /dev/rdsk/c1t3d0s0:     1040384 sectors in 509 cylinders of 64 tracks, 32 sectors
                508.0MB in 43 cyl groups (12 c/g, 11.99MB/g, 2816 i/g)
        super-block backups (for fsck -F ufs -o b=#) at:
         32, 24616, 49200, 73784, 98368, 122952, 147536, 172120, 196704, 221288,
         811304, 835888, 860472, 885056, 909640, 934224, 958808, 983392, 1007976,
         1032560

    verify:

        snorkle [0] /usr/sbin/newfs -Nv /dev/rdsk/c1t3d0s0
        pfexec mkfs -F ufs -o N /dev/rdsk/c1t3d0s0 1040384 32 64 8192 1024 16 10 546 2048 t 0 -1 8 32 n
        /dev/rdsk/c1t3d0s0:     1040384 sectors in 508 cylinders of 64 tracks, 32 sectors
                508.0MB in 32 cyl groups (16 c/g, 16.00MB/g, 7680 i/g)
        super-block backups (for fsck -F ufs -o b=#) at:
         32, 32832, 65632, 98432, 131232, 164032, 196832, 229632, 262432, 295232,
         721632, 754432, 787232, 820032, 852832, 885632, 918432, 951232, 984032,
         1016832
In looking at the details above, we've set quite a few options to 'newfs'
changing things such as the logical block size (4096), bytes per inode
(4096), percentage of free space (3%), etc.  Since we specified '-v'
to 'newfs', it even output the 'mkfs' command that would be run for us.
Running 'newfs' a second time with '-Nv', it reports back a completely
different 'mkfs' command than what we created the FS with.  In fact, it's
the same command that we saw initially with the generic FS creation, thus
block size (8192), bytes per inode (2048), percent of free space (10%) are
wrong.  This would be problematic if we were looking for a list of
backup superblocks.  How, then, are we supposed to figure out how the
FS was created if we didn't just set it up?  Well, there are two ways,
directly using 'mkfs' (the easy way), and using 'fstyp' (the tedious way).
Still using our "specialized" example above, 'mkfs' reports back the
appropriate details:
        snorkle [0] /usr/sbin/mkfs -m /dev/rdsk/c1t3d0s0
        mkfs -F ufs -o nsect=32,ntrack=64,bsize=4096,fragsize=512,cgsize=12,free=3,rps=546,nbpi=4081,\
        opt=s,apc=2,gap=0,nrpos=6,maxcontig=11,mtb=n /dev/rdsk/c1t3d0s0 1040384
The second and third line above are actually one complete 'mkfs' string,
though I've broken it up to be more legible.  All of the parameters
that we specified to 'newfs' to create the FS are accounted for.
Of note, 'mkfs' does some logic prior to creating the FS to adhere to
certain constraints while accounting for the parameters passed to it.
For instance, while we specified 'nbpi' to be "4096", accounting for
the actual disk geometry and the other options we've passed, 'mkfs' can
only set it to "4081".  This isn't necessarily an issue, just something
to keep in mind, especially if you decide to get your data from 'fstyp'.

Now for the hard way with 'fstyp', as a potential alternative.  We can
use 'fstyp' to get back nearly all of the information that we got from
'mkfs', though not in a simple command form:
        snorkle [0] /usr/sbin/fstyp -v /dev/rdsk/c1t3d0s0 2>/dev/null | /usr/bin/head -20
        ufs
        magic   11954   format  dynamic time    Tue Jan 11 17:31:19 2011
        sblkno  32      cblkno  48      iblkno  56      dblkno  760
        sbsize  2560    cgsize  4096    cgoffset 32     cgmask  0xffffffc0
        ncg     43      size    1040384 blocks  1009046
        bsize   4096    shift   12      mask    0xfffff000
        fsize   512     shift   9       mask    0xfffffe00
        frag    8       shift   3       fsbtodb 0
        minfree 3%      maxbpg  1024    optim   space
        maxcontig 11    rotdelay 0ms    rps     546
        csaddr  760     cssize  1024    shift   8       mask    0xffffff00
        ntrak   64      nsect   32      spc     2046    ncyl    509
        cpg     12      bpg     3069    fpg     24552   ipg     2816
        nindir  1024    inopb   32      nspf    1
        nbfree  126128  ndir    2       nifree  121084  nffree  13
        cgrotor 0       fmod    0       ronly   0       logbno  0
        version 0
        fs_reclaim is not set
        file system state is valid, fsclean is 1
        blocks available in each rotational position
The first 20 lines of output contain almost everything that we need.
Unfortunately, 'fstyp' doesn't provide 'nsect', 'apc', 'nrpos', or 'nbpi'.
These parameters are:
        nsect           number of sectors per track
        apc             alt. sectors per cylinder to reserve for bad blocks (default is 0)
        nrpos           number of rotational positions to divide a cylinder group (default is 8)
        nbpi            number of bytes per inode
If you are only using 'newfs' for FS creation, 'nsect' can be ignored
since there isn't an option for it.  If you don't have a reason to muck
with 'apc' or 'nrpos', you can ignore them.  While 'nbpi' isn't directly
listed in the 'fstyp' output, it can be inferred by some of the values
from fstyp.  In both experience and testing, the following equation has
served me well to determine 'nbpi':
        nbpi = ((((size * fsize) / (ncg * ipg)) / 1024) - fractional remainder) * 1024
Breaking this down, we get:
        nbpi = ((((1040384 * 512) / (43 * 2816)) / 1024) - fractional remainder) * 1024
               (((532676608 / 121088) / 1024) - fractional remainder) * 1024
               ((4399.08 / 1024) - fractional remainder) * 1024
               (4.29 - 0.29) * 1024
               4 * 1024
        nbpi = 4096
As stated earlier, while we set 'nbpi' to "4096" in our 'newfs' command,
'mkfs' will set it to "4081" to meet its constraints.  Using the 'mkfs'
command provided by 'newfs' for our "specialized" FS:
        pfexec mkfs -F ufs -o N /dev/rdsk/c1t3d0s0 1040384 32 64 4096 512 12 3 546 4096 s 2 -1 6 11 n
the following table details the correlation between 'newfs', 'mkfs',
and 'fstyp'.  The table order follows the order of the parameters after
'c1t3d0s0' in the 'mkfs' command above:

newfs flagsmkfs paramsfstyp namenewfs / mkfs valfstyp val
-ssizesize10403841040384
nsectnsect3232
-tntrackntrak6464
-bbsizebsize40964096
-ffragsizefsize512512
-ccgsizecpg1212
-mfreeminfree33
-rrpsrps546546
-inbpiequation*40964096
-ooptoptimspace / sspace
-ooptoptimtime / ttime
-aapc2
-dgaprotdelay0 / -10
-nnrpos6
-Cmaxcontigmaxcontig1111
-Tmtbmagicn11954
-Tmtbmagicydecade
        * mtb = multiterbyte FS availability (11954 = no / decade = yes)
        * 'nbpi' in 'fstyp' references the previously detailed equation
Using the above table for reference and using only the values from
'fstyp', we could easily devise a 'newfs' command that would duplicate
the filesystem (of course, without setting 'nsect', 'apc', or 'nrpos',
and assuming 'apc' wasn't modified from its default):
        snorkle [0] echo "y" | /usr/sbin/newfs -Nv -s 1040384 -t 64 -b 4096 -f 512 -c 12 -m 3 -r 546\
                -i 4096 -o space -a 2 -d 0 -C 11 /dev/rdsk/c1t3d0s0
Critically, if you set '-a' (apc) during the initial creation of the FS
via 'newfs', you will not be able to create the FS using only the values
from 'fstyp'.  The above command would produce the following output,
differing from our "specialized" example:
        pfexec mkfs -F ufs -o N /dev/rdsk/c1t3d0s0 1040384 32 64 4096 512 12 3 9 4096 s 0 0 6 11 n
        /dev/rdsk/c1t3d0s0:     1040384 sectors in 508 cylinders of 64 tracks, 32 sectors
                508.0MB in 43 cyl groups (12 c/g, 12.00MB/g, 2816 i/g)
        super-block backups (for fsck -F ufs -o b=#) at:
         32, 24640, 49248, 73856, 98464, 123072, 147680, 172288, 196896, 221504,
         812096, 836704, 861312, 885920, 910528, 935136, 959744, 984352, 1008960,
         1033568
If we didn't initially set 'apc', the resulting FS would be created
the same as initially set up.  I've included 'fstyp' here to show its
possible usefulness, though generally speaking, you would be better off
simply using the 'mkfs' option as it includes all necessary values.

see also:
    Recreate a FreeBSD UFS FS
    Recreate a Linux EXT3 FS