+# From https://github.com/plougher/squashfs-tools/pull/264
+diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
+--- a/squashfs-tools/mksquashfs.c
++++ b/squashfs-tools/mksquashfs.c
+@@ -180,6 +180,12 @@ int exit_on_error = FALSE;
+ /* Is filesystem stored at an offset from the start of the block device/file? */
+ long long start_offset = 0;
+
++/* Do we have an extra_info metadata block? */
++int extra_info = FALSE;
++/* parameters for the extra_info block */
++char *volume_label = NULL;
++char *uuid = NULL;
++
+ /* File count statistics used to print summary and fill in superblock */
+ unsigned int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0,
+ fifo_count = 0, sock_count = 0, id_count = 0;
+@@ -340,7 +346,7 @@ char *option_table[] = { "comp", "b", "mkfs-time", "fstime", "all-time",
+ "vaf", "taf", "faf", "read-queue", "write-queue", "fragment-queue",
+ "root-time", "root-uid", "root-gid", "xattrs-exclude", "xattrs-include",
+ "xattrs-add", "default-mode", "default-uid", "default-gid",
+- "mem-percent", NULL
++ "mem-percent", "label", "uuid", NULL
+ };
+
+ char *sqfstar_option_table[] = { "comp", "b", "mkfs-time", "fstime", "all-time",
+@@ -6239,6 +6245,8 @@ static void print_options(FILE *stream, char *name, int total_mem)
+ fprintf(stream, "-keep-as-directory\tif one source directory is specified, ");
+ fprintf(stream, "create a root\n");
+ fprintf(stream, "\t\t\tdirectory containing that directory, rather than the\n");
++ fprintf(stream, "-label <volume-label>\tSet the volume label\n");
++ fprintf(stream, "-uuid <UUID>\tSet the volume UUID\n");
+ fprintf(stream, "\t\t\tcontents of the directory\n");
+ fprintf(stream, "\nFilesystem filter options:\n");
+ fprintf(stream, "-p <pseudo-definition>\tadd pseudo file ");
+@@ -7541,6 +7549,7 @@ int sqfstar(int argc, char *argv[])
+ SQUASHFS_MAJOR, SQUASHFS_MINOR,
+ destination_file, block_size);
+
++ bytes = sizeof(struct squashfs_super_block);
+ /*
+ * store any compressor specific options after the superblock,
+ * and set the COMP_OPT flag to show that the filesystem has
+@@ -7554,11 +7563,9 @@ int sqfstar(int argc, char *argv[])
+ sizeof(c_byte), &c_byte);
+ write_destination(fd, sizeof(struct squashfs_super_block) +
+ sizeof(c_byte), size, comp_data);
+- bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte)
+- + size;
++ bytes += sizeof(c_byte) + size;
+ comp_opts = TRUE;
+- } else
+- bytes = sizeof(struct squashfs_super_block);
++ }
+
+ if(path)
+ paths = add_subdir(paths, path);
+@@ -7579,7 +7586,7 @@ int sqfstar(int argc, char *argv[])
+ sBlk.block_log = block_log;
+ sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments,
+ always_use_fragments, duplicate_checking, exportable,
+- no_xattrs, comp_opts);
++ no_xattrs, comp_opts, extra_info);
+ sBlk.mkfs_time = mkfs_time_opt ? mkfs_time : time(NULL);
+
+ disable_info();
+@@ -7629,6 +7636,70 @@ int sqfstar(int argc, char *argv[])
+ }
+
+
++void *info_dump(int *psize) {
++ int bytes = 0, pos = 0;
++ unsigned char *buf;
++ const int UUID_LEN = 16; /* avoid depending on uuid-dev for now */
++ int label_len;
++
++ /* The extra_info section contains one or more entries of the form:
++ TAG byte
++ LEN byte
++ VAL byte_1 ... byte_len
++
++ Terminated by the tag: SQUASHFS_EXTRA_INFO_TAG_END
++ */
++ if (volume_label) {
++ label_len = strlen(volume_label);
++ if (label_len > 255) label_len = 255;
++ bytes += 1 + 1 + label_len;
++ }
++ if (uuid)
++ bytes += 1 + 1 + UUID_LEN;
++ if (!bytes)
++ return NULL;
++ bytes += 1; /* TAG_END */
++
++ buf = malloc(bytes);
++
++ if (volume_label) {
++ buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_LABEL;
++ buf[pos++] = label_len;
++ memcpy(&buf[pos], volume_label, label_len);
++ pos += label_len;
++ }
++ if (uuid) {
++ char *puuid = uuid;
++ buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_UUID;
++ buf[pos++] = UUID_LEN;
++ /* poor man's uuid_parse() */
++ for (int i = 0; i < UUID_LEN; i++) {
++ char hex[3] = {};
++ char *endptr = NULL;
++ if (*puuid == '-') {
++ puuid++;
++ }
++ if (puuid[0] && puuid[1]) {
++ memcpy(&hex[0], puuid, 2);
++ buf[pos++] = strtoul(hex, &endptr, 16);
++ }
++ if (endptr != hex + 2) {
++ ERROR("invalid UUID: %s\n", uuid);
++ exit(1);
++ }
++ puuid += 2;
++ }
++ }
++ buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_END;
++ if (pos != bytes) {
++ ERROR("extra_info legth mismatch\n");
++ exit(1);
++ }
++ *psize = bytes;
++ return buf;
++}
++
++
+ int main(int argc, char *argv[])
+ {
+ struct stat buf, source_buf;
+@@ -8420,6 +8491,20 @@ int main(int argc, char *argv[])
+ } else if(strcmp(argv[i], "-comp") == 0) {
+ /* parsed previously */
+ i++;
++ } else if (strcmp(argv[i], "-label") == 0) {
++ if(++i == argc) {
++ ERROR("%s: -label: missing label\n",
++ argv[0]);
++ exit(1);
++ }
++ volume_label = argv[i];
++ } else if (strcmp(argv[i], "-uuid") == 0) {
++ if(++i == argc) {
++ ERROR("%s: -uuid: missing uuid\n",
++ argv[0]);
++ exit(1);
++ }
++ uuid = argv[i];
+ } else {
+ ERROR("%s: invalid option\n\n", argv[0]);
+ print_options(stderr, argv[0], total_mem);
+@@ -8645,6 +8730,7 @@ int main(int argc, char *argv[])
+ exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
+ no_xattrs = SQUASHFS_NO_XATTRS(sBlk.flags);
+ comp_opts = SQUASHFS_COMP_OPTS(sBlk.flags);
++ extra_info = SQUASHFS_EXTRA_INFO(sBlk.flags);
+ }
+
+ initialise_threads(readq, fragq, bwriteq, fwriteq, !appending,
+@@ -8666,33 +8752,44 @@ int main(int argc, char *argv[])
+ memset(dupl_frag, 0, block_size * sizeof(struct file_info *));
+
+ if(!appending) {
+- int size;
++ int comp_size;
+ void *comp_data = compressor_dump_options(comp, block_size,
+- &size);
++ &comp_size);
++
++ int info_size;
++ void *info_data = info_dump(&info_size);
+
+ if(!quiet)
+ printf("Creating %d.%d filesystem on %s, block size %d.\n",
+ SQUASHFS_MAJOR, SQUASHFS_MINOR,
+ destination_file, block_size);
+
++ bytes = sizeof(struct squashfs_super_block);
+ /*
+ * store any compressor specific options after the superblock,
+ * and set the COMP_OPT flag to show that the filesystem has
+ * compressor specfic options
+ */
+ if(comp_data) {
+- unsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT;
++ unsigned short c_byte = comp_size | SQUASHFS_COMPRESSED_BIT;
+
+ SQUASHFS_INSWAP_SHORTS(&c_byte, 1);
+- write_destination(fd, sizeof(struct squashfs_super_block),
+- sizeof(c_byte), &c_byte);
+- write_destination(fd, sizeof(struct squashfs_super_block) +
+- sizeof(c_byte), size, comp_data);
+- bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte)
+- + size;
++ write_destination(fd, bytes, sizeof(c_byte), &c_byte);
++ bytes += sizeof(c_byte);
++ write_destination(fd, bytes, comp_size, comp_data);
++ bytes += comp_size;
+ comp_opts = TRUE;
+- } else
+- bytes = sizeof(struct squashfs_super_block);
++ }
++ if (info_data) {
++ unsigned short i_byte = info_size | SQUASHFS_COMPRESSED_BIT;
++
++ SQUASHFS_INSWAP_SHORTS(&i_byte, 1);
++ write_destination(fd, bytes, sizeof(i_byte), &i_byte);
++ bytes += sizeof(i_byte);
++ write_destination(fd, bytes, info_size, info_data);
++ bytes += info_size;
++ extra_info = TRUE;
++ }
+ } else {
+ unsigned int last_directory_block, inode_dir_file_size,
+ root_inode_size, inode_dir_start_block,
+@@ -8852,7 +8949,7 @@ int main(int argc, char *argv[])
+ sBlk.block_log = block_log;
+ sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments,
+ always_use_fragments, duplicate_checking, exportable,
+- no_xattrs, comp_opts);
++ no_xattrs, comp_opts, extra_info);
+ sBlk.mkfs_time = mkfs_time_opt ? mkfs_time : time(NULL);
+
+ disable_info();
+diff --git a/squashfs-tools/squashfs_fs.h b/squashfs-tools/squashfs_fs.h
+--- a/squashfs-tools/squashfs_fs.h
++++ b/squashfs-tools/squashfs_fs.h
+@@ -72,6 +72,7 @@
+ #define SQUASHFS_NO_XATTR 9
+ #define SQUASHFS_COMP_OPT 10
+ #define SQUASHFS_NOID 11
++#define SQUASHFS_INFO 12
+
+ #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
+
+@@ -108,12 +109,16 @@
+ #define SQUASHFS_UNCOMPRESSED_IDS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOID)
+
++#define SQUASHFS_EXTRA_INFO(flags) SQUASHFS_BIT(flags, \
++ SQUASHFS_INFO)
++
+ #define SQUASHFS_MKFLAGS(noi, nod, nof, nox, noid, no_frag, always_frag, \
+- duplicate_checking, exportable, no_xattr, comp_opt) (noi | \
++ duplicate_checking, exportable, no_xattr, comp_opt, \
++ extra_info) (noi | \
+ (nod << 1) | (nof << 3) | (no_frag << 4) | \
+ (always_frag << 5) | (duplicate_checking << 6) | \
+ (exportable << 7) | (nox << 8) | (no_xattr << 9) | \
+- (comp_opt << 10) | (noid << 11))
++ (comp_opt << 10) | (noid << 11) | (extra_info << 12))
+
+ /* Max number of types and file types */
+ #define SQUASHFS_DIR_TYPE 1
+@@ -289,6 +294,10 @@ typedef long long squashfs_inode;
+ #define LZ4_COMPRESSION 5
+ #define ZSTD_COMPRESSION 6
+
++#define SQUASHFS_EXTRA_INFO_TAG_END 0
++#define SQUASHFS_EXTRA_INFO_TAG_LABEL 1
++#define SQUASHFS_EXTRA_INFO_TAG_UUID 2
++
+ struct squashfs_super_block {
+ unsigned int s_magic;
+ unsigned int inodes;