Skip to content

Commit

Permalink
Add support for max_version
Browse files Browse the repository at this point in the history
Instead of specifying just the version we now specify the min and max
version, and composefs tries to keep the version as low as possible
but may bump it if needed for newer features. This is necessary as we
now record the version in the image, and we want to avoid
unnecessarily storing a later version in the image, as would change
the digest of images where this is not needed.

We also introduce new macros for the default max version to use in the
tooling, instead of just using the max version. This allows more
careful bumping of the default later.

Signed-off-by: Alexander Larsson <[email protected]>
  • Loading branch information
alexlarsson committed Jan 26, 2024
1 parent 1c00763 commit 8d5b52d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 13 deletions.
32 changes: 31 additions & 1 deletion libcomposefs/lcfs-writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <sys/param.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/sysmacros.h>

static void lcfs_node_remove_all_children(struct lcfs_node_s *node);
static void lcfs_node_destroy(struct lcfs_node_s *node);
Expand Down Expand Up @@ -328,6 +329,27 @@ static int lcfs_close(struct lcfs_ctx_s *ctx)
return 0;
}

static void lcfs_write_update_version(struct lcfs_node_s *node,
struct lcfs_write_options_s *options)
{
/* Version 1 changed how whiteouts are handled */
if (options->version < 1 && options->max_version >= 1) {
int type = node->inode.st_mode & S_IFMT;

if (type == S_IFCHR && node->inode.st_rdev == makedev(0, 0)) {
options->version = 1;
}
}

for (size_t i = 0; i < node->children_size; ++i) {
struct lcfs_node_s *child = node->children[i];
if (child->link_to != NULL) {
continue;
}
lcfs_write_update_version(child, options);
}
}

int lcfs_write_to(struct lcfs_node_s *root, struct lcfs_write_options_s *options)
{
enum lcfs_format_t format = options->format;
Expand All @@ -340,11 +362,19 @@ int lcfs_write_to(struct lcfs_node_s *root, struct lcfs_write_options_s *options
return -1;
}

if (options->version > LCFS_VERSION_MAX) {
if (options->version > LCFS_VERSION_MAX ||
options->max_version > LCFS_VERSION_MAX) {
errno = EINVAL;
return -1;
}

if (options->max_version < options->version) {
options->max_version = options->version;
}

/* Update options->version up to options->max_version if needed */
lcfs_write_update_version(root, options);

ctx = lcfs_new_ctx(root, options);
if (ctx == NULL) {
errno = ENOMEM;
Expand Down
7 changes: 6 additions & 1 deletion libcomposefs/lcfs-writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ enum lcfs_flags_t {
* 1 - Mark xwhitouts using the new opaque=x format as needed by Linux 6.8
*/

/* Default value used by tooling, update with care */
#define LCFS_DEFAULT_VERSION_MIN 0
#define LCFS_DEFAULT_VERSION_MAX 1

typedef ssize_t (*lcfs_read_cb)(void *file, void *buf, size_t count);
typedef ssize_t (*lcfs_write_cb)(void *file, void *buf, size_t count);

Expand All @@ -64,7 +68,8 @@ struct lcfs_write_options_s {
uint8_t *digest_out;
void *file;
lcfs_write_cb file_write_cb;
uint32_t reserved[4];
uint32_t max_version;
uint32_t reserved[3];
void *reserved2[4];
};

Expand Down
2 changes: 1 addition & 1 deletion tests/test-checksums.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ for format in erofs ; do
VERSION_ARG=""
if test -f $ASSET_DIR/$file.version ; then
VERSION="$(cat $ASSET_DIR/$file.version)"
VERSION_ARG="--format-version=$VERSION"
VERSION_ARG="--min-version=$VERSION --max-version=$VERSION"
fi

echo Verifying $file $VERSION_ARG
Expand Down
37 changes: 27 additions & 10 deletions tools/mkcomposefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,9 @@ static void usage(const char *argv0)
" --print-digest Print the digest of the image\n"
" --print-digest-only Print the digest of the image, don't write image\n"
" --from-file The source is a dump file, not a directory\n"
" --format-version=N Use this format version (default=%d)\n",
bin, LCFS_VERSION_MAX);
" --min-version=N Use this minimal format version (default=%d)\n"
" --max-version=N Use this maxium format version (default=%d)\n",
bin, LCFS_DEFAULT_VERSION_MIN, LCFS_DEFAULT_VERSION_MAX);
}

#define OPT_SKIP_XATTRS 102
Expand All @@ -338,7 +339,8 @@ static void usage(const char *argv0)
#define OPT_PRINT_DIGEST_ONLY 111
#define OPT_USER_XATTRS 112
#define OPT_FROM_FILE 113
#define OPT_FORMAT_VERSION 114
#define OPT_MIN_VERSION 114
#define OPT_MAX_VERSION 115

static ssize_t write_cb(void *_file, void *buf, size_t count)
{
Expand Down Expand Up @@ -881,10 +883,16 @@ int main(int argc, char **argv)
val: OPT_FROM_FILE
},
{
name: "format-version",
name: "max-version",
has_arg: required_argument,
flag: NULL,
val: OPT_FORMAT_VERSION
val: OPT_MAX_VERSION
},
{
name: "min-version",
has_arg: required_argument,
flag: NULL,
val: OPT_MIN_VERSION
},
{},
};
Expand All @@ -903,7 +911,8 @@ int main(int argc, char **argv)
int opt;
FILE *out_file;
char *failed_path;
long format_version = LCFS_VERSION_MAX;
long min_version = LCFS_DEFAULT_VERSION_MIN;
long max_version = LCFS_DEFAULT_VERSION_MAX;
char *end;

/* We always compute the digest and reference by digest */
Expand Down Expand Up @@ -935,10 +944,17 @@ int main(int argc, char **argv)
case OPT_FROM_FILE:
from_file = true;
break;
case OPT_FORMAT_VERSION:
format_version = strtol(optarg, &end, 10);
case OPT_MIN_VERSION:
min_version = strtol(optarg, &end, 10);
if (*optarg == 0 || *end != 0) {
fprintf(stderr, "Invalid min version %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case OPT_MAX_VERSION:
max_version = strtol(optarg, &end, 10);
if (*optarg == 0 || *end != 0) {
fprintf(stderr, "Invalid format version %s\n", optarg);
fprintf(stderr, "Invalid max version %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
Expand Down Expand Up @@ -1035,7 +1051,8 @@ int main(int argc, char **argv)
options.digest_out = digest;

options.format = LCFS_FORMAT_EROFS;
options.version = (int)format_version;
options.version = (int)min_version;
options.max_version = (int)max_version;

if (lcfs_write_to(root, &options) < 0)
err(EXIT_FAILURE, "cannot write file");
Expand Down

0 comments on commit 8d5b52d

Please sign in to comment.