lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri,  3 Mar 2017 12:15:48 +0300
From:   Artem Blagodarenko <artem.blagodarenko@...il.com>
To:     linux-ext4@...r.kernel.org
Cc:     adilger.kernel@...ger.ca, alexey.lyashkov@...il.com
Subject: [PATCH] libext2fs: preload block group on request

From: Artem Blagodarenko <artem.blagodarenko@...gate.com>

I send this for descussion. Requested by Andreas Dilger and Alexey Lyashkov.

> But again - I may ask an Artem submit a patch to read GD by demand as =
>it ready again, but it don=E2=80=99t like it due a complexity.

>Sure, it would be good to send it to the list, just to see where =
>complexity is and discuss how it might be fixed.

---
 lib/ext2fs/blknum.c  |   47 +++++++++++++++++++++++++++++++++++++++++++++--
 lib/ext2fs/ext2_fs.h |    1 +
 lib/ext2fs/ext2fs.h  |    1 +
 lib/ext2fs/openfs.c  |   27 ++++++---------------------
 4 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c
index ac80849..b171bac 100644
--- a/lib/ext2fs/blknum.c
+++ b/lib/ext2fs/blknum.c
@@ -186,8 +186,51 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
 					  dgrp_t group)
 {
 	int desc_size = EXT2_DESC_SIZE(fs->super) & ~7;
-
-	return (struct ext2_group_desc *)((char *)gdp + group * desc_size);
+	struct ext2_group_desc *ret_gdp;
+	struct ext2_group_desc *tmp_gdp;
+	char *dest;
+	dgrp_t block;
+	blk64_t blk;
+	int retval;
+	unsigned int i;
+	unsigned int groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
+
+	ret_gdp = (struct ext2_group_desc *)((char *)gdp + group * desc_size);
+
+	if ((ret_gdp->bg_flags & EXT2_BG_READ) == 0) {
+		block = group / groups_per_block;
+		blk = ext2fs_descriptor_block_loc2(fs, fs->group_block, block);
+		dest = (char *) gdp + fs->blocksize * block;
+		retval = io_channel_read_blk64(fs->io, blk, 1, dest);
+		if (retval)
+			return NULL;
+
+		tmp_gdp = (struct ext2_group_desc *)dest;
+
+		for (i=0; i < groups_per_block; i++) {
+			/*
+			 * TDB: If recovery is from backup superblock, Clear
+			 * _UNININT flags & reset bg_itable_unused to zero
+			 */
+#ifdef WORDS_BIGENDIAN
+			ext2fs_swap_group_desc2(fs, tmp_gdp);
+#endif
+			tmp_gdp->bg_flags |= EXT2_BG_READ;
+
+			if (fs->orig_super == 0 &&
+			    EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+			    EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+				ext2fs_bg_flags_clear(fs, block * groups_per_block + i, EXT2_BG_BLOCK_UNINIT);
+				ext2fs_bg_flags_clear(fs,  block * groups_per_block + i, EXT2_BG_INODE_UNINIT);
+				ext2fs_bg_itable_unused_set(fs,  block * groups_per_block + i, 0);
+				// The checksum will be reset later, but fix it here
+				// anyway to avoid printing a lot of spurious errors. 
+				ext2fs_group_desc_csum_set(fs,  block * groups_per_block + i);
+			}
+			tmp_gdp = (struct ext2_group_desc *)((char *)tmp_gdp + EXT2_DESC_SIZE(fs->super));
+		}
+	}
+	return ret_gdp;
 }
 
 /* Do the same but as an ext4 group desc for internal use here */
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 27a7d3a..4858684 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -202,6 +202,7 @@ struct ext4_group_desc
 #define EXT2_BG_INODE_UNINIT	0x0001 /* Inode table/bitmap not initialized */
 #define EXT2_BG_BLOCK_UNINIT	0x0002 /* Block bitmap not initialized */
 #define EXT2_BG_INODE_ZEROED	0x0004 /* On-disk itable initialized to zero */
+#define EXT2_BG_READ		0x0008 /* Block group was read from disk */
 
 /*
  * Data structures used by the directory indexing feature
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 8ff49ca..0ae5cbe 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -221,6 +221,7 @@ struct struct_ext2_filsys {
 	int				fragsize;
 	dgrp_t				group_desc_count;
 	unsigned long			desc_blocks;
+	blk64_t				group_block;
 	struct opaque_ext2_group_desc *	group_desc;
 	unsigned int			inode_blocks_per_group;
 	ext2fs_inode_bitmap		inode_map;
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index ba39e01..5f6cda5 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -121,11 +121,9 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 	blk64_t		group_block, blk;
 	char		*dest, *cp;
 	int		group_zero_adjust = 0;
-#ifdef WORDS_BIGENDIAN
 	unsigned int	groups_per_block;
 	struct ext2_group_desc *gdp;
 	int		j;
-#endif
 
 	EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
 
@@ -412,40 +410,27 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
 					     first_meta_bg, dest);
 		if (retval)
 			goto cleanup;
-#ifdef WORDS_BIGENDIAN
-		gdp = (struct ext2_group_desc *) dest;
 		for (j=0; j < groups_per_block*first_meta_bg; j++) {
 			gdp = ext2fs_group_desc(fs, fs->group_desc, j);
-			ext2fs_swap_group_desc2(fs, gdp);
-		}
-#endif
-		dest += fs->blocksize*first_meta_bg;
-	}
-	for (i=first_meta_bg ; i < fs->desc_blocks; i++) {
-		blk = ext2fs_descriptor_block_loc2(fs, group_block, i);
-		retval = io_channel_read_blk64(fs->io, blk, 1, dest);
-		if (retval)
-			goto cleanup;
 #ifdef WORDS_BIGENDIAN
-		for (j=0; j < groups_per_block; j++) {
-			gdp = ext2fs_group_desc(fs, fs->group_desc,
-						i * groups_per_block + j);
 			ext2fs_swap_group_desc2(fs, gdp);
-		}
 #endif
-		dest += fs->blocksize;
+			gdp->bg_flags |= EXT2_BG_READ;
+		}
+		dest += fs->blocksize*first_meta_bg;
 	}
 
+	fs->group_block = group_block;
 	fs->stride = fs->super->s_raid_stride;
 
 	/*
 	 * If recovery is from backup superblock, Clear _UNININT flags &
 	 * reset bg_itable_unused to zero
 	 */
-	if (superblock > 1 && ext2fs_has_group_desc_csum(fs)) {
+	if (first_meta_bg && superblock > 1 && ext2fs_has_group_desc_csum(fs)) {
 		dgrp_t group;
 
-		for (group = 0; group < fs->group_desc_count; group++) {
+		for (group = 0; group < groups_per_block*first_meta_bg; group++) {
 			ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
 			ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
 			ext2fs_bg_itable_unused_set(fs, group, 0);
-- 
1.7.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ