diff --git a/fsck/main.c b/fsck/main.c index aef797e..dda0607 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -123,6 +123,8 @@ void resize_usage() MSG(0, " -i extended node bitmap, node ratio is 20%% by default\n"); MSG(0, " -s safe resize (Does not resize metadata)"); MSG(0, " -t target sectors [default: device size]\n"); + MSG(0, " -O feature1[,feature2,...] e.g. \"fsprojquota,fscasefold\"\n"); + MSG(0, " -C [encoding[:flag1,...]] Support casefolding with optional flags\n"); MSG(0, " -V print the version number and exit\n"); exit(1); } @@ -527,7 +529,9 @@ void f2fs_parse_options(int argc, char *argv[]) #endif } else if (!strcmp("resize.f2fs", prog)) { #ifdef WITH_RESIZE - const char *option_string = "d:fst:iV"; + const char *option_string = "d:fst:O:C:iV"; + int val; + char *token; c.func = RESIZE; while ((option = getopt(argc, argv, option_string)) != EOF) { @@ -561,6 +565,24 @@ void f2fs_parse_options(int argc, char *argv[]) case 'i': c.large_nat_bitmap = 1; break; + case 'O': + if (parse_feature(feature_table, optarg)) + resize_usage(); + break; + case 'C': + token = strtok(optarg, ":"); + val = f2fs_str2encoding(token); + if (val < 0) { + MSG(0, "\tError: Unknown encoding %s\n", token); + } + c.s_encoding = val; + token = strtok(NULL, ""); + val = f2fs_str2encoding_flags(&token, &c.s_encoding_flags); + if (val) { + MSG(0, "\tError: Unknown flag %s\n",token); + } + c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD); + break; case 'V': show_version(prog); exit(0); diff --git a/fsck/mount.c b/fsck/mount.c index 108e123..4aaba61 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -940,6 +940,44 @@ int sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr) return 0; } +static int check_and_set_one_feature(struct f2fs_sb_info *sbi, int feature) +{ + if (c.feature & cpu_to_le32(feature)) { + if (!(sbi->raw_super->feature & cpu_to_le32(feature))) { + sbi->raw_super->feature |= cpu_to_le32(feature); + return 1; + } + } + return 0; +} + +static void check_and_set_features(struct f2fs_sb_info *sbi, enum SB_ADDR sb_addr) +{ + bool need_fix = false; + if (check_and_set_one_feature(sbi, F2FS_FEATURE_EXTRA_ATTR)) { + MSG(0, "Fix set feature: extra_attr\n"); + need_fix = true; + } + + if (check_and_set_one_feature(sbi, F2FS_FEATURE_PRJQUOTA)) { + MSG(0, "Fix set feature: project_quota\n"); + need_fix = true; + } + + if (check_and_set_one_feature(sbi, F2FS_FEATURE_CASEFOLD)) { + struct f2fs_super_block *sb = sbi->raw_super; + set_sb(s_encoding, c.s_encoding); + set_sb(s_encoding_flags, c.s_encoding_flags); + MSG(0, "Fix set feature: casefold, s_encoding: %d, s_encoding_flags: %d\n", + c.s_encoding, c.s_encoding_flags); + need_fix = true; + } + + if (need_fix) { + update_superblock(sbi->raw_super, SB_MASK(sb_addr)); + } +} + #define CHECK_PERIOD (3600 * 24 * 30) // one month by default int validate_super_block(struct f2fs_sb_info *sbi, enum SB_ADDR sb_addr) @@ -957,6 +995,7 @@ int validate_super_block(struct f2fs_sb_info *sbi, enum SB_ADDR sb_addr) sizeof(struct f2fs_super_block)); if (!sanity_check_raw_super(sbi->raw_super, sb_addr)) { + check_and_set_features(sbi, sb_addr); /* get kernel version */ if (c.kd >= 0) { dev_read_version(c.version, 0, VERSION_NAME_LEN);