Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/ext2fs add support for GDT_CSUM AKA uninit_bg feature



details:   https://anonhg.NetBSD.org/src/rev/d85fd3fe9b41
branches:  trunk
changeset: 347318:d85fd3fe9b41
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sat Aug 20 19:47:44 2016 +0000

description:
add support for GDT_CSUM AKA uninit_bg feature

diffstat:

 sys/ufs/ext2fs/ext2fs.h        |   52 ++++++--
 sys/ufs/ext2fs/ext2fs_alloc.c  |  222 ++++++++++++++++++++++++++++++++++++----
 sys/ufs/ext2fs/ext2fs_bswap.c  |   19 +---
 sys/ufs/ext2fs/ext2fs_extern.h |    3 +-
 sys/ufs/ext2fs/ext2fs_vfsops.c |   20 +++-
 5 files changed, 257 insertions(+), 59 deletions(-)

diffs (truncated from 574 to 300 lines):

diff -r 792f03850be0 -r d85fd3fe9b41 sys/ufs/ext2fs/ext2fs.h
--- a/sys/ufs/ext2fs/ext2fs.h   Sat Aug 20 19:46:54 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs.h   Sat Aug 20 19:47:44 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs.h,v 1.47 2016/08/15 18:46:11 jdolecek Exp $     */
+/*     $NetBSD: ext2fs.h,v 1.48 2016/08/20 19:47:44 jdolecek Exp $     */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -249,10 +249,10 @@
        int64_t e2fs_qbmask;    /* ~fs_bmask - for use with quad size */
        int32_t e2fs_fsbtodb;   /* fsbtodb and dbtofsb shift constant */
        int32_t e2fs_ncg;       /* number of cylinder groups */
-       int32_t e2fs_ngdb;      /* number of group descriptor block */
+       int32_t e2fs_ngdb;      /* number of group descriptor blocks */
        int32_t e2fs_ipb;       /* number of inodes per block */
-       int32_t e2fs_itpg;      /* number of inode table per group */
-       struct  ext2_gd *e2fs_gd; /* group descripors */
+       int32_t e2fs_itpg;      /* number of inode table blocks per group */
+       struct  ext2_gd *e2fs_gd; /* group descriptors (data not byteswapped) */
 };
 
 
@@ -366,7 +366,8 @@
                                         | EXT2F_ROCOMPAT_LARGEFILE \
                                         | EXT2F_ROCOMPAT_HUGE_FILE \
                                         | EXT2F_ROCOMPAT_EXTRA_ISIZE \
-                                        | EXT2F_ROCOMPAT_DIR_NLINK)
+                                        | EXT2F_ROCOMPAT_DIR_NLINK \
+                                        | EXT2F_ROCOMPAT_GDT_CSUM)
 #define EXT2F_INCOMPAT_SUPP            (EXT2F_INCOMPAT_FTYPE \
                                         | EXT2F_INCOMPAT_EXTENTS \
                                         | EXT2F_INCOMPAT_FLEX_BG)
@@ -415,15 +416,35 @@
 struct ext2_gd {
        uint32_t ext2bgd_b_bitmap;      /* blocks bitmap block */
        uint32_t ext2bgd_i_bitmap;      /* inodes bitmap block */
-       uint32_t ext2bgd_i_tables;      /* inodes table block  */
+       uint32_t ext2bgd_i_tables;      /* first inodes table block */
        uint16_t ext2bgd_nbfree;        /* number of free blocks */
        uint16_t ext2bgd_nifree;        /* number of free inodes */
        uint16_t ext2bgd_ndirs;         /* number of directories */
-       uint16_t reserved;
-       uint32_t reserved2[3];
+
+       /*
+        * Following only valid when either GDT_CSUM (AKA uninit_bg) 
+        * or METADATA_CKSUM feature is on
+        */
+       uint16_t ext2bgd_flags;         /* ext4 bg flags (INODE_UNINIT, ...)*/
+       uint32_t ext2bgd_exclude_bitmap_lo;     /* snapshot exclude bitmap */
+       uint16_t ext2bgd_block_bitmap_csum_lo;  /* Low block bitmap checksum */
+       uint16_t ext2bgd_inode_bitmap_csum_lo;  /* Low inode bitmap checksum */
+       uint16_t ext2bgd_itable_unused_lo;      /* Low unused inode offset */
+       uint16_t ext2bgd_checksum;              /* Group desc checksum */
+
+       /*
+        * XXX disk32 Further fields only exist if 64BIT feature is on
+        * and superblock desc_size > 32, not supported for now.
+        */
 };
 
+#define E2FS_BG_INODE_UNINIT   0x0001  /* Inode bitmap not used/initialized */
+#define E2FS_BG_BLOCK_UNINIT   0x0002  /* Block bitmap not used/initialized */
+#define E2FS_BG_INODE_ZEROED   0x0004  /* On-disk inode table initialized */
 
+#define E2FS_HAS_GD_CSUM(fs) \
+       EXT2F_HAS_ROCOMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM|EXT2F_ROCOMPAT_METADATA_CKSUM) != 0
+       
 /*
  * If the EXT2F_ROCOMPAT_SPARSESUPER flag is set, the cylinder group has a
  * copy of the super and cylinder group descriptors blocks only if it's
@@ -457,13 +478,10 @@
 #      define fs2h16(x) (x)
 #      define fs2h32(x) (x)
 #      define fs2h64(x) (x)
-#      define e2fs_sbload(old, new) memcpy((new), (old), SBSIZE);
-#      define e2fs_cgload(old, new, size) memcpy((new), (old), (size));
-#      define e2fs_sbsave(old, new) memcpy((new), (old), SBSIZE);
-#      define e2fs_cgsave(old, new, size) memcpy((new), (old), (size));
+#      define e2fs_sbload(old, new) memcpy((new), (old), SBSIZE)
+#      define e2fs_sbsave(old, new) memcpy((new), (old), SBSIZE)
 #else
 void e2fs_sb_bswap(struct ext2fs *, struct ext2fs *);
-void e2fs_cg_bswap(struct ext2_gd *, struct ext2_gd *, int);
 #      define h2fs16(x) bswap16(x)
 #      define h2fs32(x) bswap32(x)
 #      define h2fs64(x) bswap64(x)
@@ -471,11 +489,13 @@
 #      define fs2h32(x) bswap32(x)
 #      define fs2h64(x) bswap64(x)
 #      define e2fs_sbload(old, new) e2fs_sb_bswap((old), (new))
-#      define e2fs_cgload(old, new, size) e2fs_cg_bswap((old), (new), (size));
 #      define e2fs_sbsave(old, new) e2fs_sb_bswap((old), (new))
-#      define e2fs_cgsave(old, new, size) e2fs_cg_bswap((old), (new), (size));
 #endif
 
+/* Group descriptors are not byte swapped */
+#define e2fs_cgload(old, new, size) memcpy((new), (old), (size))
+#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size))
+
 /*
  * Turn file system block numbers into disk block addresses.
  * This maps file system blocks to device size blocks.
@@ -491,7 +511,7 @@
  */
 #define        ino_to_cg(fs, x)        (((x) - 1) / (fs)->e2fs.e2fs_ipg)
 #define        ino_to_fsba(fs, x)                                              \
-       ((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables +         \
+       (fs2h32((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables) + \
        (((x) - 1) % (fs)->e2fs.e2fs_ipg) / (fs)->e2fs_ipb)
 #define        ino_to_fsbo(fs, x)      (((x) - 1) % (fs)->e2fs_ipb)
 
diff -r 792f03850be0 -r d85fd3fe9b41 sys/ufs/ext2fs/ext2fs_alloc.c
--- a/sys/ufs/ext2fs/ext2fs_alloc.c     Sat Aug 20 19:46:54 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_alloc.c     Sat Aug 20 19:47:44 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_alloc.c,v 1.48 2016/08/13 07:40:10 christos Exp $       */
+/*     $NetBSD: ext2fs_alloc.c,v 1.49 2016/08/20 19:47:44 jdolecek Exp $       */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.48 2016/08/13 07:40:10 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.49 2016/08/20 19:47:44 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,6 +72,8 @@
 #include <sys/syslog.h>
 #include <sys/kauth.h>
 
+#include <lib/libkern/crc16.h>
+
 #include <ufs/ufs/inode.h>
 #include <ufs/ufs/ufs_extern.h>
 #include <ufs/ufs/ufsmount.h>
@@ -88,6 +90,9 @@
                    daddr_t (*)(struct inode *, int, daddr_t, int));
 static daddr_t ext2fs_nodealloccg(struct inode *, int, daddr_t, int);
 static daddr_t ext2fs_mapsearch(struct m_ext2fs *, char *, daddr_t);
+static __inline void   ext2fs_cg_update(struct m_ext2fs *, int, struct ext2_gd *, int, int, int, daddr_t);
+static uint16_t        ext2fs_cg_get_csum(struct m_ext2fs *, int, struct ext2_gd *);
+static void            ext2fs_init_bb(struct m_ext2fs *, int, struct ext2_gd *, char *);
 
 /*
  * Allocate a block in the file system.
@@ -191,7 +196,11 @@
                return error;
        }
        ip = VTOI(*vpp);
-       if (ip->i_e2fs_mode && ip->i_e2fs_nlink != 0) {
+
+       KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[ino_to_cg(fs, ino)].ext2bgd_flags & h2fs16(E2FS_BG_INODE_ZEROED)) != 0);
+
+       /* check for already used inode; makes sense only for ZEROED itable */
+       if (__predict_false(ip->i_e2fs_mode && ip->i_e2fs_nlink != 0)) {
                printf("mode = 0%o, nlinks %d, inum = %llu, fs = %s\n",
                    ip->i_e2fs_mode, ip->i_e2fs_nlink,
                    (unsigned long long)ip->i_number, fs->e2fs_fsmnt);
@@ -229,10 +238,10 @@
        maxspace = 0;
        mincg = -1;
        for (cg = 0; cg < fs->e2fs_ncg; cg++)
-               if ( fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) {
-                       if (mincg == -1 || fs->e2fs_gd[cg].ext2bgd_nbfree > maxspace) {
+               if (fs2h16(fs->e2fs_gd[cg].ext2bgd_nifree) >= avgifree) {
+                       if (mincg == -1 || fs2h16(fs->e2fs_gd[cg].ext2bgd_nbfree) > maxspace) {
                                mincg = cg;
-                               maxspace = fs->e2fs_gd[cg].ext2bgd_nbfree;
+                               maxspace = fs2h16(fs->e2fs_gd[cg].ext2bgd_nbfree);
                        }
                }
        return mincg;
@@ -356,7 +365,7 @@
        if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
                return 0;
        error = bread(ip->i_devvp, EXT2_FSBTODB(fs,
-               fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+               fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap)),
                (int)fs->e2fs_bsize, B_MODIFY, &bp);
        if (error) {
                return 0;
@@ -365,6 +374,14 @@
 
        if (dtog(fs, bpref) != cg)
                bpref = 0;
+
+       /* initialize block bitmap now if uninit */
+       if (__predict_false(E2FS_HAS_GD_CSUM(fs) &&
+           (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_BLOCK_UNINIT)))) {
+               ext2fs_init_bb(fs, cg, &fs->e2fs_gd[cg], bbp);
+               fs->e2fs_gd[cg].ext2bgd_flags &= h2fs16(~E2FS_BG_BLOCK_UNINIT);
+       }
+
        if (bpref != 0) {
                bpref = dtogd(fs, bpref);
                /*
@@ -412,7 +429,7 @@
 #endif
        setbit(bbp, (daddr_t)bno);
        fs->e2fs.e2fs_fbcount--;
-       fs->e2fs_gd[cg].ext2bgd_nbfree--;
+       ext2fs_cg_update(fs, cg, &fs->e2fs_gd[cg], -1, 0, 0, 0);
        fs->e2fs_fmod = 1;
        bdwrite(bp);
        return cg * fs->e2fs.e2fs_fpg + fs->e2fs.e2fs_first_dblock + bno;
@@ -442,12 +459,23 @@
        if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
                return 0;
        error = bread(ip->i_devvp, EXT2_FSBTODB(fs,
-               fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+               fs2h32(fs->e2fs_gd[cg].ext2bgd_i_bitmap)),
                (int)fs->e2fs_bsize, B_MODIFY, &bp);
        if (error) {
                return 0;
        }
        ibp = (char *)bp->b_data;
+
+       KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_INODE_ZEROED)) != 0);
+
+       /* initialize inode bitmap now if uninit */
+       if (__predict_false(E2FS_HAS_GD_CSUM(fs) &&
+           (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_INODE_UNINIT)))) {
+               KASSERT(fs2h16(fs->e2fs_gd[cg].ext2bgd_nifree) == fs->e2fs.e2fs_ipg);
+               memset(ibp, 0, fs->e2fs_bsize);
+               fs->e2fs_gd[cg].ext2bgd_flags &= h2fs16(~E2FS_BG_INODE_UNINIT);
+       }
+
        if (ipref) {
                ipref %= fs->e2fs.e2fs_ipg;
                if (isclr(ibp, ipref))
@@ -471,17 +499,15 @@
        map = ibp[i] ^ 0xff;
        if (map == 0) {
                printf("fs = %s\n", fs->e2fs_fsmnt);
-               panic("ext2fs_nodealloccg: block not in map");
+               panic("ext2fs_nodealloccg: inode not in map");
        }
        ipref = i * NBBY + ffs(map) - 1;
 gotit:
        setbit(ibp, ipref);
        fs->e2fs.e2fs_ficount--;
-       fs->e2fs_gd[cg].ext2bgd_nifree--;
+       ext2fs_cg_update(fs, cg, &fs->e2fs_gd[cg],
+               0, -1, ((mode & IFMT) == IFDIR) ? 1 : 0, ipref);
        fs->e2fs_fmod = 1;
-       if ((mode & IFMT) == IFDIR) {
-               fs->e2fs_gd[cg].ext2bgd_ndirs++;
-       }
        bdwrite(bp);
        return cg * fs->e2fs.e2fs_ipg + ipref + 1;
 }
@@ -502,6 +528,9 @@
 
        fs = ip->i_e2fs;
        cg = dtog(fs, bno);
+
+       KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_BLOCK_UNINIT)) == 0);
+
        if ((u_int)bno >= fs->e2fs.e2fs_bcount) {
                printf("bad block %lld, ino %llu\n", (long long)bno,
                    (unsigned long long)ip->i_number);
@@ -509,7 +538,7 @@
                return;
        }
        error = bread(ip->i_devvp,
-               EXT2_FSBTODB(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+               EXT2_FSBTODB(fs, fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap)),
                (int)fs->e2fs_bsize, B_MODIFY, &bp);
        if (error) {
                return;
@@ -524,8 +553,7 @@
        }
        clrbit(bbp, bno);
        fs->e2fs.e2fs_fbcount++;
-       fs->e2fs_gd[cg].ext2bgd_nbfree++;
-
+       ext2fs_cg_update(fs, cg, &fs->e2fs_gd[cg], 1, 0, 0, 0);
        fs->e2fs_fmod = 1;
        bdwrite(bp);
 }
@@ -546,13 +574,18 @@
 
        pip = VTOI(pvp);
        fs = pip->i_e2fs;
+
        if ((u_int)ino > fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO)
                panic("ifree: range: dev = 0x%llx, ino = %llu, fs = %s",
                    (unsigned long long)pip->i_dev, (unsigned long long)ino,
                    fs->e2fs_fsmnt);
+
        cg = ino_to_cg(fs, ino);
+
+       KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_INODE_UNINIT)) == 0);
+
        error = bread(pip->i_devvp,



Home | Main Index | Thread Index | Old Index