[PATCH] blkid: retport block size of a filesystem

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

 



This patch extends libblkid, so that it reports filesystem block size.

When blkid returns a specific number in the BLOCK_SIZE attribute, it 
guarantees that all the bios submitted by the filesystem are aligned on 
this boundary.

We need this because when we want to enable dm-integrity or dm-writecache 
on an existing filesystem, we need to know filesystem block size, so that 
dm-integrity or dm-writecache is initialized with matching block size.

We could always use block size 512 for dm-integrity and dm-writecache, but
that would cause metadata overhead and performance degradation. On the
other hand, if we used block size 4096, it would fail if the filesystem
has smaller blocksize.

Signed-off-by: Mikulas Patocka <mpatocka@xxxxxxxxxx>

---
 libblkid/src/superblocks/apfs.c        |    2 
 libblkid/src/superblocks/befs.c        |    3 +
 libblkid/src/superblocks/btrfs.c       |    1 
 libblkid/src/superblocks/exfat.c       |    2 
 libblkid/src/superblocks/exfs.c        |    4 +
 libblkid/src/superblocks/ext.c         |    3 +
 libblkid/src/superblocks/f2fs.c        |    2 
 libblkid/src/superblocks/gfs.c         |    1 
 libblkid/src/superblocks/hfs.c         |    2 
 libblkid/src/superblocks/hpfs.c        |    1 
 libblkid/src/superblocks/iso9660.c     |    2 
 libblkid/src/superblocks/jfs.c         |    1 
 libblkid/src/superblocks/minix.c       |    5 ++
 libblkid/src/superblocks/nilfs.c       |    3 +
 libblkid/src/superblocks/ntfs.c        |    2 
 libblkid/src/superblocks/ocfs.c        |    3 +
 libblkid/src/superblocks/reiserfs.c    |   10 +++-
 libblkid/src/superblocks/romfs.c       |    3 +
 libblkid/src/superblocks/squashfs.c    |    2 
 libblkid/src/superblocks/superblocks.c |    7 +++
 libblkid/src/superblocks/superblocks.h |    2 
 libblkid/src/superblocks/udf.c         |    2 
 libblkid/src/superblocks/ufs.c         |    5 ++
 libblkid/src/superblocks/vfat.c        |    2 
 libblkid/src/superblocks/vxfs.c        |   18 +++++++
 libblkid/src/superblocks/xfs.c         |    1 
 libblkid/src/superblocks/zfs.c         |   76 ++++++++++++++++++++++++---------
 27 files changed, 144 insertions(+), 21 deletions(-)

Index: util-linux/libblkid/src/superblocks/ext.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/ext.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/ext.c	2019-08-29 15:44:56.000000000 +0200
@@ -187,6 +187,9 @@ static void ext_get_info(blkid_probe pr,
 	blkid_probe_sprintf_version(pr, "%u.%u",
 		le32_to_cpu(es->s_rev_level),
 		le16_to_cpu(es->s_minor_rev_level));
+
+	if (le32_to_cpu(es->s_log_block_size) < 32)
+		blkid_probe_set_block_size(pr, 1024U << le32_to_cpu(es->s_log_block_size));
 }
 
 
Index: util-linux/libblkid/src/superblocks/superblocks.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/superblocks.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/superblocks.c	2019-08-29 15:44:38.000000000 +0200
@@ -74,6 +74,8 @@
  * @APPLICATION_ID: ISO9660 application identifier
  *
  * @BOOT_SYSTEM_ID: ISO9660 boot system identifier
+ *
+ * @BLOCK_SIZE: block size
  */
 
 static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn);
@@ -553,6 +555,11 @@ int blkid_probe_sprintf_version(blkid_pr
 	return rc;
 }
 
+int blkid_probe_set_block_size(blkid_probe pr, unsigned block_size)
+{
+	return blkid_probe_sprintf_value(pr, "BLOCK_SIZE", "%u", block_size);
+}
+
 static int blkid_probe_set_usage(blkid_probe pr, int usage)
 {
 	struct blkid_chain *chn = blkid_probe_get_chain(pr);
Index: util-linux/libblkid/src/superblocks/superblocks.h
===================================================================
--- util-linux.orig/libblkid/src/superblocks/superblocks.h	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/superblocks.h	2019-08-29 15:44:38.000000000 +0200
@@ -108,6 +108,8 @@ extern int blkid_probe_set_id_label(blki
 extern int blkid_probe_set_utf8_id_label(blkid_probe pr, const char *name,
 			     const unsigned char *data, size_t len, int enc);
 
+int blkid_probe_set_block_size(blkid_probe pr, unsigned block_size);
+
 extern int blkid_probe_is_bitlocker(blkid_probe pr);
 
 #endif /* _BLKID_SUPERBLOCKS_H */
Index: util-linux/libblkid/src/superblocks/apfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/apfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/apfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -65,6 +65,8 @@ static int probe_apfs(blkid_probe pr, co
 	if (blkid_probe_set_uuid(pr, sb->uuid) < 0)
 		return BLKID_PROBE_NONE;
 
+	blkid_probe_set_block_size(pr, le32_to_cpu(sb->block_size));
+
 	return BLKID_PROBE_OK;
 }
 
Index: util-linux/libblkid/src/superblocks/btrfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/btrfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/btrfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -74,6 +74,7 @@ static int probe_btrfs(blkid_probe pr, c
 
 	blkid_probe_set_uuid(pr, bfs->fsid);
 	blkid_probe_set_uuid_as(pr, bfs->dev_item.uuid, "UUID_SUB");
+	blkid_probe_set_block_size(pr, le32_to_cpu(bfs->sectorsize));
 
 	return 0;
 }
Index: util-linux/libblkid/src/superblocks/hfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/hfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/hfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -241,6 +241,8 @@ static int probe_hfsplus(blkid_probe pr,
 	if (blocksize < HFSPLUS_SECTOR_SIZE)
 		return 1;
 
+	blkid_probe_set_block_size(pr, blocksize);
+
 	memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
 	cat_block = be32_to_cpu(extents[0].start_block);
 
Index: util-linux/libblkid/src/superblocks/hpfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/hpfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/hpfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -99,6 +99,7 @@ static int probe_hpfs(blkid_probe pr, co
 				hbb->vol_serno[1], hbb->vol_serno[0]);
 	}
 	blkid_probe_sprintf_version(pr, "%u", version);
+	blkid_probe_set_block_size(pr, 512);
 
 	return 0;
 }
Index: util-linux/libblkid/src/superblocks/iso9660.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/iso9660.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/iso9660.c	2019-08-29 15:44:38.000000000 +0200
@@ -182,6 +182,8 @@ static int probe_iso9660(blkid_probe pr,
 
 	memcpy(label, iso->volume_id, sizeof(label));
 
+	blkid_probe_set_block_size(pr, 2048);
+
 	if (!is_str_empty(iso->system_id, sizeof(iso->system_id)))
 		blkid_probe_set_id_label(pr, "SYSTEM_ID",
 				iso->system_id, sizeof(iso->system_id));
Index: util-linux/libblkid/src/superblocks/jfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/jfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/jfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -52,6 +52,7 @@ static int probe_jfs(blkid_probe pr, con
 	if (*((char *) js->js_label) != '\0')
 		blkid_probe_set_label(pr, js->js_label, sizeof(js->js_label));
 	blkid_probe_set_uuid(pr, js->js_uuid);
+	blkid_probe_set_block_size(pr, le32_to_cpu(js->js_bsize));
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/minix.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/minix.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/minix.c	2019-08-29 15:44:38.000000000 +0200
@@ -80,6 +80,7 @@ static int probe_minix(blkid_probe pr,
 	unsigned long zones, ninodes, imaps, zmaps;
 	off_t firstz;
 	size_t zone_size;
+	unsigned block_size;
 
 	data = blkid_probe_get_buffer(pr, 1024,
 			max(sizeof(struct minix_super_block),
@@ -103,6 +104,7 @@ static int probe_minix(blkid_probe pr,
 		zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
 		firstz  = minix_swab16(swabme, sb->s_firstdatazone);
 		zone_size = sb->s_log_zone_size;
+		block_size = 1024;
 		break;
 	}
 	case 3: {
@@ -114,6 +116,8 @@ static int probe_minix(blkid_probe pr,
 		zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
 		firstz  = minix_swab16(swabme, sb->s_firstdatazone);
 		zone_size = sb->s_log_zone_size;
+		block_size = minix_swab16(swabme, sb->s_blocksize);
+
 		break;
 	}
 	default:
@@ -143,6 +147,7 @@ static int probe_minix(blkid_probe pr,
 		return 1;
 
 	blkid_probe_sprintf_version(pr, "%d", version);
+	blkid_probe_set_block_size(pr, block_size);
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/nilfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/nilfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/nilfs.c	2019-08-29 15:45:18.000000000 +0200
@@ -157,6 +157,9 @@ static int probe_nilfs2(blkid_probe pr,
 				(unsigned char *) &sb->s_magic))
 		return 1;
 
+	if (le32_to_cpu(sb->s_log_block_size) < 32)
+		blkid_probe_set_block_size(pr, 1024U << le32_to_cpu(sb->s_log_block_size));
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/ocfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/ocfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/ocfs.c	2019-08-29 15:45:45.000000000 +0200
@@ -153,6 +153,9 @@ static int probe_ocfs2(blkid_probe pr, c
 		le16_to_cpu(osb->s_major_rev_level),
 		le16_to_cpu(osb->s_minor_rev_level));
 
+	if (le32_to_cpu(osb->s_blocksize_bits) < 32)
+		blkid_probe_set_block_size(pr, 1U << le32_to_cpu(osb->s_blocksize_bits));
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/reiserfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/reiserfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/reiserfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -32,7 +32,8 @@ struct reiserfs_super_block {
 
 struct reiser4_super_block {
 	unsigned char	rs4_magic[16];
-	uint16_t	rs4_dummy[2];
+	uint8_t		rs4_dummy[3];
+	uint8_t		rs4_blocksize;
 	unsigned char	rs4_uuid[16];
 	unsigned char	rs4_label[16];
 	uint64_t	rs4_dummy2;
@@ -73,22 +74,29 @@ static int probe_reiser(blkid_probe pr,
 	else
 		blkid_probe_set_version(pr, "3.5");
 
+	blkid_probe_set_block_size(pr, blocksize);
+
 	return 0;
 }
 
 static int probe_reiser4(blkid_probe pr, const struct blkid_idmag *mag)
 {
 	struct reiser4_super_block *rs4;
+	unsigned int blocksize;
 
 	rs4 = blkid_probe_get_sb(pr, mag, struct reiser4_super_block);
 	if (!rs4)
 		return errno ? -errno : 1;
 
+	blocksize = rs4->rs4_blocksize * 256;
+
 	if (*rs4->rs4_label)
 		blkid_probe_set_label(pr, rs4->rs4_label, sizeof(rs4->rs4_label));
 	blkid_probe_set_uuid(pr, rs4->rs4_uuid);
 	blkid_probe_set_version(pr, "4");
 
+	blkid_probe_set_block_size(pr, blocksize);
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/xfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/xfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/xfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -173,6 +173,7 @@ static int probe_xfs(blkid_probe pr, con
 		blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname,
 				sizeof(xs->sb_fname));
 	blkid_probe_set_uuid(pr, xs->sb_uuid);
+	blkid_probe_set_block_size(pr, xs->sb_sectsize * 256);
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/vfat.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/vfat.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/vfat.c	2019-08-29 15:44:38.000000000 +0200
@@ -220,6 +220,8 @@ static int fat_valid_superblock(blkid_pr
 	    sector_size < 512 || sector_size > 4096)
 		return 0;
 
+	blkid_probe_set_block_size(pr, sector_size);
+
 	dir_entries = unaligned_le16(&ms->ms_dir_entries);
 	reserved =  le16_to_cpu(ms->ms_reserved);
 	sect_count = unaligned_le16(&ms->ms_sectors);
Index: util-linux/libblkid/src/superblocks/gfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/gfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/gfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -98,6 +98,7 @@ static int probe_gfs2(blkid_probe pr, co
 				sizeof(sbd->sb_locktable));
 		blkid_probe_set_uuid(pr, sbd->sb_uuid);
 		blkid_probe_set_version(pr, "1");
+		blkid_probe_set_block_size(pr, be32_to_cpu(sbd->sb_bsize));
 		return 0;
 	}
 	return 1;
Index: util-linux/libblkid/src/superblocks/befs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/befs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/befs.c	2019-08-29 15:44:38.000000000 +0200
@@ -519,6 +519,9 @@ static int probe_befs(blkid_probe pr, co
 		blkid_probe_sprintf_uuid(pr, (unsigned char *) &volume_id,
 					sizeof(volume_id), "%016" PRIx64,
 					FS64_TO_CPU(volume_id, fs_le));
+
+	blkid_probe_set_block_size(pr, block_size);
+
 	return BLKID_PROBE_OK;
 }
 
Index: util-linux/libblkid/src/superblocks/exfat.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/exfat.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/exfat.c	2019-08-29 15:44:38.000000000 +0200
@@ -137,6 +137,8 @@ static int probe_exfat(blkid_probe pr, c
 	blkid_probe_sprintf_version(pr, "%u.%u",
 			sb->version.vermaj, sb->version.vermin);
 
+	blkid_probe_set_block_size(pr, BLOCK_SIZE(sb));
+
 	return BLKID_PROBE_OK;
 }
 
Index: util-linux/libblkid/src/superblocks/exfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/exfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/exfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -170,7 +170,11 @@ static int probe_exfs(blkid_probe pr, co
 	if (*xs->sb_fname != '\0')
 		blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname,
 				sizeof(xs->sb_fname));
+
 	blkid_probe_set_uuid(pr, xs->sb_uuid);
+
+	blkid_probe_set_block_size(pr, be32_to_cpu(xs->sb_blocksize));
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/f2fs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/f2fs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/f2fs.c	2019-08-29 15:46:17.000000000 +0200
@@ -78,6 +78,8 @@ static int probe_f2fs(blkid_probe pr, co
 
 	blkid_probe_set_uuid(pr, sb->uuid);
 	blkid_probe_sprintf_version(pr, "%u.%u", vermaj, vermin);
+	if (le32_to_cpu(sb->log_blocksize) < 32)
+		blkid_probe_set_block_size(pr, 1U << le32_to_cpu(sb->log_blocksize));
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/ntfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/ntfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/ntfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -204,6 +204,8 @@ static int probe_ntfs(blkid_probe pr, co
 		attr_off += attr_len;
 	}
 
+	blkid_probe_set_block_size(pr, sector_size);
+
 	blkid_probe_sprintf_uuid(pr,
 			(unsigned char *) &ns->volume_serial,
 			sizeof(ns->volume_serial),
Index: util-linux/libblkid/src/superblocks/romfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/romfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/romfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -34,6 +34,9 @@ static int probe_romfs(blkid_probe pr, c
 	if (*((char *) ros->ros_volume) != '\0')
 		blkid_probe_set_label(pr, ros->ros_volume,
 				sizeof(ros->ros_volume));
+
+	blkid_probe_set_block_size(pr, 1024);
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/squashfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/squashfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/squashfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -71,6 +71,8 @@ static int probe_squashfs3(blkid_probe p
 
 	blkid_probe_sprintf_version(pr, "%u.%u", vermaj, vermin);
 
+	blkid_probe_set_block_size(pr, 1024);
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/udf.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/udf.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/udf.c	2019-08-29 15:44:38.000000000 +0200
@@ -464,6 +464,8 @@ real_blksz:
 		 * E.g. number 0x0150 is revision 1.50, number 0x0201 is revision 2.01. */
 		blkid_probe_sprintf_version(pr, "%x.%02x", (unsigned int)(udf_rev >> 8), (unsigned int)(udf_rev & 0xFF));
 
+	blkid_probe_set_block_size(pr, bs);
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/ufs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/ufs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/ufs.c	2019-08-29 15:44:38.000000000 +0200
@@ -233,6 +233,11 @@ found:
 			(unsigned char *) &ufs->fs_magic))
 		return 1;
 
+	if (!is_be)
+		blkid_probe_set_block_size(pr, le32_to_cpu(ufs->fs_fsize));
+	else
+		blkid_probe_set_block_size(pr, be32_to_cpu(ufs->fs_fsize));
+
 	return 0;
 }
 
Index: util-linux/libblkid/src/superblocks/vxfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/vxfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/vxfs.c	2019-08-29 15:44:38.000000000 +0200
@@ -12,6 +12,15 @@
 struct vxfs_super_block {
 	uint32_t		vs_magic;
 	int32_t			vs_version;
+	uint32_t		vs_ctime;
+	uint32_t		vs_cutime;
+	uint32_t		__unused1;
+	uint32_t		__unused2;
+	uint32_t		vs_old_logstart;
+	uint32_t		vs_old_logend;
+	uint32_t		vs_bsize;
+	uint32_t		vs_size;
+	uint32_t		vs_dsize;
 };
 
 static int probe_vxfs(blkid_probe pr, const struct blkid_idmag *mag)
@@ -22,7 +31,13 @@ static int probe_vxfs(blkid_probe pr, co
 	if (!vxs)
 		return errno ? -errno : 1;
 
-	blkid_probe_sprintf_version(pr, "%u", (unsigned int) vxs->vs_version);
+	if (le32_to_cpu(vxs->vs_magic) == 0xa501fcf5) {
+		blkid_probe_sprintf_version(pr, "%u", (unsigned int)le32_to_cpu(vxs->vs_version));
+		blkid_probe_set_block_size(pr, le32_to_cpu(vxs->vs_bsize));
+	} else if (be32_to_cpu(vxs->vs_magic) == 0xa501fcf5) {
+		blkid_probe_sprintf_version(pr, "%u", (unsigned int)be32_to_cpu(vxs->vs_version));
+		blkid_probe_set_block_size(pr, be32_to_cpu(vxs->vs_bsize));
+	}
 	return 0;
 }
 
@@ -35,6 +50,7 @@ const struct blkid_idinfo vxfs_idinfo =
 	.magics		=
 	{
 		{ .magic = "\365\374\001\245", .len = 4, .kboff = 1 },
+		{ .magic = "\245\001\374\365", .len = 4, .kboff = 8 },
 		{ NULL }
 	}
 };
Index: util-linux/libblkid/src/superblocks/zfs.c
===================================================================
--- util-linux.orig/libblkid/src/superblocks/zfs.c	2019-08-29 15:44:38.000000000 +0200
+++ util-linux/libblkid/src/superblocks/zfs.c	2019-08-29 15:46:36.000000000 +0200
@@ -37,6 +37,7 @@ struct zfs_uberblock {
 
 #define DATA_TYPE_UINT64 8
 #define DATA_TYPE_STRING 9
+#define DATA_TYPE_DIRECTORY 19
 
 struct nvpair {
 	uint32_t	nvp_size;
@@ -60,32 +61,37 @@ struct nvuint64 {
 	uint64_t	nvu_value;
 };
 
+struct nvdirectory {
+	uint32_t	nvd_type;
+	uint32_t	nvd_unknown[3];
+};
+
 struct nvlist {
 	uint32_t	nvl_unknown[3];
 	struct nvpair	nvl_nvpair;
 };
 
-static int zfs_process_value(blkid_probe pr, char *name, size_t namelen,
-			     void *value, size_t max_value_size)
+static void zfs_process_value(blkid_probe pr, char *name, size_t namelen,
+			     void *value, size_t max_value_size, unsigned directory_level)
 {
 	if (strncmp(name, "name", namelen) == 0 &&
-	    sizeof(struct nvstring) <= max_value_size) {
+	    sizeof(struct nvstring) <= max_value_size &&
+	    !directory_level) {
 		struct nvstring *nvs = value;
 		uint32_t nvs_type = be32_to_cpu(nvs->nvs_type);
 		uint32_t nvs_strlen = be32_to_cpu(nvs->nvs_strlen);
 
 		if (nvs_type != DATA_TYPE_STRING ||
 		    (uint64_t)nvs_strlen + sizeof(*nvs) > max_value_size)
-			return 0;
+			return;
 
 		DBG(LOWPROBE, ul_debug("nvstring: type %u string %*s\n",
 				       nvs_type, nvs_strlen, nvs->nvs_string));
 
 		blkid_probe_set_label(pr, nvs->nvs_string, nvs_strlen);
-
-		return 1;
 	} else if (strncmp(name, "guid", namelen) == 0 &&
-		   sizeof(struct nvuint64) <= max_value_size) {
+		   sizeof(struct nvuint64) <= max_value_size &&
+		   !directory_level) {
 		struct nvuint64 *nvu = value;
 		uint32_t nvu_type = be32_to_cpu(nvu->nvu_type);
 		uint64_t nvu_value;
@@ -94,17 +100,16 @@ static int zfs_process_value(blkid_probe
 		nvu_value = be64_to_cpu(nvu_value);
 
 		if (nvu_type != DATA_TYPE_UINT64)
-			return 0;
+			return;
 
 		DBG(LOWPROBE, ul_debug("nvuint64: type %u value %"PRIu64"\n",
 				       nvu_type, nvu_value));
 
 		blkid_probe_sprintf_value(pr, "UUID_SUB",
 					  "%"PRIu64, nvu_value);
-
-		return 1;
 	} else if (strncmp(name, "pool_guid", namelen) == 0 &&
-		   sizeof(struct nvuint64) <= max_value_size) {
+		   sizeof(struct nvuint64) <= max_value_size &&
+		   !directory_level) {
 		struct nvuint64 *nvu = value;
 		uint32_t nvu_type = be32_to_cpu(nvu->nvu_type);
 		uint64_t nvu_value;
@@ -113,7 +118,7 @@ static int zfs_process_value(blkid_probe
 		nvu_value = be64_to_cpu(nvu_value);
 
 		if (nvu_type != DATA_TYPE_UINT64)
-			return 0;
+			return;
 
 		DBG(LOWPROBE, ul_debug("nvuint64: type %u value %"PRIu64"\n",
 				       nvu_type, nvu_value));
@@ -121,10 +126,21 @@ static int zfs_process_value(blkid_probe
 		blkid_probe_sprintf_uuid(pr, (unsigned char *) &nvu_value,
 					 sizeof(nvu_value),
 					 "%"PRIu64, nvu_value);
-		return 1;
-	}
+	} else if (strncmp(name, "ashift", namelen) == 0 &&
+		   sizeof(struct nvuint64) <= max_value_size) {
+		struct nvuint64 *nvu = value;
+		uint32_t nvu_type = be32_to_cpu(nvu->nvu_type);
+		uint64_t nvu_value;
 
-	return 0;
+		memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value));
+		nvu_value = be64_to_cpu(nvu_value);
+
+		if (nvu_type != DATA_TYPE_UINT64)
+			return;
+
+		if (nvu_value < 32)
+			blkid_probe_set_block_size(pr, 1U << nvu_value);
+	}
 }
 
 static void zfs_extract_guid_name(blkid_probe pr, loff_t offset)
@@ -133,7 +149,7 @@ static void zfs_extract_guid_name(blkid_
 	struct nvlist *nvl;
 	struct nvpair *nvp;
 	size_t left = 4096;
-	int found = 0;
+	unsigned directory_level = 0;
 
 	offset = (offset & ~(VDEV_LABEL_SIZE - 1)) + VDEV_LABEL_NVPAIR;
 
@@ -152,16 +168,26 @@ static void zfs_extract_guid_name(blkid_
 	nvp = &nvl->nvl_nvpair;
 	left -= (unsigned char *)nvp - p; /* Already used up 12 bytes */
 
-	while (left > sizeof(*nvp) && nvp->nvp_size != 0 && found < 3) {
+	while (left > sizeof(*nvp)) {
 		uint32_t nvp_size = be32_to_cpu(nvp->nvp_size);
 		uint32_t nvp_namelen = be32_to_cpu(nvp->nvp_namelen);
 		uint64_t namesize = ((uint64_t)nvp_namelen + 3) & ~3;
 		size_t max_value_size;
 		void *value;
 
+		if (!nvp->nvp_size) {
+			if (!directory_level)
+				break;
+			directory_level--;
+			nvp_size = 8;
+			goto cont;
+		}
+
 		DBG(LOWPROBE, ul_debug("left %zd nvp_size %u\n",
 				       left, nvp_size));
 
+		fprintf(stderr, "processing: '%.*s'\n", nvp_namelen, nvp->nvp_name);
+
 		/* nvpair fits in buffer and name fits in nvpair? */
 		if (nvp_size > left || namesize + sizeof(*nvp) > nvp_size)
 			break;
@@ -174,9 +200,21 @@ static void zfs_extract_guid_name(blkid_
 		max_value_size = nvp_size - (namesize + sizeof(*nvp));
 		value = nvp->nvp_name + namesize;
 
-		found += zfs_process_value(pr, nvp->nvp_name, nvp_namelen,
-					   value, max_value_size);
+		if (sizeof(struct nvdirectory) <= max_value_size) {
+			struct nvdirectory *nvu = value;
+			if (be32_to_cpu(nvu->nvd_type) == DATA_TYPE_DIRECTORY) {
+				nvp_size = sizeof(*nvp) + namesize + sizeof(*nvu);
+				directory_level++;
+				goto cont;
+			}
+		}
 
+		zfs_process_value(pr, nvp->nvp_name, nvp_namelen,
+				  value, max_value_size, directory_level);
+
+cont:
+		if (nvp_size > left)
+			break;
 		left -= nvp_size;
 
 		nvp = (struct nvpair *)((char *)nvp + nvp_size);

--
dm-devel mailing list
dm-devel@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/dm-devel



[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux