From owner-svn-src-head@freebsd.org Mon Jan 29 21:54:14 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4D2C5EE0EE3; Mon, 29 Jan 2018 21:54:14 +0000 (UTC) (envelope-from fsu@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 002FF689D4; Mon, 29 Jan 2018 21:54:13 +0000 (UTC) (envelope-from fsu@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id EF2ED6215; Mon, 29 Jan 2018 21:54:13 +0000 (UTC) (envelope-from fsu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w0TLsDX3008819; Mon, 29 Jan 2018 21:54:13 GMT (envelope-from fsu@FreeBSD.org) Received: (from fsu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w0TLsDsR008816; Mon, 29 Jan 2018 21:54:13 GMT (envelope-from fsu@FreeBSD.org) Message-Id: <201801292154.w0TLsDsR008816@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: fsu set sender to fsu@FreeBSD.org using -f From: Fedor Uporov Date: Mon, 29 Jan 2018 21:54:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r328564 - head/sys/fs/ext2fs X-SVN-Group: head X-SVN-Commit-Author: fsu X-SVN-Commit-Paths: head/sys/fs/ext2fs X-SVN-Commit-Revision: 328564 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Jan 2018 21:54:14 -0000 Author: fsu Date: Mon Jan 29 21:54:13 2018 New Revision: 328564 URL: https://svnweb.freebsd.org/changeset/base/328564 Log: Add flex_bg/meta_bg features RW support. Reviewed by: pfg MFC after: 6 months Differential Revision: https://reviews.freebsd.org/D13964 Modified: head/sys/fs/ext2fs/ext2_alloc.c head/sys/fs/ext2fs/ext2_vfsops.c head/sys/fs/ext2fs/ext2fs.h Modified: head/sys/fs/ext2fs/ext2_alloc.c ============================================================================== --- head/sys/fs/ext2fs/ext2_alloc.c Mon Jan 29 21:16:56 2018 (r328563) +++ head/sys/fs/ext2fs/ext2_alloc.c Mon Jan 29 21:54:13 2018 (r328564) @@ -755,49 +755,68 @@ ext2_hashalloc(struct inode *ip, int cg, long pref, in } static unsigned long -ext2_cg_num_gdb(struct m_ext2fs *fs, int cg) +ext2_cg_number_gdb_nometa(struct m_ext2fs *fs, int cg) { - int gd_per_block, metagroup, first, last; - gd_per_block = fs->e2fs_bsize / sizeof(struct ext2_gd); - metagroup = cg / gd_per_block; - first = metagroup * gd_per_block; - last = first + gd_per_block - 1; + if (!ext2_cg_has_sb(fs, cg)) + return (0); - if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) || - metagroup < fs->e2fs->e3fs_first_meta_bg) { - if (!ext2_cg_has_sb(fs, cg)) - return (0); - if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG)) - return (fs->e2fs->e3fs_first_meta_bg); - return (fs->e2fs_gdbcount); - } + if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG)) + return (fs->e2fs->e3fs_first_meta_bg); + return ((fs->e2fs_gcount + EXT2_DESCS_PER_BLOCK(fs) - 1) / + EXT2_DESCS_PER_BLOCK(fs)); +} + +static unsigned long +ext2_cg_number_gdb_meta(struct m_ext2fs *fs, int cg) +{ + unsigned long metagroup; + int first, last; + + metagroup = cg / EXT2_DESCS_PER_BLOCK(fs); + first = metagroup * EXT2_DESCS_PER_BLOCK(fs); + last = first + EXT2_DESCS_PER_BLOCK(fs) - 1; + if (cg == first || cg == first + 1 || cg == last) return (1); + return (0); +} +static unsigned long +ext2_cg_number_gdb(struct m_ext2fs *fs, int cg) +{ + unsigned long first_meta_bg, metagroup; + + first_meta_bg = fs->e2fs->e3fs_first_meta_bg; + metagroup = cg / EXT2_DESCS_PER_BLOCK(fs); + + if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) || + metagroup < first_meta_bg) + return (ext2_cg_number_gdb_nometa(fs, cg)); + + return ext2_cg_number_gdb_meta(fs, cg); } static int -ext2_num_base_meta_blocks(struct m_ext2fs *fs, int cg) +ext2_number_base_meta_blocks(struct m_ext2fs *fs, int cg) { - int num, gd_per_block; + int number; - gd_per_block = fs->e2fs_bsize / sizeof(struct ext2_gd); - num = ext2_cg_has_sb(fs, cg); + number = ext2_cg_has_sb(fs, cg); if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) || - cg < fs->e2fs->e3fs_first_meta_bg * gd_per_block) { - if (num) { - num += ext2_cg_num_gdb(fs, cg); - num += fs->e2fs->e2fs_reserved_ngdb; + cg < fs->e2fs->e3fs_first_meta_bg * EXT2_DESCS_PER_BLOCK(fs)) { + if (number) { + number += ext2_cg_number_gdb(fs, cg); + number += fs->e2fs->e2fs_reserved_ngdb; } } else { - num += ext2_cg_num_gdb(fs, cg); + number += ext2_cg_number_gdb(fs, cg); } - - return (num); + + return (number); } static void @@ -815,6 +834,20 @@ ext2_mark_bitmap_end(int start_bit, int end_bit, char } static int +ext2_get_group_number(struct m_ext2fs *fs, e4fs_daddr_t block) +{ + + return ((block - fs->e2fs->e2fs_first_dblock) / fs->e2fs_bsize); +} + +static int +ext2_block_in_group(struct m_ext2fs *fs, e4fs_daddr_t block, int cg) +{ + + return ((ext2_get_group_number(fs, block) == cg) ? 1 : 0); +} + +static int ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp) { int bit, bit_max, inodes_per_block; @@ -825,7 +858,7 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, memset(bp->b_data, 0, fs->e2fs_bsize); - bit_max = ext2_num_base_meta_blocks(fs, cg); + bit_max = ext2_number_base_meta_blocks(fs, cg); if ((bit_max >> 3) >= fs->e2fs_bsize) return (EINVAL); @@ -837,12 +870,12 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, /* Set bits for block and inode bitmaps, and inode table. */ tmp = e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg]); if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) || - cg == dtogd(fs, tmp)) + ext2_block_in_group(fs, tmp, cg)) setbit(bp->b_data, tmp - start); tmp = e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg]); if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) || - cg == dtogd(fs, tmp)) + ext2_block_in_group(fs, tmp, cg)) setbit(bp->b_data, tmp - start); tmp = e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]); @@ -850,7 +883,7 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, while( tmp < e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) + fs->e2fs->e2fs_ipg / inodes_per_block ) { if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) || - cg == dtogd(fs, tmp)) + ext2_block_in_group(fs, tmp, cg)) setbit(bp->b_data, tmp - start); tmp++; } Modified: head/sys/fs/ext2fs/ext2_vfsops.c ============================================================================== --- head/sys/fs/ext2fs/ext2_vfsops.c Mon Jan 29 21:16:56 2018 (r328563) +++ head/sys/fs/ext2fs/ext2_vfsops.c Mon Jan 29 21:54:13 2018 (r328564) @@ -154,7 +154,8 @@ ext2_mount(struct mount *mp) if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = ext2_flushfiles(mp, flags, td); - if (error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) { + if (error == 0 && fs->e2fs_wasvalid && + ext2_cgupdate(ump, MNT_WAIT) == 0) { fs->e2fs->e2fs_state |= E2FS_ISCLEAN; ext2_sbupdate(ump, MNT_WAIT); } @@ -318,6 +319,36 @@ ext2_check_sb_compat(struct ext2fs *es, struct cdev *d return (0); } +static e4fs_daddr_t +cg_location(struct m_ext2fs *fs, int number) +{ + int cg, descpb, logical_sb, has_super = 0; + + /* + * Adjust logical superblock block number. + * Godmar thinks: if the blocksize is greater than 1024, then + * the superblock is logically part of block zero. + */ + logical_sb = fs->e2fs_bsize > SBSIZE ? 0 : 1; + + if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) || + number < fs->e2fs->e3fs_first_meta_bg) + return (logical_sb + number + 1); + + if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) + descpb = fs->e2fs_bsize / sizeof(struct ext2_gd); + else + descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE; + + cg = descpb * number; + + if (ext2_cg_has_sb(fs, cg)) + has_super = 1; + + return (has_super + cg * (e4fs_daddr_t)EXT2_BLOCKS_PER_GROUP(fs) + + fs->e2fs->e2fs_first_dblock); +} + /* * This computes the fields of the m_ext2fs structure from the * data in the ext2fs structure read in. @@ -328,7 +359,6 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es { int g_count = 0, error; int i, j; - int logic_sb_block = 1; /* XXX for now */ struct buf *bp; uint32_t e2fs_descpb, e2fs_gdbcount_alloc; @@ -385,6 +415,12 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es es->e3fs_desc_size); return (EINVAL); } + /* Check for group size */ + if (fs->e2fs_bpg != fs->e2fs_bsize * 8) { + printf("ext2fs: non-standard group size unsupported %d\n", + fs->e2fs_bpg); + return (EINVAL); + } fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs); fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb; @@ -405,16 +441,9 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es fs->e2fs_contigdirs = malloc(fs->e2fs_gcount * sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO); - /* - * Adjust logic_sb_block. - * Godmar thinks: if the blocksize is greater than 1024, then - * the superblock is logically part of block zero. - */ - if (fs->e2fs_bsize > SBSIZE) - logic_sb_block = 0; for (i = 0; i < fs->e2fs_gdbcount; i++) { error = bread(devvp, - fsbtodb(fs, logic_sb_block + i + 1), + fsbtodb(fs, cg_location(fs, i)), fs->e2fs_bsize, NOCRED, &bp); if (error) { free(fs->e2fs_contigdirs, M_EXT2MNT); @@ -1151,8 +1180,8 @@ ext2_cgupdate(struct ext2mount *mp, int waitfor) for (i = 0; i < fs->e2fs_gdbcount; i++) { bp = getblk(mp->um_devvp, fsbtodb(fs, - fs->e2fs->e2fs_first_dblock + - 1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0); + cg_location(fs, i)), + fs->e2fs_bsize, 0, 0, 0); if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) { memcpy(bp->b_data, &fs->e2fs_gd[ i * fs->e2fs_bsize / sizeof(struct ext2_gd)], Modified: head/sys/fs/ext2fs/ext2fs.h ============================================================================== --- head/sys/fs/ext2fs/ext2fs.h Mon Jan 29 21:16:56 2018 (r328563) +++ head/sys/fs/ext2fs/ext2fs.h Mon Jan 29 21:54:13 2018 (r328564) @@ -334,12 +334,12 @@ static const struct ext2_feature incompat[] = { EXT2F_ROCOMPAT_HUGE_FILE | \ EXT2F_ROCOMPAT_EXTRA_ISIZE) #define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE | \ + EXT2F_INCOMPAT_META_BG | \ EXT2F_INCOMPAT_EXTENTS | \ EXT2F_INCOMPAT_64BIT | \ - EXT2F_INCOMPAT_CSUM_SEED) -#define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_RECOVER | \ EXT2F_INCOMPAT_FLEX_BG | \ - EXT2F_INCOMPAT_META_BG ) + EXT2F_INCOMPAT_CSUM_SEED) +#define EXT4F_RO_INCOMPAT_SUPP EXT2F_INCOMPAT_RECOVER /* Assume that user mode programs are passing in an ext2fs superblock, not * a kernel struct super_block. This will allow us to call the feature-test @@ -423,5 +423,8 @@ struct ext2_gd { * Macro-instructions used to manage group descriptors */ #define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg) +#define EXT2_DESCS_PER_BLOCK(s) (EXT2_HAS_INCOMPAT_FEATURE((s), \ + EXT2F_INCOMPAT_64BIT) ? ((s)->e2fs_bsize / sizeof(struct ext2_gd)) : \ + ((s)->e2fs_bsize / E2FS_REV0_GD_SIZE)) #endif /* !_FS_EXT2FS_EXT2FS_H_ */