diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp index acf4d7b25..a8c2cc117 100644 --- a/fs_mgr/fs_mgr_format.cpp +++ b/fs_mgr/fs_mgr_format.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -57,7 +58,7 @@ static int get_dev_sz(const std::string& fs_blkdev, uint64_t* dev_sz) { } static int format_ext4(const std::string& fs_blkdev, const std::string& fs_mnt_point, - bool crypt_footer) { + bool crypt_footer, bool needs_projid) { uint64_t dev_sz; int rc = 0; @@ -72,11 +73,20 @@ static int format_ext4(const std::string& fs_blkdev, const std::string& fs_mnt_p } std::string size_str = std::to_string(dev_sz / 4096); - const char* const mke2fs_args[] = { - "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fs_blkdev.c_str(), - size_str.c_str(), nullptr}; - rc = logwrap_fork_execvp(arraysize(mke2fs_args), mke2fs_args, nullptr, false, LOG_KLOG, true, + std::vector mke2fs_args = {"/system/bin/mke2fs", "-t", "ext4", "-b", "4096"}; + + // Project ID's require wider inodes. The Quotas themselves are enabled by tune2fs during boot. + if (needs_projid) { + mke2fs_args.push_back("-I"); + mke2fs_args.push_back("512"); + } + // casefolding is enabled via tune2fs during boot. + + mke2fs_args.push_back(fs_blkdev.c_str()); + mke2fs_args.push_back(size_str.c_str()); + + rc = logwrap_fork_execvp(mke2fs_args.size(), mke2fs_args.data(), nullptr, false, LOG_KLOG, true, nullptr); if (rc) { LERROR << "mke2fs returned " << rc; @@ -95,7 +105,8 @@ static int format_ext4(const std::string& fs_blkdev, const std::string& fs_mnt_p return rc; } -static int format_f2fs(const std::string& fs_blkdev, uint64_t dev_sz, bool crypt_footer) { +static int format_f2fs(const std::string& fs_blkdev, uint64_t dev_sz, bool crypt_footer, + bool needs_projid, bool needs_casefold) { if (!dev_sz) { int rc = get_dev_sz(fs_blkdev, &dev_sz); if (rc) { @@ -109,26 +120,40 @@ static int format_f2fs(const std::string& fs_blkdev, uint64_t dev_sz, bool crypt } std::string size_str = std::to_string(dev_sz / 4096); - // clang-format off - const char* const args[] = { - "/system/bin/make_f2fs", - "-g", "android", - fs_blkdev.c_str(), - size_str.c_str(), - nullptr - }; - // clang-format on - return logwrap_fork_execvp(arraysize(args), args, nullptr, false, LOG_KLOG, true, nullptr); + std::vector args = {"/system/bin/make_f2fs", "-g", "android"}; + if (needs_projid) { + args.push_back("-O"); + args.push_back("project_quota,extra_attr"); + } + if (needs_casefold) { + args.push_back("-O"); + args.push_back("casefold"); + args.push_back("-C"); + args.push_back("utf8"); + } + args.push_back(fs_blkdev.c_str()); + args.push_back(size_str.c_str()); + + return logwrap_fork_execvp(args.size(), args.data(), nullptr, false, LOG_KLOG, true, nullptr); } int fs_mgr_do_format(const FstabEntry& entry, bool crypt_footer) { LERROR << __FUNCTION__ << ": Format " << entry.blk_device << " as '" << entry.fs_type << "'"; + bool needs_casefold = false; + bool needs_projid = false; + + if (entry.mount_point == "/data") { + needs_casefold = android::base::GetBoolProperty("ro.emulated_storage.casefold", false); + needs_projid = android::base::GetBoolProperty("ro.emulated_storage.projid", false); + } + if (entry.fs_type == "f2fs") { - return format_f2fs(entry.blk_device, entry.length, crypt_footer); + return format_f2fs(entry.blk_device, entry.length, crypt_footer, needs_projid, + needs_casefold); } else if (entry.fs_type == "ext4") { - return format_ext4(entry.blk_device, entry.mount_point, crypt_footer); + return format_ext4(entry.blk_device, entry.mount_point, crypt_footer, needs_projid); } else { LERROR << "File system type '" << entry.fs_type << "' is not supported"; return -EINVAL;