H的erofs已经支持Android,QC/droid 10下生成镜像有如下错误:

failed to find [app] in canned fs_config

code在system/core/libcutils/canned_fs_config.cpp:

void canned_fs_config(const char* path, int dir, const char* target_out_path,
unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities) {
Path key, *p;

key.path = path;
if (path[0] == '/') key.path++; // canned paths lack the leading '/'
p = (Path*) bsearch(&key, canned_data, canned_used, sizeof(Path), path_compare);
if (p == NULL) {
fprintf(stderr, "failed to find [%s] in canned fs_config\n", path); //tj: here
exit(1);
}

canned_datacanned_usedbsearch()无结果。先有个load_canned_fs_config():

#ifdef WITH_ANDROID
if (cfg.fs_config_file &&
load_canned_fs_config(cfg.fs_config_file) < 0) { //tj: here
erofs_err("failed to load fs config %s", cfg.fs_config_file);
return 1;
}
#endif

cfg.fs_config_file是工具传入:

#ifdef WITH_ANDROID
"\nwith following android-specific options:\n"
" --mount-point=X X=prefix of target fs path (default: /)\n"
" --product-out=X X=product_out directory\n"
" --fs-config-file=X X=fs_config file\n" //tj: here
#endif
                case 12:
cfg.fs_config_file = optarg;
break;
#endif

load_canned_fs_config()在system/core/libcutils/canned_fs_config.cpp.

看下传入fs_config文件,product分区:

 0 0 755 selabel=u:object_r:rootfs:s0 capabilities=0x0
product/app 0 0 755 selabel=u:object_r:system_file:s0 capabilities=0x0
product/app/CalculatorGoogle 0 0 755 selabel=u:object_r:system_file:s0 capabilities=0x0

多了个product目录,txt should来源:

ifdef BUILDING_PRODUCT_IMAGE
$(hide) $(call fs_config,$(zip_root)/PRODUCT,product/) > $(zip_root)/META/product_filesystem_config.txt
endif
# Run fs_config while creating the target files package
# $1: root directory
# $2: add prefix
define fs_config
(cd $(1); find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,$(2),' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) -R "$(2)"
endef

so,应该是build时增加了product这个prefix。

看下erofs的处理:

int erofs_droid_inode_fsconfig(struct erofs_inode *inode,
struct stat64 *st,
const char *path)
{
/* filesystem_config does not preserve file type bits */
mode_t stat_file_type_mask = st->st_mode & S_IFMT;
unsigned int uid = 0, gid = 0, mode = 0;
char *fspath;

inode->capabilities = 0;
if (cfg.fs_config_file)
canned_fs_config(erofs_fspath(path), //tj: here
S_ISDIR(st->st_mode),
cfg.target_out_path,
&uid, &gid, &mode, &inode->capabilities);
else if (cfg.mount_point) {
if (asprintf(&fspath, "%s/%s", cfg.mount_point,
erofs_fspath(path)) <= 0)
return -ENOMEM;

fs_config(fspath, S_ISDIR(st->st_mode),
cfg.target_out_path,
&uid, &gid, &mode, &inode->capabilities);
free(fspath);
}
st->st_uid = uid;
st->st_gid = gid;
st->st_mode = mode | stat_file_type_mask;

erofs_dbg("/%s -> mode = 0x%x, uid = 0x%x, gid = 0x%x, "
"capabilities = 0x%" PRIx64 "\n",
erofs_fspath(path),
mode, uid, gid, inode->capabilities);
return 0;
}

check erofs_fspath():

const char *erofs_fspath(const char *fullpath)
{
const char *s = fullpath + fullpath_prefix;

while (*s == '/')
s++;
return s;
}

fullpath_prefix:

static unsigned int fullpath_prefix;    /* root directory prefix length */

void erofs_set_fs_root(const char *rootdir)
{
fullpath_prefix = strlen(rootdir);
}
erofs_set_fs_root(cfg.c_src_path);

so, erofs_fspath()就是子目录了, 而product_filesystem_config.txt是有前缀的(就是挂载点), 那加上前缀就可以了。

具体讨论看这里:https://lore.kernel.org/linux-erofs/20201222020430.12512-1-zbestahu@gmail.com/