tAdd UFS2 support. - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e060bc52275a6d7eff5238fba5ba592004da3eb3
 (DIR) parent 8ecefa411d235498ed036c6e173f62547a2e5dd4
 (HTM) Author: rsc <devnull@localhost>
       Date:   Thu, 11 Aug 2005 16:45:39 +0000
       
       Add UFS2 support.
       
       Diffstat:
         M src/libdiskfs/ffs.c                 |     155 ++++++++++++++++++++-----------
         M src/libdiskfs/ffs.h                 |     165 +++++++++++++++++++++----------
         M src/libdiskfs/mkfile                |       2 ++
       
       3 files changed, 219 insertions(+), 103 deletions(-)
       ---
 (DIR) diff --git a/src/libdiskfs/ffs.c b/src/libdiskfs/ffs.c
       t@@ -6,6 +6,8 @@
        #include <diskfs.h>
        #include "ffs.h"
        
       +#define BADBNO        ((u64int)~0ULL)
       +
        #define checkcg 0
        #define debug 0
        
       t@@ -57,7 +59,7 @@ error:
        }
        
        static Cgblk*
       -ffscylgrp(Ffs *fs, int i, Block **pb)
       +ffscylgrp(Ffs *fs, u32int i, Block **pb)
        {
                Block *b;
                Cgblk *cg;
       t@@ -82,6 +84,7 @@ static int
        ffssync(Fsys *fsys)
        {
                int i;
       +        int off[] = { SBOFF, SBOFF2, SBOFFPIGGY };
                Block *b, *cgb;
                Cgblk *cgblk;
                Cylgrp *cg;
       t@@ -95,12 +98,18 @@ ffssync(Fsys *fsys)
                /*
                 * Read super block.
                 */
       -        if((b = diskread(disk, SBSIZE, SBOFF)) == nil)
       -                goto error;
       -        fsblk = (Fsblk*)b->data;
       -        if(checkfsblk(fsblk) < 0)
       -                goto error;
       +        for(i=0; i<nelem(off); i++){
       +                if((b = diskread(disk, SBSIZE, off[i])) == nil)
       +                        goto error;
       +                fsblk = (Fsblk*)b->data;
       +                fprint(2, "offset of magic: %d\n", offsetof(Fsblk, magic));
       +                if((fs->ufs = checkfsblk(fsblk)) > 0)
       +                        goto okay;
       +                blockput(b);
       +        }
       +        goto error;
        
       +okay:
                fs->blocksize = fsblk->blocksize;
                fs->nblock = (fsblk->nfrag+fsblk->fragsperblock-1) / fsblk->fragsperblock;
                fs->fragsize = fsblk->fragsize;
       t@@ -111,21 +120,31 @@ ffssync(Fsys *fsys)
        
                fs->nfrag = fsblk->nfrag;
                fs->ndfrag = fsblk->ndfrag;
       -        fs->blockspergroup = (u64int)fsblk->cylspergroup * 
       -                fsblk->secspercyl * BYTESPERSEC / fsblk->blocksize;
       +        /*
       +         * used to use 
       +         *        fs->blockspergroup = (u64int)fsblk->_cylspergroup * 
       +         *                fsblk->secspercyl * BYTESPERSEC / fsblk->blocksize;
       +         * for UFS1, but this should work for both UFS1 and UFS2
       +         */
       +        fs->blockspergroup = (u64int)fsblk->fragspergroup / fsblk->fragsperblock;
                fs->ncg = fsblk->ncg;
        
                fsys->blocksize = fs->blocksize;
                fsys->nblock = fs->nblock;
        
       -        if(0) fprint(2, "ffs %d %d-byte blocks, %d cylinder groups\n",
       +        if(debug) fprint(2, "ffs %lld %d-byte blocks, %d cylinder groups\n",
                        fs->nblock, fs->blocksize, fs->ncg);
       +        if(debug) fprint(2, "\tinospergroup %d perblock %d blockspergroup %lld\n",
       +                fs->inospergroup, fs->inosperblock, fs->blockspergroup);
        
                if(fs->cg == nil)
                        fs->cg = emalloc(fs->ncg*sizeof(Cylgrp));
                for(i=0; i<fs->ncg; i++){
                        cg = &fs->cg[i];
       -                cg->bno = fs->blockspergroup*i + fsblk->cgoffset * (i & ~fsblk->cgmask);
       +                if(fs->ufs == 2)
       +                        cg->bno = (u64int)fs->blockspergroup*i;
       +                else
       +                        cg->bno = fs->blockspergroup*i + fsblk->_cgoffset * (i & ~fsblk->_cgmask);
                        cg->cgblkno = cg->bno + fsblk->cfragno/fs->fragsperblock;
                        cg->ibno = cg->bno + fsblk->ifragno/fs->fragsperblock;
                        cg->dbno = cg->bno + fsblk->dfragno/fs->fragsperblock;
       t@@ -172,12 +191,20 @@ ffsclose(Fsys *fsys)
        static int
        checkfsblk(Fsblk *super)
        {
       -        if(super->magic != FSMAGIC){
       -                werrstr("bad super block");
       -                return -1;
       +fprint(2, "ffs magic 0x%ux\n", super->magic);
       +        if(super->magic == FSMAGIC){
       +                super->time = super->_time;
       +                super->nfrag = super->_nfrag;
       +                super->ndfrag = super->_ndfrag;
       +                super->flags = super->_flags;
       +                return 1;
       +        }
       +        if(super->magic == FSMAGIC2){
       +                return 2;
                }
        
       -        return 0;
       +        werrstr("bad super block");
       +        return -1;
        }
        
        static int
       t@@ -198,11 +225,10 @@ int nskipx;
        static Block*
        ffsblockread(Fsys *fsys, u64int bno)
        {
       -        u32int i, o;
       +        int i, o;
                u8int *fmap;
                int frag, fsize, avail;
                Block *b;
       -//        Cylgrp *cg;
                Cgblk *cgblk;
                Ffs *fs;
        
       t@@ -211,10 +237,6 @@ ffsblockread(Fsys *fsys, u64int bno)
                o = bno % fs->blockspergroup;
                if(i >= fs->ncg)
                        return nil;
       -//        cg = &fs->cg[i];
       -
       -//        if(o >= cg->nblock)
       -//                return nil;
        
                if((cgblk = ffscylgrp(fs, i, &b)) == nil)
                        return nil;
       t@@ -257,7 +279,7 @@ nskipx++;
        }
        
        static Block*
       -ffsdatablock(Ffs *fs, u32int bno, int size)
       +ffsdatablock(Ffs *fs, u64int bno, int size)
        {
                int fsize;
                u64int diskaddr;
       t@@ -290,25 +312,26 @@ ffsdatablock(Ffs *fs, u32int bno, int size)
                return b;
        }
        
       -static u32int
       -ifetch(Ffs *fs, u32int bno, u32int off)
       +static u64int
       +ifetch(Ffs *fs, u64int bno, u32int off)
        {
       -        u32int *a;
                Block *b;
                
       -        if(bno == ~0)
       -                return ~0;
       +        if(bno == BADBNO)
       +                return BADBNO;
                b = ffsdatablock(fs, bno, fs->blocksize);
                if(b == nil)
       -                return ~0;
       -        a = (u32int*)b->data;
       -        bno = a[off];
       +                return BADBNO;
       +        if(fs->ufs == 2)
       +                bno = ((u64int*)b->data)[off];
       +        else
       +                bno = ((u32int*)b->data)[off];
                blockput(b);
                return bno;
        }
        
       -static u32int
       -ffsfileblockno(Ffs *fs, Inode *ino, u32int bno)
       +static u64int
       +ffsfileblockno(Ffs *fs, Inode *ino, u64int bno)
        {
                int ppb;
        
       t@@ -329,16 +352,15 @@ ffsfileblockno(Ffs *fs, Inode *ino, u32int bno)
                
                if(bno/ppb/ppb/ppb == 0)        /* bno < ppb*ppb*ppb w/o overflow */
                        return ifetch(fs, ifetch(fs, ifetch(fs, ino->ib[2], bno/ppb/ppb), (bno/ppb)%ppb), bno%ppb);
       -        bno -= ppb*ppb*ppb;
                
       -        fprint(2, "ffsfileblock %lud: way too big\n", (ulong)bno+NDADDR);
       -        return ~0;
       +        fprint(2, "ffsfileblock %llud: way too big\n", bno+NDADDR+ppb+ppb*ppb);
       +        return BADBNO;
        }
        
        static Block*
       -ffsfileblock(Ffs *fs, Inode *ino, u32int bno, int size)
       +ffsfileblock(Ffs *fs, Inode *ino, u64int bno, int size)
        {
       -        u32int b;
       +        u64int b;
                
                b = ffsfileblockno(fs, ino, bno);
                if(b == ~0)
       t@@ -365,7 +387,33 @@ byte2u32(uchar *p)
                return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
        }
        
       -static u64int iaddr;
       +static u64int lastiaddr;        /* debugging */
       +
       +static void
       +inode1to2(Inode1 *i1, Inode *i2)
       +{
       +        int i;
       +        
       +        memset(i2, 0, sizeof *i2);
       +        i2->mode = i1->mode;
       +        i2->nlink = i1->nlink;
       +        i2->size = i1->size;
       +        i2->atime = i1->atime;
       +        i2->atimensec = i1->atimensec;
       +        i2->mtime = i1->mtime;
       +        i2->mtimensec = i1->mtimensec;
       +        i2->ctime = i1->ctime;
       +        i2->ctimensec = i1->ctimensec;
       +        for(i=0; i<NDADDR; i++)
       +                i2->db[i] = i1->db[i];
       +        for(i=0; i<NIADDR; i++)
       +                i2->ib[i] = i1->ib[i];
       +        i2->flags = i1->flags;
       +        i2->nblock = i1->nblock;
       +        i2->gen = i1->gen;
       +        i2->uid = i1->uid;
       +        i2->gid = i1->gid;
       +}
        
        static Nfs3Status
        handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
       t@@ -373,8 +421,10 @@ handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
                int i;
                u32int ioff;
                u32int inum;
       +        u64int iaddr;
                Block *b;
                Cylgrp *cg;
       +        Inode1 ino1;
        
                if(h->len != 4)
                        return Nfs3ErrBadHandle;
       t@@ -390,20 +440,21 @@ handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
                if(i >= fs->ncg)
                        return Nfs3ErrBadHandle;
                cg = &fs->cg[i];
       -/*
       -        if(ioff >= cg->nino)
       -                return Nfs3ErrBadHandle;
       -*/
        
       -        if(debug) print("cg->ibno %d...", cg->ibno);
       -        if((b = diskread(fs->disk, fs->blocksize,
       -                (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize)) == nil)
       +        if(debug) print("cg->ibno %lld ufs %d...", cg->ibno, fs->ufs);
       +        iaddr = (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize;
       +        ioff = ioff%fs->inosperblock;
       +        if((b = diskread(fs->disk, fs->blocksize, iaddr)) == nil)
                        return Nfs3ErrIo;
       -        iaddr = (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize
       -                + (ioff%fs->inosperblock)*sizeof(Inode);
       -        *ino = ((Inode*)b->data)[ioff%fs->inosperblock];
       +        if(fs->ufs == 2){
       +                *ino = ((Inode*)b->data)[ioff];
       +                lastiaddr = iaddr+ioff*sizeof(Inode);
       +        }else{
       +                ino1 = ((Inode1*)b->data)[ioff];
       +                inode1to2(&ino1, ino);
       +                lastiaddr = iaddr+ioff*sizeof(Inode1);
       +        }
                blockput(b);
       -
                return Nfs3Ok;
        }
        
       t@@ -717,7 +768,7 @@ ffsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u64int cook
        static u64int
        ffsxfileblock(Fsys *fsys, Nfs3Handle *h, u64int offset)
        {
       -        u32int bno;
       +        u64int bno;
                Inode ino;
                Nfs3Status ok;
                Ffs *fs;
       t@@ -727,8 +778,8 @@ ffsxfileblock(Fsys *fsys, Nfs3Handle *h, u64int offset)
                        nfs3errstr(ok);
                        return 0;
                }
       -        if(offset == 1)
       -                return iaddr;
       +        if(offset == 1)        /* clumsy hack for debugging */
       +                return lastiaddr;
                if(offset >= ino.size){
                        werrstr("beyond end of file");
                        return 0;
       t@@ -820,7 +871,7 @@ ffsreadlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link)
                len = ino.size;
        
                if(ino.nblock != 0){
       -                /* BUG: assumes symlink fits in one block */
       +                /* assumes symlink fits in one block */
                        b = ffsfileblock(fs, &ino, 0, len);
                        if(b == nil)
                                return Nfs3ErrIo;
 (DIR) diff --git a/src/libdiskfs/ffs.h b/src/libdiskfs/ffs.h
       t@@ -19,8 +19,10 @@
        typedef struct Cgblk Cgblk;
        typedef struct Cylgrp Cylgrp;
        typedef struct Cylsum Cylsum;
       +typedef struct Cylsumtotal Cylsumtotal;
        typedef struct Ffs Ffs;
        typedef struct Fsblk Fsblk;
       +typedef struct Inode1 Inode1;
        typedef struct Inode Inode;
        typedef struct Dirent Dirent;
        
       t@@ -30,9 +32,13 @@ enum
        
                /* constants for Fsblk */
                FSMAXMNTLEN = 512,
       -        FSNOCSPTRS = 128 / sizeof(void*) - 3,
       +        FSMAXMNTLEN2 = 468,
       +        FSMAXVOLLEN = 32,                                /* UFS2 */
       +        FSNOCSPTRSLEN = 128-12,
       +        FSNOCSPTRSLEN2 = 128-16,        /* UFS2 */
                FSMAXSNAP = 20,
                FSMAGIC = 0x011954,
       +        FSMAGIC2 = 0x19540119,
                FSCHECKSUM = 0x7c269d38,
                
                /* Fsblk.inodefmt */
       t@@ -45,6 +51,8 @@ enum
        
                /* offset and size of first super block */
                SBOFF = BBOFF+BBSIZE,
       +        SBOFF2 = BBOFF+65536,                        /* UFS2 */
       +        SBOFFPIGGY = BBOFF+262144,                /* UFS2 */
                SBSIZE = 8192,
        
                /* minimum block size */
       t@@ -60,6 +68,7 @@ enum
                ROOTINODE = 2,
                WHITEOUT = 1,
        
       +        NXADDR = 2,        /* UFS2 */
                NDADDR = 12,
                NIADDR = 3,
        
       t@@ -102,6 +111,17 @@ struct Cylsum
                u32int        nffree;
        };
        
       +struct Cylsumtotal
       +{
       +        u64int        ndir;
       +        u64int        nbfree;
       +        u64int        nifree;
       +        u64int        nffree;
       +        u64int        numclusters;
       +        u64int        unused[3];
       +};
       +
       +/* Fields beginning with underscore are deprecated in UFS2 */
        struct Fsblk
        {
                u32int        unused0;
       t@@ -110,11 +130,11 @@ struct Fsblk
                daddr_t        cfragno;                /* fragment address if cylinder block in file system */
                daddr_t        ifragno;                /* fragment offset of inode blocks in file system */
                daddr_t        dfragno;                /* fragment offset of data blocks in cg */
       -        u32int        cgoffset;                /* block (maybe fragment?) offset of Cgblk in cylinder */
       -        u32int        cgmask;
       -        time_t        time;
       -        u32int        nfrag;                /* number of blocks in fs * fragsperblock */
       -        u32int        ndfrag;
       +        u32int        _cgoffset;                /* block (maybe fragment?) offset of Cgblk in cylinder */
       +        u32int        _cgmask;
       +        time_t        _time;
       +        u32int        _nfrag;                        /* number of blocks in fs * fragsperblock */
       +        u32int        _ndfrag;
                u32int        ncg;                        /* number of cylinder groups in fs */
                u32int        blocksize;                /* block size in fs */
                u32int        fragsize;                /* frag size in fs */
       t@@ -130,58 +150,73 @@ struct Fsblk
                u32int        maxbpg;
                u32int        fragshift;
                u32int        fsbtodbshift;
       -        u32int        sbsize;                /* size of super block */
       +        u32int        sbsize;                        /* size of super block */
                u32int        unused2;                /* more stuff we don't use ... */
                u32int        unused3;
                u32int        nindir;
                u32int        inosperblock;        /* inodes per block */
       -        u32int        nspf;
       +        u32int        _nspf;
                u32int        optim;
       -        u32int        npsect;
       -        u32int        interleave;
       -        u32int        trackskew;
       +        u32int        _npsect;
       +        u32int        _interleave;
       +        u32int        _trackskew;
                u32int        id[2];
       -        daddr_t        csaddr;                /* blk addr of cyl grp summary area */
       -        u32int        cssize;                /* size of cyl grp summary area */
       -        u32int        cgsize;                /* cylinder group size */
       -        u32int        trackspercyl;        /* tracks per cylinder */
       -        u32int        secspertrack;        /* sectors per track */
       -        u32int        secspercyl;        /* sectors per cylinder */
       -        u32int        ncyl;                        /* cylinders in fs */
       -        u32int        cylspergroup;        /* cylinders per group */
       +        daddr_t        _csaddr;                /* blk addr of cyl grp summary area */
       +        u32int        cssize;                        /* size of cyl grp summary area */
       +        u32int        cgsize;                        /* cylinder group size */
       +        u32int        _trackspercyl;        /* tracks per cylinder */
       +        u32int        _secspertrack;        /* sectors per track */
       +        u32int        _secspercyl;        /* sectors per cylinder */
       +        u32int        _ncyl;                        /* cylinders in fs */
       +        u32int        _cylspergroup;        /* cylinders per group */
                u32int        inospergroup;        /* inodes per group */
                u32int        fragspergroup;        /* data blocks per group * fragperblock */
       -        Cylsum        cstotal;                /* more unused... */
       +        Cylsum        _cstotal;                /* more unused... */
                u8int        fmod;
                u8int        clean;
                u8int        ronly;
       -        u8int        flags;
       -        char                fsmnt[FSMAXMNTLEN];
       +        u8int        _flags;
       +        /* char fsmnt[512]; in UFS1 */
       +                char        fsmnt[FSMAXMNTLEN2];
       +                char        volname[FSMAXVOLLEN];
       +                u64int        swuid;
       +                u32int        pad;
                u32int        cgrotor;
       -        void*        ocsp[FSNOCSPTRS];
       -        u8int*        contigdirs;
       -        Cylsum*        csp;
       -        u32int*        maxcluster;
       -        u32int        cpc;
       -        u16int        opostbl[16][8];
       +        uchar        ocsp[FSNOCSPTRSLEN]; /* last 4 bytes is contigdirs in UFS2 */
       +        u32int        contigdirs;                /* csp in UFS2 */
       +        u32int        csp;                        /* maxcluster in UFS2 */
       +        u32int        maxcluster;                /* active in UFS2 */
       +        u32int        _cpc;
       +        /* u16int        opostbl[16][8]; in UFS1 */
       +                u32int        maxbsize;
       +                u64int        spare64[17];
       +                u64int        sblockloc;
       +                Cylsumtotal        cstotal;
       +                u64int        time;
       +                u64int        nfrag;
       +                u64int        ndfrag;
       +                u64int        csaddr;
       +                u64int        pendingblocks;
       +                u32int        pendinginodes;
                u32int        snapinum[FSMAXSNAP];
                u32int        avgfilesize;
                u32int        avgfpdir;
       -        u32int        sparecon[26];
       -        u32int        pendingblocks;
       -        u32int        pendinginodes;
       +        /* u32int sparecon[26], pendingblocks, pendinginodes; in UFS1 */
       +                u32int        savecgsize;
       +                u32int        sparecon[26];
       +                u32int        flags;
                u32int        contigsumsize;
                u32int        maxsymlinklen;
       -        u32int        inodefmt;                /* format of on-disk inodes */
       +        u32int        _inodefmt;                /* format of on-disk inodes */
                u64int        maxfilesize;        /* maximum representable file size */
                u64int        qbmask;
                u64int        qfmask;
                u32int        state;
       -        u32int        postblformat;
       -        u32int        nrpos;
       -        u32int        postbloff;
       -        u32int        rotbloff;
       -        u32int        magic;                /* FS_MAGIC */
       +        u32int        _postblformat;
       +        u32int        _nrpos;
       +        u32int        _postbloff;
       +        u32int        _rotbloff;
       +        u32int        magic;                        /* FSMAGIC or FSMAGIC2 */
        };
        
        /*
       t@@ -190,12 +225,12 @@ struct Fsblk
        struct Cgblk
        {
                u32int        unused0;
       -        u32int        magic;                /* CGMAGIC */
       +        u32int        magic;                        /* CGMAGIC */
                u32int        time;                        /* time last written */
       -        u32int        num;                /* we are cg #cgnum */
       +        u32int        num;                        /* we are cg #cgnum */
                u16int        ncyl;                        /* number of cylinders in gp */
       -        u16int        nino;                /* number of inodes */
       -        u32int        nfrag;                /* number of fragments  */
       +        u16int        nino;                        /* number of inodes */
       +        u32int        nfrag;                        /* number of fragments  */
                Cylsum        csum;
                u32int        rotor;
                u32int        frotor;
       t@@ -215,16 +250,16 @@ struct Cgblk
        struct Cylgrp
        {
                /* these are block numbers not fragment numbers */
       -        u32int        bno;                        /* disk block address of start of cg */
       -        u32int        ibno;                        /* disk block address of first inode */
       -        u32int        dbno;                /* disk block address of first data */
       -        u32int        cgblkno;
       +        u64int        bno;                        /* disk block address of start of cg */
       +        u64int        ibno;                        /* disk block address of first inode */
       +        u64int        dbno;                        /* disk block address of first data */
       +        u64int        cgblkno;
        };
        
        /*
         * this is the on-disk structure
         */
       -struct Inode
       +struct Inode1
        {
                u16int        mode;
                u16int        nlink;
       t@@ -247,6 +282,33 @@ struct Inode
                u32int        spare[2];
        };
        
       +struct Inode
       +{
       +        u16int        mode;
       +        u16int        nlink;
       +        u32int        uid;
       +        u32int        gid;
       +        u32int        blksize;
       +        u64int        size;
       +        u64int        nblock;
       +        u64int        atime;
       +        u64int        mtime;
       +        u64int        ctime;
       +        u64int        btime;
       +        u32int        atimensec;
       +        u32int        mtimensec;
       +        u32int        ctimensec;
       +        u32int        btimensec;
       +        u32int        gen;
       +        u32int        kernflags;
       +        u32int        flags;
       +        u32int        extsize;
       +        u64int        ext[NXADDR];
       +        u64int        db[NDADDR];
       +        u64int        ib[NIADDR];
       +        u64int        spare[3];
       +};
       +
        struct Dirent
        {
                u32int        ino;
       t@@ -261,17 +323,18 @@ struct Dirent
         */
        struct Ffs
        {
       +        int                ufs;
                int                blocksize;
       -        int                nblock;
       +        u64int        nblock;
                int                fragsize;
                int                fragsperblock;
                int                inosperblock;
       -        int                blockspergroup;
       -        int                fragspergroup;
       +        u64int        blockspergroup;
       +        u64int        fragspergroup;
                int                inospergroup;
        
       -        u32int        nfrag;
       -        u32int        ndfrag;
       +        u64int        nfrag;
       +        u64int        ndfrag;
        
                int                ncg;
                Cylgrp        *cg;
 (DIR) diff --git a/src/libdiskfs/mkfile b/src/libdiskfs/mkfile
       t@@ -29,3 +29,5 @@ CFLAGS=$CFLAGS
        
        %.acid: %.$O %.c
                $CC $CFLAGS -a $stem.c >$stem.acid
       +
       +ffs.$O: ffs.h