Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/ext2fs support arbitrary ext3/ext4 inode size, add a...



details:   https://anonhg.NetBSD.org/src/rev/b35c3d403b13
branches:  trunk
changeset: 816941:b35c3d403b13
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Wed Aug 03 21:53:02 2016 +0000

description:
support arbitrary ext3/ext4 inode size, add all the new ext4 fields ext2fs_dinode, and add support for loading the extra inode data

diffstat:

 sys/ufs/ext2fs/ext2fs.h        |    5 +-
 sys/ufs/ext2fs/ext2fs_alloc.c  |    6 +-
 sys/ufs/ext2fs/ext2fs_bswap.c  |   42 ++++++++++++--
 sys/ufs/ext2fs/ext2fs_dinode.h |   36 ++++++++----
 sys/ufs/ext2fs/ext2fs_inode.c  |    6 +-
 sys/ufs/ext2fs/ext2fs_vfsops.c |  120 +++++++++++++++++++++++++---------------
 sys/ufs/ext2fs/ext2fs_vnops.c  |    6 +-
 7 files changed, 148 insertions(+), 73 deletions(-)

diffs (truncated from 453 to 300 lines):

diff -r 7d7d26eb604b -r b35c3d403b13 sys/ufs/ext2fs/ext2fs.h
--- a/sys/ufs/ext2fs/ext2fs.h   Wed Aug 03 19:59:57 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs.h   Wed Aug 03 21:53:02 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs.h,v 1.38 2016/06/24 17:21:30 christos Exp $     */
+/*     $NetBSD: ext2fs.h,v 1.39 2016/08/03 21:53:02 jdolecek Exp $     */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -327,7 +327,8 @@
 #define EXT2F_COMPAT_SUPP              0x0000
 #define EXT2F_ROCOMPAT_SUPP            (EXT2F_ROCOMPAT_SPARSESUPER \
                                         | EXT2F_ROCOMPAT_LARGEFILE \
-                                        | EXT2F_ROCOMPAT_HUGE_FILE)
+                                        | EXT2F_ROCOMPAT_HUGE_FILE \
+                                        | EXT2F_ROCOMPAT_EXTRA_ISIZE)
 #define EXT2F_INCOMPAT_SUPP            (EXT2F_INCOMPAT_FTYPE \
                                         | EXT2F_INCOMPAT_EXTENTS)
 
diff -r 7d7d26eb604b -r b35c3d403b13 sys/ufs/ext2fs/ext2fs_alloc.c
--- a/sys/ufs/ext2fs/ext2fs_alloc.c     Wed Aug 03 19:59:57 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_alloc.c     Wed Aug 03 21:53:02 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_alloc.c,v 1.46 2015/03/28 19:24:04 maxv Exp $   */
+/*     $NetBSD: ext2fs_alloc.c,v 1.47 2016/08/03 21:53:02 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.46 2015/03/28 19:24:04 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.47 2016/08/03 21:53:02 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -198,7 +198,7 @@
                panic("ext2fs_valloc: dup alloc");
        }
 
-       memset(ip->i_din.e2fs_din, 0, sizeof(struct ext2fs_dinode));
+       memset(ip->i_din.e2fs_din, 0, EXT2_DINODE_SIZE(fs));
 
        /*
         * Set up a new generation number for this inode.
diff -r 7d7d26eb604b -r b35c3d403b13 sys/ufs/ext2fs/ext2fs_bswap.c
--- a/sys/ufs/ext2fs/ext2fs_bswap.c     Wed Aug 03 19:59:57 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_bswap.c     Wed Aug 03 21:53:02 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_bswap.c,v 1.20 2016/08/02 17:24:24 jdolecek Exp $       */
+/*     $NetBSD: ext2fs_bswap.c,v 1.21 2016/08/03 21:53:02 jdolecek Exp $       */
 
 /*
  * Copyright (c) 1997 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_bswap.c,v 1.20 2016/08/02 17:24:24 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_bswap.c,v 1.21 2016/08/03 21:53:02 jdolecek Exp $");
 
 #include <sys/types.h>
 #include <ufs/ext2fs/ext2fs.h>
@@ -81,7 +81,8 @@
        new->e2fs_reserved_ngdb =       bswap16(old->e2fs_reserved_ngdb);
 }
 
-void e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size)
+void
+e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size)
 {
        int i;
 
@@ -95,9 +96,13 @@
        }
 }
 
-void e2fs_i_bswap(struct ext2fs_dinode *old, struct ext2fs_dinode *new)
+void
+e2fs_i_bswap(struct ext2fs_dinode *old, struct ext2fs_dinode *new, size_t isize)
 {
+       /* preserve non-swapped and unused fields */ 
+       memcpy(new, old, isize);
 
+       /* swap what needs to be swapped */
        new->e2di_mode          =       bswap16(old->e2di_mode);
        new->e2di_uid           =       bswap16(old->e2di_uid);
        new->e2di_gid           =       bswap16(old->e2di_gid);
@@ -117,7 +122,32 @@
        new->e2di_facl_high     =       bswap16(old->e2di_facl_high);
        new->e2di_uid_high      =       bswap16(old->e2di_uid_high);
        new->e2di_gid_high      =       bswap16(old->e2di_gid_high);
-       memcpy(&new->e2di_blocks[0], &old->e2di_blocks[0],
-           (EXT2FS_NDADDR + EXT2FS_NIADDR) * sizeof(uint32_t));
+       new->e2di_checksum_low  =       bswap16(old->e2di_checksum_low);
+
+       /*
+        * Following fields are only supported for inode sizes bigger
+        * than the old ext2 one
+        */
+       if (isize == EXT2_REV0_DINODE_SIZE)
+               return;
+
+       new->e2di_extra_isize   = bswap16(old->e2di_extra_isize);
+       new->e2di_checksum_high = bswap16(old->e2di_checksum_high);
+
+       /* Following fields are ext4, might not be actually present */
+       if (EXT2_DINODE_FITS(new, e2di_ctime_extra, isize))
+               new->e2di_ctime_extra   = bswap32(old->e2di_ctime_extra);
+       if (EXT2_DINODE_FITS(new, e2di_mtime_extra, isize))
+               new->e2di_mtime_extra   = bswap32(old->e2di_mtime_extra);
+       if (EXT2_DINODE_FITS(new, e2di_atime_extra, isize))
+               new->e2di_atime_extra   = bswap32(old->e2di_atime_extra);
+       if (EXT2_DINODE_FITS(new, e2di_crtime, isize))
+               new->e2di_crtime        = bswap32(old->e2di_crtime);
+       if (EXT2_DINODE_FITS(new, e2di_crtime_extra, isize))
+               new->e2di_crtime_extra  = bswap32(old->e2di_crtime_extra);
+       if (EXT2_DINODE_FITS(new, e2di_version_high, isize))
+               new->e2di_version_high  = bswap32(old->e2di_version_high);
+       if (EXT2_DINODE_FITS(new, e2di_projid, isize))
+               new->e2di_projid        = bswap32(old->e2di_projid);
 }
 #endif
diff -r 7d7d26eb604b -r b35c3d403b13 sys/ufs/ext2fs/ext2fs_dinode.h
--- a/sys/ufs/ext2fs/ext2fs_dinode.h    Wed Aug 03 19:59:57 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_dinode.h    Wed Aug 03 21:53:02 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_dinode.h,v 1.27 2016/08/02 17:36:02 jdolecek Exp $      */
+/*     $NetBSD: ext2fs_dinode.h,v 1.28 2016/08/03 21:53:02 jdolecek Exp $      */
 
 /*
  * Copyright (c) 1982, 1989, 1993
@@ -125,11 +125,19 @@
        uint16_t        e2di_facl_high; /* 118: file ACL bits 47:32 (ext4) */
        uint16_t        e2di_uid_high;  /* 120: Owner UID top 16 bits (ext4) */
        uint16_t        e2di_gid_high;  /* 122: Owner GID top 16 bits (ext4) */
-       uint16_t        e2di_extra_isize; /* 124: inode extra size (over 128) actually used (ext4) */
-       uint16_t        e2di_checksum_high; /* 126: crc (not implemented) (ext4) */
+       uint16_t        e2di_checksum_low;  /* 124: crc LE (not implemented) (ext4) */
+       uint16_t        e2di_reserved;      /* 126: reserved */
+       uint16_t        e2di_extra_isize;   /* 128: inode extra size (over 128) actually used (ext4) */
+       uint16_t        e2di_checksum_high; /* 130: crc BE (not implemented) (ext4) */
+       uint32_t        e2di_ctime_extra;   /* 132: ctime (nsec << 2 | high epoch) (ext4) */
+       uint32_t        e2di_mtime_extra;   /* 136: mtime (nsec << 2 | high epoch) (ext4) */
+       uint32_t        e2di_atime_extra;   /* 140: atime (nsec << 2 | high epoch) (ext4) */
+       uint32_t        e2di_crtime;        /* 144: creation time (epoch) (ext4) */
+       uint32_t        e2di_crtime_extra;  /* 148: creation time (nsec << 2 | high epoch) (ext4) */
+       uint32_t        e2di_version_high;  /* 152: version high (ext4) */
+       uint32_t        e2di_projid;        /* 156: project id (not implemented) (ext4) */
 };
 
-
 /* XXX how does this differ from EXT2_MAXSYMLINKLEN above? */
 #define        E2MAXSYMLINKLEN ((EXT2FS_NDADDR + EXT2FS_NIADDR) * sizeof(uint32_t))
 
@@ -171,10 +179,14 @@
 #define EXT2_EOFBLOCKS         0x00400000 /* Blocks allocated beyond EOF */
 
 /* Size of on-disk inode. */
-#define EXT2_REV0_DINODE_SIZE  sizeof(struct ext2fs_dinode)
+#define EXT2_REV0_DINODE_SIZE  128
 #define EXT2_DINODE_SIZE(fs)   ((fs)->e2fs.e2fs_rev > E2FS_REV0 ?      \
                                    (fs)->e2fs.e2fs_inode_size :        \
                                    EXT2_REV0_DINODE_SIZE)
+#define EXT2_DINODE_FITS(dinode, field, isize) (\
+       (isize > EXT2_REV0_DINODE_SIZE) \
+       && ((EXT2_REV0_DINODE_SIZE + (dinode)->e2di_extra_isize)  >= offsetof(struct ext2fs_dinode, field) + sizeof((dinode)->field)) \
+       )
 
 /*
  * The e2di_blocks fields may be overlaid with other information for
@@ -189,14 +201,14 @@
 
 /* e2fs needs byte swapping on big-endian systems */
 #if BYTE_ORDER == LITTLE_ENDIAN
-#      define e2fs_iload(old, new)     \
-               memcpy((new),(old),sizeof(struct ext2fs_dinode))
-#      define e2fs_isave(old, new)     \
-               memcpy((new),(old),sizeof(struct ext2fs_dinode))
+#      define e2fs_iload(old, new, isize)      \
+               memcpy((new),(old),(isize))
+#      define e2fs_isave(old, new, isize)      \
+               memcpy((new),(old),(isize))
 #else
-void e2fs_i_bswap(struct ext2fs_dinode *, struct ext2fs_dinode *);
-#      define e2fs_iload(old, new) e2fs_i_bswap((old), (new))
-#      define e2fs_isave(old, new) e2fs_i_bswap((old), (new))
+void e2fs_i_bswap(struct ext2fs_dinode *, struct ext2fs_dinode *, size_t);
+#      define e2fs_iload(old, new, isize) e2fs_i_bswap((old), (new))
+#      define e2fs_isave(old, new, isize) e2fs_i_bswap((old), (new))
 #endif
 
 #endif /* !_UFS_EXT2FS_EXT2FS_DINODE_H_ */
diff -r 7d7d26eb604b -r b35c3d403b13 sys/ufs/ext2fs/ext2fs_inode.c
--- a/sys/ufs/ext2fs/ext2fs_inode.c     Wed Aug 03 19:59:57 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_inode.c     Wed Aug 03 21:53:02 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_inode.c,v 1.82 2015/03/28 19:24:04 maxv Exp $   */
+/*     $NetBSD: ext2fs_inode.c,v 1.83 2016/08/03 21:53:02 jdolecek Exp $       */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.82 2015/03/28 19:24:04 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.83 2016/08/03 21:53:02 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -269,7 +269,7 @@
        ip->i_flag &= ~(IN_MODIFIED | IN_ACCESSED);
        cp = (char *)bp->b_data +
            (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE(fs));
-       e2fs_isave(ip->i_din.e2fs_din, (struct ext2fs_dinode *)cp);
+       e2fs_isave(ip->i_din.e2fs_din, (struct ext2fs_dinode *)cp, EXT2_DINODE_SIZE(fs));
        if ((updflags & (UPDATE_WAIT|UPDATE_DIROP)) != 0 &&
            (flags & IN_MODIFIED) != 0 &&
            (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
diff -r 7d7d26eb604b -r b35c3d403b13 sys/ufs/ext2fs/ext2fs_vfsops.c
--- a/sys/ufs/ext2fs/ext2fs_vfsops.c    Wed Aug 03 19:59:57 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_vfsops.c    Wed Aug 03 21:53:02 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_vfsops.c,v 1.193 2015/03/28 19:24:04 maxv Exp $ */
+/*     $NetBSD: ext2fs_vfsops.c,v 1.194 2016/08/03 21:53:02 jdolecek Exp $     */
 
 /*
  * Copyright (c) 1989, 1991, 1993, 1994
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.193 2015/03/28 19:24:04 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.194 2016/08/03 21:53:02 jdolecek Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -213,7 +213,6 @@
  * XXX Same structure as FFS inodes?  Should we share a common pool?
  */
 struct pool ext2fs_inode_pool;
-struct pool ext2fs_dinode_pool;
 
 extern u_long ext2gennumber;
 
@@ -223,8 +222,6 @@
 
        pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0, 0, 0,
            "ext2fsinopl", &pool_allocator_nointr, IPL_NONE);
-       pool_init(&ext2fs_dinode_pool, sizeof(struct ext2fs_dinode), 0, 0, 0,
-           "ext2dinopl", &pool_allocator_nointr, IPL_NONE);
        ufs_init();
 }
 
@@ -240,7 +237,6 @@
 
        ufs_done();
        pool_destroy(&ext2fs_inode_pool);
-       pool_destroy(&ext2fs_dinode_pool);
 }
 
 /*
@@ -497,6 +493,43 @@
 }
 
 /*
+ *
+ */
+static int
+ext2fs_loadvnode_content(struct m_ext2fs *fs, ino_t ino, struct buf *bp, struct inode *ip)
+{
+       struct ext2fs_dinode *din;
+       void *cp;
+       int error = 0;
+
+       cp = (char *)bp->b_data + (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE(fs));
+       din = kmem_alloc(EXT2_DINODE_SIZE(fs), KM_SLEEP);
+       e2fs_iload((struct ext2fs_dinode *)cp, din, EXT2_DINODE_SIZE(fs));
+
+       /* sanity checks */
+       if (EXT2_DINODE_FITS(din, e2di_extra_isize, EXT2_DINODE_SIZE(fs))
+           && (EXT2_DINODE_SIZE(fs) - EXT2_REV0_DINODE_SIZE) < din->e2di_extra_isize)
+       {
+               printf("ext2fs: inode %llu bad extra_isize %u",
+                       ino, din->e2di_extra_isize);
+               error = EINVAL;
+               goto bad;
+       }
+
+       /* replace old dinode; assumes new dinode size is same as old one */
+       if (ip->i_din.e2fs_din)
+               kmem_free(ip->i_din.e2fs_din, EXT2_DINODE_SIZE(fs));
+       ip->i_din.e2fs_din = din;
+
+       ext2fs_set_inode_guid(ip);
+       return (error);
+
+    bad:



Home | Main Index | Thread Index | Old Index