Richard W.M. Jones
2021-Jun-16 16:15 UTC
[Libguestfs] [PATCH nbdkit 1/5] floppy: support FAT FSes with unused space.
Nolan, I've added 4 patches at the end with my fixes. It's intended that these be folded into your patch, if you approve them. Rich.
Richard W.M. Jones
2021-Jun-16 16:15 UTC
[Libguestfs] [PATCH nbdkit 1/5] floppy: support FAT FSes with unused space.
From: Nolan Leake <nolan at sigbus.net> This is useful for at least 2 use cases: - Testing support for non-full filesystem - In conjuction with the CoW plugin, for making a writable filesystem. There is also a small bugfix, the partition bootsector didn't account for the 2048 sector offset to the start of the partition when calculating the number of sectors in the partition. Signed-off-by: Nolan Leake <nolan at sigbus.net> --- plugins/floppy/virtual-floppy.h | 2 ++ plugins/floppy/floppy.c | 9 ++++++- plugins/floppy/virtual-floppy.c | 43 +++++++++++++++++++++++++++------ 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/plugins/floppy/virtual-floppy.h b/plugins/floppy/virtual-floppy.h index e5e1e3c9..b3eac24e 100644 --- a/plugins/floppy/virtual-floppy.h +++ b/plugins/floppy/virtual-floppy.h @@ -198,6 +198,7 @@ struct virtual_floppy { uint64_t fat_clusters; /* Size of FAT (clusters on disk). */ uint64_t data_size; /* Size of data region (bytes). */ uint64_t data_clusters; /* Size of data region (clusters). */ + uint64_t data_used_clusters; /* Size of the used part of the data region. */ /* The disk layout: * sector 0: MBR @@ -229,6 +230,7 @@ struct virtual_floppy { extern void init_virtual_floppy (struct virtual_floppy *floppy) __attribute__((__nonnull__ (1))); extern int create_virtual_floppy (const char *dir, const char *label, + uint64_t size, struct virtual_floppy *floppy) __attribute__((__nonnull__ (1, 2, 3))); extern void free_virtual_floppy (struct virtual_floppy *floppy) diff --git a/plugins/floppy/floppy.c b/plugins/floppy/floppy.c index 3f5220b2..24850300 100644 --- a/plugins/floppy/floppy.c +++ b/plugins/floppy/floppy.c @@ -50,6 +50,9 @@ static char *dir = NULL; /* Volume label. */ static const char *label = "NBDKITFLOPY"; +/* Filesystem size. */ +static uint64_t size = 0; + /* Virtual floppy. */ static struct virtual_floppy floppy; @@ -82,6 +85,10 @@ floppy_config (const char *key, const char *value) else if (strcmp (key, "label") == 0) { label = value; } + else if (strcmp (key, "size") == 0) { + if (nbdkit_parse_uint64_t ("size", value, &size) == -1) + return -1; + } else { nbdkit_error ("unknown parameter '%s'", key); return -1; @@ -109,7 +116,7 @@ floppy_config_complete (void) static int floppy_get_ready (void) { - return create_virtual_floppy (dir, label, &floppy); + return create_virtual_floppy (dir, label, size, &floppy); } static void * diff --git a/plugins/floppy/virtual-floppy.c b/plugins/floppy/virtual-floppy.c index 60916fc5..2d5fe72d 100644 --- a/plugins/floppy/virtual-floppy.c +++ b/plugins/floppy/virtual-floppy.c @@ -85,11 +85,12 @@ init_virtual_floppy (struct virtual_floppy *floppy) } int -create_virtual_floppy (const char *dir, const char *label, +create_virtual_floppy (const char *dir, const char *label, uint64_t size, struct virtual_floppy *floppy) { size_t i; uint64_t nr_bytes, nr_clusters; + uint64_t data_used_size; uint32_t cluster; if (visit (dir, floppy) == -1) @@ -112,14 +113,14 @@ create_virtual_floppy (const char *dir, const char *label, * The first cluster number is always 2 (0 and 1 are reserved), and * (in this implementation) always contains the root directory. */ - floppy->data_size = 0; + data_used_size = 0; cluster = 2; for (i = 0; i < floppy->dirs.size; ++i) { floppy->dirs.ptr[i].first_cluster = cluster; nr_bytes ROUND_UP (floppy->dirs.ptr[i].table.size * sizeof (struct dir_entry), CLUSTER_SIZE); - floppy->data_size += nr_bytes; + data_used_size += nr_bytes; nr_clusters = nr_bytes / CLUSTER_SIZE; if (cluster + nr_clusters > UINT32_MAX) goto too_big; @@ -129,7 +130,7 @@ create_virtual_floppy (const char *dir, const char *label, for (i = 0; i < floppy->files.size; ++i) { floppy->files.ptr[i].first_cluster = cluster; nr_bytes = ROUND_UP (floppy->files.ptr[i].statbuf.st_size, CLUSTER_SIZE); - floppy->data_size += nr_bytes; + data_used_size += nr_bytes; nr_clusters = nr_bytes / CLUSTER_SIZE; if (cluster + nr_clusters > UINT32_MAX) goto too_big; @@ -137,7 +138,21 @@ create_virtual_floppy (const char *dir, const char *label, cluster += nr_clusters; } + if (size > 0) { + uint64_t data_size = size - (2080 * SECTOR_SIZE); + data_size = data_size - 2 * DIV_ROUND_UP((data_size / CLUSTER_SIZE + 2) * 4, + CLUSTER_SIZE) * CLUSTER_SIZE; + if (data_used_size > data_size) { + nbdkit_error ("filesystem is larger than \"size\" bytes"); + return -1; + } + floppy->data_size = data_size; + } else { + floppy->data_size = data_used_size; + } + floppy->data_clusters = floppy->data_size / CLUSTER_SIZE; + floppy->data_used_clusters = data_used_size / CLUSTER_SIZE; /* Despite its name, FAT32 only allows 28 bit cluster numbers, so * give an error if we go beyond this. @@ -199,6 +214,10 @@ create_virtual_floppy (const char *dir, const char *label, if (create_regions (floppy) == -1) return -1; + /* Check that if a size was specified, we ended up with it. */ + if (size > 0) + assert (virtual_size (&floppy->regions) == size); + return 0; } @@ -488,7 +507,7 @@ create_partition_boot_sector (const char *label, struct virtual_floppy *floppy) floppy->bootsect.sectors_per_track = htole16 (0); floppy->bootsect.nr_heads = htole16 (0); floppy->bootsect.nr_hidden_sectors = htole32 (0); - floppy->bootsect.nr_sectors = htole32 (floppy->data_last_sector + 1); + floppy->bootsect.nr_sectors = htole32 (floppy->data_last_sector - 2048 + 1); floppy->bootsect.sectors_per_fat htole32 (floppy->fat_clusters * SECTORS_PER_CLUSTER); @@ -524,8 +543,9 @@ create_fsinfo (struct virtual_floppy *floppy) floppy->fsinfo.signature2[1] = 0x72; floppy->fsinfo.signature2[2] = 0x41; floppy->fsinfo.signature2[3] = 0x61; - floppy->fsinfo.free_data_clusters = htole32 (0); - floppy->fsinfo.last_free_cluster = htole32 (2 + floppy->data_clusters); + floppy->fsinfo.free_data_clusters = htole32 (floppy->data_clusters - + floppy->data_used_clusters); + floppy->fsinfo.last_free_cluster = htole32 (2 + floppy->data_used_clusters); floppy->fsinfo.signature3[0] = 0x00; floppy->fsinfo.signature3[1] = 0x00; floppy->fsinfo.signature3[2] = 0x55; @@ -687,6 +707,15 @@ create_regions (struct virtual_floppy *floppy) return -1; } + /* Append region for empty data region if we have extra space. */ + if (floppy->data_used_clusters != floppy->data_clusters) { + uint64_t clusters = (floppy->data_clusters - floppy->data_used_clusters); + if (append_region_len (&floppy->regions, "data padding", + clusters * CLUSTER_SIZE, 0, CLUSTER_SIZE, + region_zero) == -1) + return -1; + } + nbdkit_debug ("floppy: %zu regions, " "total disk size %" PRIi64, nr_regions (&floppy->regions), -- 2.32.0
Richard W.M. Jones
2021-Jun-16 16:15 UTC
[Libguestfs] [PATCH nbdkit 2/5] FIX: Use nbdkit_parse_size to parse the size. (So that size=256M etc works)
--- plugins/floppy/floppy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/floppy/floppy.c b/plugins/floppy/floppy.c index 24850300..80f350af 100644 --- a/plugins/floppy/floppy.c +++ b/plugins/floppy/floppy.c @@ -72,6 +72,8 @@ floppy_unload (void) static int floppy_config (const char *key, const char *value) { + int64_t r; + if (strcmp (key, "dir") == 0) { if (dir != NULL) { /* TODO: Support merging of multiple directories, like iso plugin. */ @@ -86,8 +88,10 @@ floppy_config (const char *key, const char *value) label = value; } else if (strcmp (key, "size") == 0) { - if (nbdkit_parse_uint64_t ("size", value, &size) == -1) + r = nbdkit_parse_size (value); + if (r == -1) return -1; + size = r; } else { nbdkit_error ("unknown parameter '%s'", key); -- 2.32.0
Richard W.M. Jones
2021-Jun-16 16:15 UTC
[Libguestfs] [PATCH nbdkit 3/5] FIX: Add documentation.
--- plugins/floppy/nbdkit-floppy-plugin.pod | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/floppy/nbdkit-floppy-plugin.pod b/plugins/floppy/nbdkit-floppy-plugin.pod index 8e25b1f5..5938ad70 100644 --- a/plugins/floppy/nbdkit-floppy-plugin.pod +++ b/plugins/floppy/nbdkit-floppy-plugin.pod @@ -5,7 +5,7 @@ nbdkit-floppy-plugin - create virtual floppy disk from directory =head1 SYNOPSIS nbdkit floppy [dir=]DIRECTORY - [label=LABEL] + [label=LABEL] [size=SIZE] =head1 DESCRIPTION @@ -55,6 +55,12 @@ See L<nbdkit(1)/Magic parameters>. The optional volume label for the filesystem. This may be up to 11 ASCII characters. If omitted, C<NBDKITFLOPY> is used. +=item B<size=>SIZE + +Optional total disk size. If omitted then the disk will only be large +enough to store all the files and directories from C<DIRECTORY> with +no free space. + =back =head1 LIMITATIONS -- 2.32.0
In file included from floppy.c:45: virtual-floppy.h:235:3: error: ?nonnull? attribute argument 3 value ?3? refers to parameter type ?uint64_t? {aka ?long unsigned int?} [-Werror=attributes] 235 | __attribute__((__nonnull__ (1, 2, 3))); | ^~~~~~~~~~~~~ --- plugins/floppy/virtual-floppy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/floppy/virtual-floppy.h b/plugins/floppy/virtual-floppy.h index b3eac24e..b8c555f8 100644 --- a/plugins/floppy/virtual-floppy.h +++ b/plugins/floppy/virtual-floppy.h @@ -232,7 +232,7 @@ extern void init_virtual_floppy (struct virtual_floppy *floppy) extern int create_virtual_floppy (const char *dir, const char *label, uint64_t size, struct virtual_floppy *floppy) - __attribute__((__nonnull__ (1, 2, 3))); + __attribute__((__nonnull__ (1, 2, 4))); extern void free_virtual_floppy (struct virtual_floppy *floppy) __attribute__((__nonnull__ (1))); extern int create_directory (size_t di, const char *label, -- 2.32.0
Richard W.M. Jones
2021-Jun-16 16:15 UTC
[Libguestfs] [PATCH nbdkit 5/5] FIX: Remove extra parens
--- plugins/floppy/virtual-floppy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/floppy/virtual-floppy.c b/plugins/floppy/virtual-floppy.c index 2d5fe72d..6eae5600 100644 --- a/plugins/floppy/virtual-floppy.c +++ b/plugins/floppy/virtual-floppy.c @@ -709,7 +709,7 @@ create_regions (struct virtual_floppy *floppy) /* Append region for empty data region if we have extra space. */ if (floppy->data_used_clusters != floppy->data_clusters) { - uint64_t clusters = (floppy->data_clusters - floppy->data_used_clusters); + uint64_t clusters = floppy->data_clusters - floppy->data_used_clusters; if (append_region_len (&floppy->regions, "data padding", clusters * CLUSTER_SIZE, 0, CLUSTER_SIZE, region_zero) == -1) -- 2.32.0
Nolan
2021-Jun-16 17:02 UTC
[Libguestfs] [PATCH nbdkit 1/5] floppy: support FAT FSes with unused space.
On 6/16/21 9:15 AM, Richard W.M. Jones wrote:> I've added 4 patches at the end with my fixes. It's intended that > these be folded into your patch, if you approve them.Those all look great. Sorry for forgetting to update the documentation. - nolan