This patch adds validation for all combinations of source mode and
dataimport mode, and prints corresponding error/warning messages.
It should have no impact on external behavior.

Signed-off-by: Yifan Zhao <[email protected]>
---
 mkfs/main.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 131 insertions(+), 13 deletions(-)

diff --git a/mkfs/main.c b/mkfs/main.c
index a948b2e..e369347 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -169,7 +169,7 @@ static void usage(int argc, char **argv)
        }
        printf(
                " -C#                    specify the size of compress physical 
cluster in bytes\n"
-               " -EX[,...]              X=extended options\n"
+               " -EX[,...]              X=extended options, see mkfs.erofs(1) 
manual for details\n"
                " -L volume-label        set the volume label (maximum 15 
bytes)\n"
                " -m#[:X]                enable metadata compression (# = 
physical cluster size in bytes;\n"
                "                                                     X = 
another compression algorithm for metadata)\n"
@@ -300,6 +300,10 @@ static struct ocierofs_config ocicfg;
 static bool mkfs_oci_tarindex_mode;
 
 enum {
+       /* XXX: the "DEFAULT" mode is actually source-dependent,
+        * meaning BLOB_INDEX for rebuild mode and FULLDATA for others.
+        * Consider refactoring this...
+        */
        EROFS_MKFS_DATA_IMPORT_DEFAULT,
        EROFS_MKFS_DATA_IMPORT_FULLDATA,
        EROFS_MKFS_DATA_IMPORT_RVSP,
@@ -314,6 +318,118 @@ static enum {
        EROFS_MKFS_SOURCE_REBUILD,
 } source_mode;
 
+static int erofs_mkfs_validate_source_datamode(void)
+{
+       int status;
+       enum {
+               EROFS_MKFS_CLEAN_MODE = 0,
+               EROFS_MKFS_INCREMENTAL_MODE = 1
+       };
+       const char *SOURCE_NAME[] = {
+               [EROFS_MKFS_SOURCE_LOCALDIR] = "localdir source",
+               [EROFS_MKFS_SOURCE_TAR] = "tarball source",
+               [EROFS_MKFS_SOURCE_S3] = "S3-compatible object store source",
+               [EROFS_MKFS_SOURCE_OCI] = "OCI remote source",
+               [EROFS_MKFS_SOURCE_REBUILD] = "rebuilding from existing EROFS 
image(s)",
+       };
+       const char *DATAIMPORT_NAME[] = {
+               [EROFS_MKFS_DATA_IMPORT_DEFAULT] = "default", // placeholder
+               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = "data",
+               [EROFS_MKFS_DATA_IMPORT_RVSP] = "rvsp",
+               [EROFS_MKFS_DATA_IMPORT_ZEROFILL] = "0",
+       };
+       enum {
+               INVALID = 0, // INVALID must be 0 for static initialization
+               NOP = 1,
+               SUPPORTED = 2,
+       };
+       static const int support[EROFS_MKFS_SOURCE_REBUILD + 
1][EROFS_MKFS_INCREMENTAL_MODE + 1][EROFS_MKFS_DATA_IMPORT_ZEROFILL + 1] = {
+               [EROFS_MKFS_SOURCE_LOCALDIR] = {
+                       [EROFS_MKFS_CLEAN_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_RVSP] = NOP,
+                               [EROFS_MKFS_DATA_IMPORT_ZEROFILL] = NOP
+                       },
+                       [EROFS_MKFS_INCREMENTAL_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_RVSP] = NOP,
+                               [EROFS_MKFS_DATA_IMPORT_ZEROFILL] = NOP
+                       },
+               },
+               [EROFS_MKFS_SOURCE_TAR] = {
+                       [EROFS_MKFS_CLEAN_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_RVSP] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_ZEROFILL] = NOP
+                       },
+                       [EROFS_MKFS_INCREMENTAL_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_RVSP] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_ZEROFILL] = NOP
+                       },
+               },
+               [EROFS_MKFS_SOURCE_S3] = {
+                       [EROFS_MKFS_CLEAN_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_ZEROFILL] = SUPPORTED,
+                       },
+               },
+               [EROFS_MKFS_SOURCE_OCI] = {
+                       [EROFS_MKFS_CLEAN_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED
+                       },
+               },
+               [EROFS_MKFS_SOURCE_REBUILD] = {
+                       [EROFS_MKFS_CLEAN_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_DEFAULT] = SUPPORTED,
+                               /* XXX: FULLDATA rebuild mode doesn't work 
actually, let's keep
+                                * its behavior until v1.9 is released to avoid 
breaking anyone who
+                                * might rely on it...
+                                */
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_RVSP] = SUPPORTED,
+                       },
+                       [EROFS_MKFS_INCREMENTAL_MODE] = {
+                               [EROFS_MKFS_DATA_IMPORT_DEFAULT] = SUPPORTED,
+                               /* XXX: FULLDATA rebuild mode doesn't work 
actually, let's keep
+                                * its behavior until v1.9 is released to avoid 
breaking anyone who
+                                * might rely on it...
+                                */
+                               [EROFS_MKFS_DATA_IMPORT_FULLDATA] = SUPPORTED,
+                               [EROFS_MKFS_DATA_IMPORT_RVSP] = SUPPORTED,
+                       },
+               },
+       };
+       int real_dataimport_mode = dataimport_mode;
+       if (real_dataimport_mode == EROFS_MKFS_DATA_IMPORT_DEFAULT)
+               real_dataimport_mode = (source_mode == 
EROFS_MKFS_SOURCE_REBUILD) ?
+                       EROFS_MKFS_DATA_IMPORT_DEFAULT : 
EROFS_MKFS_DATA_IMPORT_FULLDATA;
+
+       if (source_mode < 0 || source_mode > EROFS_MKFS_SOURCE_REBUILD)
+               return -EINVAL;
+
+       if (real_dataimport_mode < EROFS_MKFS_DATA_IMPORT_DEFAULT ||
+           real_dataimport_mode > EROFS_MKFS_DATA_IMPORT_ZEROFILL)
+               return -EINVAL;
+
+       status = support[source_mode][incremental_mode ? 
EROFS_MKFS_INCREMENTAL_MODE : EROFS_MKFS_CLEAN_MODE][real_dataimport_mode];
+       if (status == SUPPORTED) {
+               return 0;
+       } else if (status == NOP) {
+               erofs_warn("datamode '%s' under %s mode is a no-op for %s.",
+                          DATAIMPORT_NAME[real_dataimport_mode],
+                          incremental_mode ? "incremental" : "clean",
+                          SOURCE_NAME[source_mode]);
+               return 0;
+       } else {
+               erofs_err("datamode '%s' under %s mode is not supported for 
%s.",
+                         DATAIMPORT_NAME[real_dataimport_mode],
+                         incremental_mode ? "incremental" : "clean",
+                         SOURCE_NAME[source_mode]);
+               return -EOPNOTSUPP;
+       }
+}
+
 static unsigned int rebuild_src_count, total_ccfgs;
 static LIST_HEAD(rebuild_src_list);
 static u8 fixeduuid[16];
@@ -1570,6 +1686,10 @@ static int mkfs_parse_options_cfg(struct 
erofs_importer_params *params,
 
        if (has_timestamp && cfg.c_timeinherit == TIMESTAMP_UNSPECIFIED)
                cfg.c_timeinherit = TIMESTAMP_FIXED;
+
+       err = erofs_mkfs_validate_source_datamode();
+       if (err)
+               return err;
        return 0;
 }
 
@@ -1631,11 +1751,16 @@ static int erofs_mkfs_rebuild_load_trees(struct 
erofs_inode *root)
                datamode = EROFS_REBUILD_DATA_BLOB_INDEX;
                break;
        case EROFS_MKFS_DATA_IMPORT_FULLDATA:
+               /* XXX: fulldata rebuild is unsupported, but let's keep this 
behavior
+                * in case anyone relies on it until v1.9 is released...
+                */
                datamode = EROFS_REBUILD_DATA_FULL;
                break;
        case EROFS_MKFS_DATA_IMPORT_RVSP:
                datamode = EROFS_REBUILD_DATA_RESVSP;
                break;
+       case EROFS_MKFS_DATA_IMPORT_ZEROFILL:
+               return -EOPNOTSUPP;
        default:
                return -EINVAL;
        }
@@ -1786,6 +1911,8 @@ int main(int argc, char **argv)
        if (source_mode == EROFS_MKFS_SOURCE_TAR) {
                if (dataimport_mode == EROFS_MKFS_DATA_IMPORT_RVSP)
                        erofstar.rvsp_mode = true;
+               if (erofstar.index_mode && erofstar.rvsp_mode)
+                       erofs_warn("rvsp mode takes precedence and tar index 
mode is ignored");
                erofstar.dev = rebuild_src_count + 1;
 
                if (erofstar.mapfile) {
@@ -1950,12 +2077,8 @@ int main(int argc, char **argv)
                        s3cfg.secret_key[S3_SECRET_KEY_LEN] = '\0';
                }
 
-               if (incremental_mode ||
-                   dataimport_mode == EROFS_MKFS_DATA_IMPORT_RVSP)
-                       err = -EOPNOTSUPP;
-               else
-                       err = s3erofs_build_trees(&importer, &s3cfg,
-                                                 cfg.c_src_path,
+               err = s3erofs_build_trees(&importer, &s3cfg,
+                                         cfg.c_src_path,
                                dataimport_mode == 
EROFS_MKFS_DATA_IMPORT_ZEROFILL);
 #endif
 #ifdef OCIEROFS_ENABLED
@@ -1966,12 +2089,7 @@ int main(int argc, char **argv)
                        if (!ocicfg.zinfo_path)
                                ocicfg.zinfo_path = mkfs_aws_zinfo_file;
 
-                       if (incremental_mode ||
-                           dataimport_mode == EROFS_MKFS_DATA_IMPORT_RVSP ||
-                           dataimport_mode == EROFS_MKFS_DATA_IMPORT_ZEROFILL)
-                               err = -EOPNOTSUPP;
-                       else
-                               err = ocierofs_build_trees(&importer, &ocicfg);
+                       err = ocierofs_build_trees(&importer, &ocicfg);
                        if (err)
                                goto exit;
 #endif
-- 
2.47.3


Reply via email to