15e5c12b0Sopenharmony_ci/**
25e5c12b0Sopenharmony_ci * main.c
35e5c12b0Sopenharmony_ci *
45e5c12b0Sopenharmony_ci * Copyright (c) 2013 Samsung Electronics Co., Ltd.
55e5c12b0Sopenharmony_ci *             http://www.samsung.com/
65e5c12b0Sopenharmony_ci * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org>
75e5c12b0Sopenharmony_ci *  : implement defrag.f2fs
85e5c12b0Sopenharmony_ci * Copyright (C) 2015 Huawei Ltd.
95e5c12b0Sopenharmony_ci *   Hou Pengyang <houpengyang@huawei.com>
105e5c12b0Sopenharmony_ci *   Liu Shuoran <liushuoran@huawei.com>
115e5c12b0Sopenharmony_ci *   Jaegeuk Kim <jaegeuk@kernel.org>
125e5c12b0Sopenharmony_ci *  : add sload.f2fs
135e5c12b0Sopenharmony_ci * Copyright (c) 2019 Google Inc.
145e5c12b0Sopenharmony_ci *   Robin Hsu <robinhsu@google.com>
155e5c12b0Sopenharmony_ci *  : add cache layer
165e5c12b0Sopenharmony_ci * Copyright (c) 2020 Google Inc.
175e5c12b0Sopenharmony_ci *   Robin Hsu <robinhsu@google.com>
185e5c12b0Sopenharmony_ci *  : add sload compression support
195e5c12b0Sopenharmony_ci *
205e5c12b0Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
215e5c12b0Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as
225e5c12b0Sopenharmony_ci * published by the Free Software Foundation.
235e5c12b0Sopenharmony_ci */
245e5c12b0Sopenharmony_ci#include "fsck.h"
255e5c12b0Sopenharmony_ci#include <libgen.h>
265e5c12b0Sopenharmony_ci#include <ctype.h>
275e5c12b0Sopenharmony_ci#include <time.h>
285e5c12b0Sopenharmony_ci#include <getopt.h>
295e5c12b0Sopenharmony_ci#include <stdbool.h>
305e5c12b0Sopenharmony_ci#include "quotaio.h"
315e5c12b0Sopenharmony_ci#include "compress.h"
325e5c12b0Sopenharmony_ci
335e5c12b0Sopenharmony_cistruct f2fs_fsck gfsck;
345e5c12b0Sopenharmony_ci
355e5c12b0Sopenharmony_ciINIT_FEATURE_TABLE;
365e5c12b0Sopenharmony_ci
375e5c12b0Sopenharmony_ci#ifdef WITH_SLOAD
385e5c12b0Sopenharmony_cistatic char *absolute_path(const char *file)
395e5c12b0Sopenharmony_ci{
405e5c12b0Sopenharmony_ci	char *ret;
415e5c12b0Sopenharmony_ci	char cwd[PATH_MAX];
425e5c12b0Sopenharmony_ci
435e5c12b0Sopenharmony_ci	if (file[0] != '/') {
445e5c12b0Sopenharmony_ci		if (getcwd(cwd, PATH_MAX) == NULL) {
455e5c12b0Sopenharmony_ci			fprintf(stderr, "Failed to getcwd\n");
465e5c12b0Sopenharmony_ci			exit(EXIT_FAILURE);
475e5c12b0Sopenharmony_ci		}
485e5c12b0Sopenharmony_ci		ret = malloc(strlen(cwd) + 1 + strlen(file) + 1);
495e5c12b0Sopenharmony_ci		if (ret)
505e5c12b0Sopenharmony_ci			sprintf(ret, "%s/%s", cwd, file);
515e5c12b0Sopenharmony_ci	} else
525e5c12b0Sopenharmony_ci		ret = strdup(file);
535e5c12b0Sopenharmony_ci	return ret;
545e5c12b0Sopenharmony_ci}
555e5c12b0Sopenharmony_ci#endif
565e5c12b0Sopenharmony_ci
575e5c12b0Sopenharmony_civoid fsck_usage()
585e5c12b0Sopenharmony_ci{
595e5c12b0Sopenharmony_ci	MSG(0, "\nUsage: fsck.f2fs [options] device\n");
605e5c12b0Sopenharmony_ci	MSG(0, "[options]:\n");
615e5c12b0Sopenharmony_ci	MSG(0, "  -a check/fix potential corruption, reported by f2fs\n");
625e5c12b0Sopenharmony_ci	MSG(0, "  -c <num-cache-entry>  set number of cache entries"
635e5c12b0Sopenharmony_ci			" (default 0)\n");
645e5c12b0Sopenharmony_ci	MSG(0, "  -m <max-hash-collision>  set max cache hash collision"
655e5c12b0Sopenharmony_ci			" (default 16)\n");
665e5c12b0Sopenharmony_ci	MSG(0, "  -C encoding[:flag1,flag2] Set options for enabling"
675e5c12b0Sopenharmony_ci			" casefolding\n");
685e5c12b0Sopenharmony_ci	MSG(0, "  -d debug level [default:0]\n");
695e5c12b0Sopenharmony_ci	MSG(0, "  -f check/fix entire partition\n");
705e5c12b0Sopenharmony_ci	MSG(0, "  -g add default options\n");
715e5c12b0Sopenharmony_ci	MSG(0, "  -l show superblock/checkpoint\n");
725e5c12b0Sopenharmony_ci	MSG(0, "  -M show a file map\n");
735e5c12b0Sopenharmony_ci	MSG(0, "  -O feature1[feature2,feature3,...] e.g. \"encrypt\"\n");
745e5c12b0Sopenharmony_ci	MSG(0, "  -p preen mode [default:0 the same as -a [0|1|2]]\n");
755e5c12b0Sopenharmony_ci	MSG(0, "  -S sparse_mode\n");
765e5c12b0Sopenharmony_ci	MSG(0, "  -t show directory tree\n");
775e5c12b0Sopenharmony_ci	MSG(0, "  -q preserve quota limits\n");
785e5c12b0Sopenharmony_ci	MSG(0, "  -y fix all the time\n");
795e5c12b0Sopenharmony_ci	MSG(0, "  -V print the version number and exit\n");
805e5c12b0Sopenharmony_ci	MSG(0, "  --dry-run do not really fix corruptions\n");
815e5c12b0Sopenharmony_ci	MSG(0, "  --no-kernel-check skips detecting kernel change\n");
825e5c12b0Sopenharmony_ci	MSG(0, "  --kernel-check checks kernel change\n");
835e5c12b0Sopenharmony_ci	MSG(0, "  --debug-cache to debug cache when -c is used\n");
845e5c12b0Sopenharmony_ci	exit(1);
855e5c12b0Sopenharmony_ci}
865e5c12b0Sopenharmony_ci
875e5c12b0Sopenharmony_civoid dump_usage()
885e5c12b0Sopenharmony_ci{
895e5c12b0Sopenharmony_ci	MSG(0, "\nUsage: dump.f2fs [options] device\n");
905e5c12b0Sopenharmony_ci	MSG(0, "[options]:\n");
915e5c12b0Sopenharmony_ci	MSG(0, "  -d debug level [default:0]\n");
925e5c12b0Sopenharmony_ci	MSG(0, "  -i inode no (hex)\n");
935e5c12b0Sopenharmony_ci	MSG(0, "  -I inode no (hex) scan full disk\n");
945e5c12b0Sopenharmony_ci	MSG(0, "  -n [NAT dump nid from #1~#2 (decimal), for all 0~-1]\n");
955e5c12b0Sopenharmony_ci	MSG(0, "  -M show a block map\n");
965e5c12b0Sopenharmony_ci	MSG(0, "  -s [SIT dump segno from #1~#2 (decimal), for all 0~-1]\n");
975e5c12b0Sopenharmony_ci	MSG(0, "  -S sparse_mode\n");
985e5c12b0Sopenharmony_ci	MSG(0, "  -a [SSA dump segno from #1~#2 (decimal), for all 0~-1]\n");
995e5c12b0Sopenharmony_ci	MSG(0, "  -b blk_addr (in 4KB)\n");
1005e5c12b0Sopenharmony_ci	MSG(0, "  -V print the version number and exit\n");
1015e5c12b0Sopenharmony_ci
1025e5c12b0Sopenharmony_ci	exit(1);
1035e5c12b0Sopenharmony_ci}
1045e5c12b0Sopenharmony_ci
1055e5c12b0Sopenharmony_civoid defrag_usage()
1065e5c12b0Sopenharmony_ci{
1075e5c12b0Sopenharmony_ci	MSG(0, "\nUsage: defrag.f2fs [options] device\n");
1085e5c12b0Sopenharmony_ci	MSG(0, "[options]:\n");
1095e5c12b0Sopenharmony_ci	MSG(0, "  -d debug level [default:0]\n");
1105e5c12b0Sopenharmony_ci	MSG(0, "  -s start block address [default: main_blkaddr]\n");
1115e5c12b0Sopenharmony_ci	MSG(0, "  -S sparse_mode\n");
1125e5c12b0Sopenharmony_ci	MSG(0, "  -l length [default:512 (2MB)]\n");
1135e5c12b0Sopenharmony_ci	MSG(0, "  -t target block address [default: main_blkaddr + 2MB]\n");
1145e5c12b0Sopenharmony_ci	MSG(0, "  -i set direction as shrink [default: expand]\n");
1155e5c12b0Sopenharmony_ci	MSG(0, "  -V print the version number and exit\n");
1165e5c12b0Sopenharmony_ci	exit(1);
1175e5c12b0Sopenharmony_ci}
1185e5c12b0Sopenharmony_ci
1195e5c12b0Sopenharmony_civoid resize_usage()
1205e5c12b0Sopenharmony_ci{
1215e5c12b0Sopenharmony_ci	MSG(0, "\nUsage: resize.f2fs [options] device\n");
1225e5c12b0Sopenharmony_ci	MSG(0, "[options]:\n");
1235e5c12b0Sopenharmony_ci	MSG(0, "  -d debug level [default:0]\n");
1245e5c12b0Sopenharmony_ci	MSG(0, "  -i extended node bitmap, node ratio is 20%% by default\n");
1255e5c12b0Sopenharmony_ci	MSG(0, "  -o overprovision percentage [default:auto]\n");
1265e5c12b0Sopenharmony_ci	MSG(0, "  -s safe resize (Does not resize metadata)\n");
1275e5c12b0Sopenharmony_ci	MSG(0, "  -t target sectors [default: device size]\n");
1285e5c12b0Sopenharmony_ci	MSG(0, "  -O feature1[,feature2,...] e.g. \"fsprojquota,fscasefold\"\n");
1295e5c12b0Sopenharmony_ci	MSG(0, "  -C [encoding[:flag1,...]] Support casefolding with optional flags\n");
1305e5c12b0Sopenharmony_ci	MSG(0, "  -V print the version number and exit\n");
1315e5c12b0Sopenharmony_ci	exit(1);
1325e5c12b0Sopenharmony_ci}
1335e5c12b0Sopenharmony_ci
1345e5c12b0Sopenharmony_civoid sload_usage()
1355e5c12b0Sopenharmony_ci{
1365e5c12b0Sopenharmony_ci	MSG(0, "\nUsage: sload.f2fs [options] device\n");
1375e5c12b0Sopenharmony_ci	MSG(0, "[options]:\n");
1385e5c12b0Sopenharmony_ci	MSG(0, "  -C fs_config\n");
1395e5c12b0Sopenharmony_ci	MSG(0, "  -f source directory [path of the source directory]\n");
1405e5c12b0Sopenharmony_ci	MSG(0, "  -p product out directory\n");
1415e5c12b0Sopenharmony_ci	MSG(0, "  -s file_contexts\n");
1425e5c12b0Sopenharmony_ci	MSG(0, "  -S sparse_mode\n");
1435e5c12b0Sopenharmony_ci	MSG(0, "  -t mount point [prefix of target fs path, default:/]\n");
1445e5c12b0Sopenharmony_ci	MSG(0, "  -T timestamp\n");
1455e5c12b0Sopenharmony_ci	MSG(0, "  -P preserve owner: user and group\n");
1465e5c12b0Sopenharmony_ci	MSG(0, "  -c enable compression (default allow policy)\n");
1475e5c12b0Sopenharmony_ci	MSG(0, "    ------------ Compression sub-options -----------------\n");
1485e5c12b0Sopenharmony_ci	MSG(0, "    -L <log-of-blocks-per-cluster>, default 2\n");
1495e5c12b0Sopenharmony_ci	MSG(0, "    -a <algorithm> compression algorithm, default LZ4\n");
1505e5c12b0Sopenharmony_ci	MSG(0, "    -x <ext> compress files except for these extensions.\n");
1515e5c12b0Sopenharmony_ci	MSG(0, "    -i <ext> compress files with these extensions only.\n");
1525e5c12b0Sopenharmony_ci	MSG(0, "    * -i or -x: use it many times for multiple extensions.\n");
1535e5c12b0Sopenharmony_ci	MSG(0, "    * -i and -x cannot be used together..\n");
1545e5c12b0Sopenharmony_ci	MSG(0, "    -m <num> min compressed blocks per cluster\n");
1555e5c12b0Sopenharmony_ci	MSG(0, "    -r read only (to release unused blocks) for compressed "
1565e5c12b0Sopenharmony_ci			"files\n");
1575e5c12b0Sopenharmony_ci	MSG(0, "    ------------------------------------------------------\n");
1585e5c12b0Sopenharmony_ci	MSG(0, "  -d debug level [default:0]\n");
1595e5c12b0Sopenharmony_ci	MSG(0, "  -V print the version number and exit\n");
1605e5c12b0Sopenharmony_ci	exit(1);
1615e5c12b0Sopenharmony_ci}
1625e5c12b0Sopenharmony_ci
1635e5c12b0Sopenharmony_civoid label_usage()
1645e5c12b0Sopenharmony_ci{
1655e5c12b0Sopenharmony_ci	MSG(0, "\nUsage: f2fslabel [options] device [volume-label]\n");
1665e5c12b0Sopenharmony_ci	MSG(0, "[options]:\n");
1675e5c12b0Sopenharmony_ci	MSG(0, "  -V print the version number and exit\n");
1685e5c12b0Sopenharmony_ci	exit(1);
1695e5c12b0Sopenharmony_ci}
1705e5c12b0Sopenharmony_ci
1715e5c12b0Sopenharmony_cistatic int is_digits(char *optarg)
1725e5c12b0Sopenharmony_ci{
1735e5c12b0Sopenharmony_ci	unsigned int i;
1745e5c12b0Sopenharmony_ci
1755e5c12b0Sopenharmony_ci	for (i = 0; i < strlen(optarg); i++)
1765e5c12b0Sopenharmony_ci		if (!isdigit(optarg[i]))
1775e5c12b0Sopenharmony_ci			break;
1785e5c12b0Sopenharmony_ci	return i == strlen(optarg);
1795e5c12b0Sopenharmony_ci}
1805e5c12b0Sopenharmony_ci
1815e5c12b0Sopenharmony_cistatic void error_out(char *prog)
1825e5c12b0Sopenharmony_ci{
1835e5c12b0Sopenharmony_ci	if (!strcmp("fsck.f2fs", prog))
1845e5c12b0Sopenharmony_ci		fsck_usage();
1855e5c12b0Sopenharmony_ci	else if (!strcmp("dump.f2fs", prog))
1865e5c12b0Sopenharmony_ci		dump_usage();
1875e5c12b0Sopenharmony_ci	else if (!strcmp("defrag.f2fs", prog))
1885e5c12b0Sopenharmony_ci		defrag_usage();
1895e5c12b0Sopenharmony_ci	else if (!strcmp("resize.f2fs", prog))
1905e5c12b0Sopenharmony_ci		resize_usage();
1915e5c12b0Sopenharmony_ci	else if (!strcmp("sload.f2fs", prog))
1925e5c12b0Sopenharmony_ci		sload_usage();
1935e5c12b0Sopenharmony_ci	else if (!strcmp("f2fslabel", prog))
1945e5c12b0Sopenharmony_ci		label_usage();
1955e5c12b0Sopenharmony_ci	else
1965e5c12b0Sopenharmony_ci		MSG(0, "\nWrong program.\n");
1975e5c12b0Sopenharmony_ci}
1985e5c12b0Sopenharmony_ci
1995e5c12b0Sopenharmony_cistatic void __add_fsck_options(void)
2005e5c12b0Sopenharmony_ci{
2015e5c12b0Sopenharmony_ci	/* -a */
2025e5c12b0Sopenharmony_ci	c.auto_fix = 1;
2035e5c12b0Sopenharmony_ci}
2045e5c12b0Sopenharmony_ci
2055e5c12b0Sopenharmony_cistatic void add_default_options(void)
2065e5c12b0Sopenharmony_ci{
2075e5c12b0Sopenharmony_ci	switch (c.defset) {
2085e5c12b0Sopenharmony_ci	case CONF_ANDROID:
2095e5c12b0Sopenharmony_ci		__add_fsck_options();
2105e5c12b0Sopenharmony_ci	}
2115e5c12b0Sopenharmony_ci	c.quota_fix = 1;
2125e5c12b0Sopenharmony_ci}
2135e5c12b0Sopenharmony_ci
2145e5c12b0Sopenharmony_civoid f2fs_parse_options(int argc, char *argv[])
2155e5c12b0Sopenharmony_ci{
2165e5c12b0Sopenharmony_ci	int option = 0;
2175e5c12b0Sopenharmony_ci	char *prog = basename(argv[0]);
2185e5c12b0Sopenharmony_ci	int err = NOERROR;
2195e5c12b0Sopenharmony_ci#ifdef WITH_ANDROID
2205e5c12b0Sopenharmony_ci	int i;
2215e5c12b0Sopenharmony_ci
2225e5c12b0Sopenharmony_ci	/* Allow prog names (e.g, sload_f2fs, fsck_f2fs, etc) */
2235e5c12b0Sopenharmony_ci	for (i = 0; i < strlen(prog); i++) {
2245e5c12b0Sopenharmony_ci		if (prog[i] == '_')
2255e5c12b0Sopenharmony_ci			prog[i] = '.';
2265e5c12b0Sopenharmony_ci	}
2275e5c12b0Sopenharmony_ci#endif
2285e5c12b0Sopenharmony_ci	if (argc < 2) {
2295e5c12b0Sopenharmony_ci		MSG(0, "\tError: Device not specified\n");
2305e5c12b0Sopenharmony_ci		error_out(prog);
2315e5c12b0Sopenharmony_ci	}
2325e5c12b0Sopenharmony_ci
2335e5c12b0Sopenharmony_ci	if (!strcmp("fsck.f2fs", prog)) {
2345e5c12b0Sopenharmony_ci		const char *option_string = ":aC:c:m:Md:fg:lO:p:q:StyV";
2355e5c12b0Sopenharmony_ci		int opt = 0, val;
2365e5c12b0Sopenharmony_ci		char *token;
2375e5c12b0Sopenharmony_ci		struct option long_opt[] = {
2385e5c12b0Sopenharmony_ci			{"dry-run", no_argument, 0, 1},
2395e5c12b0Sopenharmony_ci			{"no-kernel-check", no_argument, 0, 2},
2405e5c12b0Sopenharmony_ci			{"kernel-check", no_argument, 0, 3},
2415e5c12b0Sopenharmony_ci			{"debug-cache", no_argument, 0, 4},
2425e5c12b0Sopenharmony_ci			{0, 0, 0, 0}
2435e5c12b0Sopenharmony_ci		};
2445e5c12b0Sopenharmony_ci
2455e5c12b0Sopenharmony_ci		c.func = FSCK;
2465e5c12b0Sopenharmony_ci		c.cache_config.max_hash_collision = 16;
2475e5c12b0Sopenharmony_ci		c.cache_config.dbg_en = false;
2485e5c12b0Sopenharmony_ci		while ((option = getopt_long(argc, argv, option_string,
2495e5c12b0Sopenharmony_ci						long_opt, &opt)) != EOF) {
2505e5c12b0Sopenharmony_ci			switch (option) {
2515e5c12b0Sopenharmony_ci			case 1:
2525e5c12b0Sopenharmony_ci				c.dry_run = 1;
2535e5c12b0Sopenharmony_ci				MSG(0, "Info: Dry run\n");
2545e5c12b0Sopenharmony_ci				break;
2555e5c12b0Sopenharmony_ci			case 2:
2565e5c12b0Sopenharmony_ci				c.no_kernel_check = 1;
2575e5c12b0Sopenharmony_ci				MSG(0, "Info: No Kernel Check\n");
2585e5c12b0Sopenharmony_ci				break;
2595e5c12b0Sopenharmony_ci			case 3:
2605e5c12b0Sopenharmony_ci				c.no_kernel_check = 0;
2615e5c12b0Sopenharmony_ci				MSG(0, "Info: Do Kernel Check\n");
2625e5c12b0Sopenharmony_ci				break;
2635e5c12b0Sopenharmony_ci			case 4:
2645e5c12b0Sopenharmony_ci				c.cache_config.dbg_en = true;
2655e5c12b0Sopenharmony_ci				break;
2665e5c12b0Sopenharmony_ci			case 'a':
2675e5c12b0Sopenharmony_ci				c.auto_fix = 1;
2685e5c12b0Sopenharmony_ci				MSG(0, "Info: Fix the reported corruption.\n");
2695e5c12b0Sopenharmony_ci				break;
2705e5c12b0Sopenharmony_ci			case 'c':
2715e5c12b0Sopenharmony_ci				c.cache_config.num_cache_entry = atoi(optarg);
2725e5c12b0Sopenharmony_ci				break;
2735e5c12b0Sopenharmony_ci			case 'm':
2745e5c12b0Sopenharmony_ci				c.cache_config.max_hash_collision =
2755e5c12b0Sopenharmony_ci						atoi(optarg);
2765e5c12b0Sopenharmony_ci				break;
2775e5c12b0Sopenharmony_ci			case 'g':
2785e5c12b0Sopenharmony_ci				if (!strcmp(optarg, "android")) {
2795e5c12b0Sopenharmony_ci					c.defset = CONF_ANDROID;
2805e5c12b0Sopenharmony_ci					MSG(0, "Info: Set conf for android\n");
2815e5c12b0Sopenharmony_ci				}
2825e5c12b0Sopenharmony_ci				break;
2835e5c12b0Sopenharmony_ci			case 'l':
2845e5c12b0Sopenharmony_ci				c.layout = 1;
2855e5c12b0Sopenharmony_ci				break;
2865e5c12b0Sopenharmony_ci			case 'M':
2875e5c12b0Sopenharmony_ci				c.show_file_map = 1;
2885e5c12b0Sopenharmony_ci				break;
2895e5c12b0Sopenharmony_ci			case 'O':
2905e5c12b0Sopenharmony_ci				if (parse_feature(feature_table, optarg))
2915e5c12b0Sopenharmony_ci					fsck_usage();
2925e5c12b0Sopenharmony_ci				break;
2935e5c12b0Sopenharmony_ci			case 'p':
2945e5c12b0Sopenharmony_ci				/* preen mode has different levels:
2955e5c12b0Sopenharmony_ci				 *  0: default level, the same as -a
2965e5c12b0Sopenharmony_ci				 *  1: check meta
2975e5c12b0Sopenharmony_ci				 *  2: same as 0, but will skip some
2985e5c12b0Sopenharmony_ci				 *     check for old kernel
2995e5c12b0Sopenharmony_ci				 */
3005e5c12b0Sopenharmony_ci				if (optarg[0] == '-' || !is_digits(optarg) ||
3015e5c12b0Sopenharmony_ci							optind == argc) {
3025e5c12b0Sopenharmony_ci					MSG(0, "Info: Use default preen mode\n");
3035e5c12b0Sopenharmony_ci					c.preen_mode = PREEN_MODE_0;
3045e5c12b0Sopenharmony_ci					c.auto_fix = 1;
3055e5c12b0Sopenharmony_ci					optind--;
3065e5c12b0Sopenharmony_ci					break;
3075e5c12b0Sopenharmony_ci				}
3085e5c12b0Sopenharmony_ci				c.preen_mode = atoi(optarg);
3095e5c12b0Sopenharmony_ci				if (c.preen_mode < 0)
3105e5c12b0Sopenharmony_ci					c.preen_mode = PREEN_MODE_0;
3115e5c12b0Sopenharmony_ci				else if (c.preen_mode >= PREEN_MODE_MAX)
3125e5c12b0Sopenharmony_ci					c.preen_mode = PREEN_MODE_MAX - 1;
3135e5c12b0Sopenharmony_ci				if (c.preen_mode == PREEN_MODE_0 ||
3145e5c12b0Sopenharmony_ci					c.preen_mode == PREEN_MODE_2)
3155e5c12b0Sopenharmony_ci					c.auto_fix = 1;
3165e5c12b0Sopenharmony_ci				MSG(0, "Info: Fix the reported corruption in "
3175e5c12b0Sopenharmony_ci					"preen mode %d\n", c.preen_mode);
3185e5c12b0Sopenharmony_ci				break;
3195e5c12b0Sopenharmony_ci			case 'd':
3205e5c12b0Sopenharmony_ci				if (optarg[0] == '-') {
3215e5c12b0Sopenharmony_ci					err = ENEED_ARG;
3225e5c12b0Sopenharmony_ci					break;
3235e5c12b0Sopenharmony_ci				} else if (!is_digits(optarg)) {
3245e5c12b0Sopenharmony_ci					err = EWRONG_OPT;
3255e5c12b0Sopenharmony_ci					break;
3265e5c12b0Sopenharmony_ci				}
3275e5c12b0Sopenharmony_ci				c.dbg_lv = atoi(optarg);
3285e5c12b0Sopenharmony_ci				MSG(0, "Info: Debug level = %d\n", c.dbg_lv);
3295e5c12b0Sopenharmony_ci				break;
3305e5c12b0Sopenharmony_ci			case 'f':
3315e5c12b0Sopenharmony_ci			case 'y':
3325e5c12b0Sopenharmony_ci				c.fix_on = 1;
3335e5c12b0Sopenharmony_ci				c.force = 1;
3345e5c12b0Sopenharmony_ci				MSG(0, "Info: Force to fix corruption\n");
3355e5c12b0Sopenharmony_ci				break;
3365e5c12b0Sopenharmony_ci			case 'q':
3375e5c12b0Sopenharmony_ci				c.preserve_limits = atoi(optarg);
3385e5c12b0Sopenharmony_ci				MSG(0, "Info: Preserve quota limits = %d\n",
3395e5c12b0Sopenharmony_ci					c.preserve_limits);
3405e5c12b0Sopenharmony_ci				break;
3415e5c12b0Sopenharmony_ci			case 'S':
3425e5c12b0Sopenharmony_ci				c.sparse_mode = 1;
3435e5c12b0Sopenharmony_ci				break;
3445e5c12b0Sopenharmony_ci			case 't':
3455e5c12b0Sopenharmony_ci				c.show_dentry = 1;
3465e5c12b0Sopenharmony_ci				break;
3475e5c12b0Sopenharmony_ci			case ':':
3485e5c12b0Sopenharmony_ci				if (optopt == 'p') {
3495e5c12b0Sopenharmony_ci					MSG(0, "Info: Use default preen mode\n");
3505e5c12b0Sopenharmony_ci					c.preen_mode = PREEN_MODE_0;
3515e5c12b0Sopenharmony_ci					c.auto_fix = 1;
3525e5c12b0Sopenharmony_ci				} else {
3535e5c12b0Sopenharmony_ci					option = optopt;
3545e5c12b0Sopenharmony_ci					err = ENEED_ARG;
3555e5c12b0Sopenharmony_ci					break;
3565e5c12b0Sopenharmony_ci				}
3575e5c12b0Sopenharmony_ci				break;
3585e5c12b0Sopenharmony_ci			case 'C':
3595e5c12b0Sopenharmony_ci				token = strtok(optarg, ":");
3605e5c12b0Sopenharmony_ci				val = f2fs_str2encoding(token);
3615e5c12b0Sopenharmony_ci				if (val < 0) {
3625e5c12b0Sopenharmony_ci					MSG(0, "\tError: Unknown encoding %s\n", token);
3635e5c12b0Sopenharmony_ci					fsck_usage();
3645e5c12b0Sopenharmony_ci				}
3655e5c12b0Sopenharmony_ci				c.s_encoding = val;
3665e5c12b0Sopenharmony_ci				token = strtok(NULL, "");
3675e5c12b0Sopenharmony_ci				val = f2fs_str2encoding_flags(&token, &c.s_encoding_flags);
3685e5c12b0Sopenharmony_ci				if (val) {
3695e5c12b0Sopenharmony_ci					MSG(0, "\tError: Unknown flag %s\n", token);
3705e5c12b0Sopenharmony_ci					fsck_usage();
3715e5c12b0Sopenharmony_ci				}
3725e5c12b0Sopenharmony_ci				c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD);
3735e5c12b0Sopenharmony_ci				break;
3745e5c12b0Sopenharmony_ci			case 'V':
3755e5c12b0Sopenharmony_ci				show_version(prog);
3765e5c12b0Sopenharmony_ci				exit(0);
3775e5c12b0Sopenharmony_ci			case '?':
3785e5c12b0Sopenharmony_ci				option = optopt;
3795e5c12b0Sopenharmony_ci				fallthrough;
3805e5c12b0Sopenharmony_ci			default:
3815e5c12b0Sopenharmony_ci				err = EUNKNOWN_OPT;
3825e5c12b0Sopenharmony_ci				break;
3835e5c12b0Sopenharmony_ci			}
3845e5c12b0Sopenharmony_ci			if (err != NOERROR)
3855e5c12b0Sopenharmony_ci				break;
3865e5c12b0Sopenharmony_ci		}
3875e5c12b0Sopenharmony_ci	} else if (!strcmp("dump.f2fs", prog)) {
3885e5c12b0Sopenharmony_ci#ifdef WITH_DUMP
3895e5c12b0Sopenharmony_ci		const char *option_string = "d:i:I:n:Ms:Sa:b:V";
3905e5c12b0Sopenharmony_ci		static struct dump_option dump_opt = {
3915e5c12b0Sopenharmony_ci			.nid = 0,	/* default root ino */
3925e5c12b0Sopenharmony_ci			.start_nat = -1,
3935e5c12b0Sopenharmony_ci			.end_nat = -1,
3945e5c12b0Sopenharmony_ci			.start_sit = -1,
3955e5c12b0Sopenharmony_ci			.end_sit = -1,
3965e5c12b0Sopenharmony_ci			.start_ssa = -1,
3975e5c12b0Sopenharmony_ci			.end_ssa = -1,
3985e5c12b0Sopenharmony_ci			.blk_addr = -1,
3995e5c12b0Sopenharmony_ci			.scan_nid = 0,
4005e5c12b0Sopenharmony_ci		};
4015e5c12b0Sopenharmony_ci
4025e5c12b0Sopenharmony_ci		c.func = DUMP;
4035e5c12b0Sopenharmony_ci		while ((option = getopt(argc, argv, option_string)) != EOF) {
4045e5c12b0Sopenharmony_ci			int ret = 0;
4055e5c12b0Sopenharmony_ci
4065e5c12b0Sopenharmony_ci			switch (option) {
4075e5c12b0Sopenharmony_ci			case 'd':
4085e5c12b0Sopenharmony_ci				if (!is_digits(optarg)) {
4095e5c12b0Sopenharmony_ci					err = EWRONG_OPT;
4105e5c12b0Sopenharmony_ci					break;
4115e5c12b0Sopenharmony_ci				}
4125e5c12b0Sopenharmony_ci				c.dbg_lv = atoi(optarg);
4135e5c12b0Sopenharmony_ci				MSG(0, "Info: Debug level = %d\n",
4145e5c12b0Sopenharmony_ci							c.dbg_lv);
4155e5c12b0Sopenharmony_ci				break;
4165e5c12b0Sopenharmony_ci			case 'i':
4175e5c12b0Sopenharmony_ci				if (strncmp(optarg, "0x", 2))
4185e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%d",
4195e5c12b0Sopenharmony_ci							&dump_opt.nid);
4205e5c12b0Sopenharmony_ci				else
4215e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%x",
4225e5c12b0Sopenharmony_ci							&dump_opt.nid);
4235e5c12b0Sopenharmony_ci				break;
4245e5c12b0Sopenharmony_ci			case 'I':
4255e5c12b0Sopenharmony_ci				if (strncmp(optarg, "0x", 2))
4265e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%d",
4275e5c12b0Sopenharmony_ci							&dump_opt.scan_nid);
4285e5c12b0Sopenharmony_ci				else
4295e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%x",
4305e5c12b0Sopenharmony_ci							&dump_opt.scan_nid);
4315e5c12b0Sopenharmony_ci				break;
4325e5c12b0Sopenharmony_ci			case 'n':
4335e5c12b0Sopenharmony_ci				ret = sscanf(optarg, "%d~%d",
4345e5c12b0Sopenharmony_ci							&dump_opt.start_nat,
4355e5c12b0Sopenharmony_ci							&dump_opt.end_nat);
4365e5c12b0Sopenharmony_ci				break;
4375e5c12b0Sopenharmony_ci			case 'M':
4385e5c12b0Sopenharmony_ci				c.show_file_map = 1;
4395e5c12b0Sopenharmony_ci				break;
4405e5c12b0Sopenharmony_ci			case 's':
4415e5c12b0Sopenharmony_ci				ret = sscanf(optarg, "%d~%d",
4425e5c12b0Sopenharmony_ci							&dump_opt.start_sit,
4435e5c12b0Sopenharmony_ci							&dump_opt.end_sit);
4445e5c12b0Sopenharmony_ci				break;
4455e5c12b0Sopenharmony_ci			case 'S':
4465e5c12b0Sopenharmony_ci				c.sparse_mode = 1;
4475e5c12b0Sopenharmony_ci				break;
4485e5c12b0Sopenharmony_ci			case 'a':
4495e5c12b0Sopenharmony_ci				ret = sscanf(optarg, "%d~%d",
4505e5c12b0Sopenharmony_ci							&dump_opt.start_ssa,
4515e5c12b0Sopenharmony_ci							&dump_opt.end_ssa);
4525e5c12b0Sopenharmony_ci				break;
4535e5c12b0Sopenharmony_ci			case 'b':
4545e5c12b0Sopenharmony_ci				if (strncmp(optarg, "0x", 2))
4555e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%d",
4565e5c12b0Sopenharmony_ci							&dump_opt.blk_addr);
4575e5c12b0Sopenharmony_ci				else
4585e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%x",
4595e5c12b0Sopenharmony_ci							&dump_opt.blk_addr);
4605e5c12b0Sopenharmony_ci				break;
4615e5c12b0Sopenharmony_ci			case 'V':
4625e5c12b0Sopenharmony_ci				show_version(prog);
4635e5c12b0Sopenharmony_ci				exit(0);
4645e5c12b0Sopenharmony_ci			default:
4655e5c12b0Sopenharmony_ci				err = EUNKNOWN_OPT;
4665e5c12b0Sopenharmony_ci				break;
4675e5c12b0Sopenharmony_ci			}
4685e5c12b0Sopenharmony_ci			ASSERT(ret >= 0);
4695e5c12b0Sopenharmony_ci			if (err != NOERROR)
4705e5c12b0Sopenharmony_ci				break;
4715e5c12b0Sopenharmony_ci		}
4725e5c12b0Sopenharmony_ci
4735e5c12b0Sopenharmony_ci		c.private = &dump_opt;
4745e5c12b0Sopenharmony_ci#endif
4755e5c12b0Sopenharmony_ci	} else if (!strcmp("defrag.f2fs", prog)) {
4765e5c12b0Sopenharmony_ci#ifdef WITH_DEFRAG
4775e5c12b0Sopenharmony_ci		const char *option_string = "d:s:Sl:t:iV";
4785e5c12b0Sopenharmony_ci
4795e5c12b0Sopenharmony_ci		c.func = DEFRAG;
4805e5c12b0Sopenharmony_ci		while ((option = getopt(argc, argv, option_string)) != EOF) {
4815e5c12b0Sopenharmony_ci			int ret = 0;
4825e5c12b0Sopenharmony_ci
4835e5c12b0Sopenharmony_ci			switch (option) {
4845e5c12b0Sopenharmony_ci			case 'd':
4855e5c12b0Sopenharmony_ci				if (!is_digits(optarg)) {
4865e5c12b0Sopenharmony_ci					err = EWRONG_OPT;
4875e5c12b0Sopenharmony_ci					break;
4885e5c12b0Sopenharmony_ci				}
4895e5c12b0Sopenharmony_ci				c.dbg_lv = atoi(optarg);
4905e5c12b0Sopenharmony_ci				MSG(0, "Info: Debug level = %d\n",
4915e5c12b0Sopenharmony_ci							c.dbg_lv);
4925e5c12b0Sopenharmony_ci				break;
4935e5c12b0Sopenharmony_ci			case 's':
4945e5c12b0Sopenharmony_ci				if (strncmp(optarg, "0x", 2))
4955e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIu64"",
4965e5c12b0Sopenharmony_ci							&c.defrag_start);
4975e5c12b0Sopenharmony_ci				else
4985e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIx64"",
4995e5c12b0Sopenharmony_ci							&c.defrag_start);
5005e5c12b0Sopenharmony_ci				break;
5015e5c12b0Sopenharmony_ci			case 'S':
5025e5c12b0Sopenharmony_ci				c.sparse_mode = 1;
5035e5c12b0Sopenharmony_ci				break;
5045e5c12b0Sopenharmony_ci			case 'l':
5055e5c12b0Sopenharmony_ci				if (strncmp(optarg, "0x", 2))
5065e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIu64"",
5075e5c12b0Sopenharmony_ci							&c.defrag_len);
5085e5c12b0Sopenharmony_ci				else
5095e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIx64"",
5105e5c12b0Sopenharmony_ci							&c.defrag_len);
5115e5c12b0Sopenharmony_ci				break;
5125e5c12b0Sopenharmony_ci			case 't':
5135e5c12b0Sopenharmony_ci				if (strncmp(optarg, "0x", 2))
5145e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIu64"",
5155e5c12b0Sopenharmony_ci							&c.defrag_target);
5165e5c12b0Sopenharmony_ci				else
5175e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIx64"",
5185e5c12b0Sopenharmony_ci							&c.defrag_target);
5195e5c12b0Sopenharmony_ci				break;
5205e5c12b0Sopenharmony_ci			case 'i':
5215e5c12b0Sopenharmony_ci				c.defrag_shrink = 1;
5225e5c12b0Sopenharmony_ci				break;
5235e5c12b0Sopenharmony_ci			case 'V':
5245e5c12b0Sopenharmony_ci				show_version(prog);
5255e5c12b0Sopenharmony_ci				exit(0);
5265e5c12b0Sopenharmony_ci			default:
5275e5c12b0Sopenharmony_ci				err = EUNKNOWN_OPT;
5285e5c12b0Sopenharmony_ci				break;
5295e5c12b0Sopenharmony_ci			}
5305e5c12b0Sopenharmony_ci			ASSERT(ret >= 0);
5315e5c12b0Sopenharmony_ci			if (err != NOERROR)
5325e5c12b0Sopenharmony_ci				break;
5335e5c12b0Sopenharmony_ci		}
5345e5c12b0Sopenharmony_ci#endif
5355e5c12b0Sopenharmony_ci	} else if (!strcmp("resize.f2fs", prog)) {
5365e5c12b0Sopenharmony_ci#ifdef WITH_RESIZE
5375e5c12b0Sopenharmony_ci		const char *option_string = "d:fst:O:C:io:V";
5385e5c12b0Sopenharmony_ci		int val;
5395e5c12b0Sopenharmony_ci		char *token;
5405e5c12b0Sopenharmony_ci
5415e5c12b0Sopenharmony_ci		c.func = RESIZE;
5425e5c12b0Sopenharmony_ci		while ((option = getopt(argc, argv, option_string)) != EOF) {
5435e5c12b0Sopenharmony_ci			int ret = 0;
5445e5c12b0Sopenharmony_ci
5455e5c12b0Sopenharmony_ci			switch (option) {
5465e5c12b0Sopenharmony_ci			case 'd':
5475e5c12b0Sopenharmony_ci				if (!is_digits(optarg)) {
5485e5c12b0Sopenharmony_ci					err = EWRONG_OPT;
5495e5c12b0Sopenharmony_ci					break;
5505e5c12b0Sopenharmony_ci				}
5515e5c12b0Sopenharmony_ci				c.dbg_lv = atoi(optarg);
5525e5c12b0Sopenharmony_ci				MSG(0, "Info: Debug level = %d\n",
5535e5c12b0Sopenharmony_ci							c.dbg_lv);
5545e5c12b0Sopenharmony_ci				break;
5555e5c12b0Sopenharmony_ci			case 'f':
5565e5c12b0Sopenharmony_ci				c.force = 1;
5575e5c12b0Sopenharmony_ci				MSG(0, "Info: Force to resize\n");
5585e5c12b0Sopenharmony_ci				break;
5595e5c12b0Sopenharmony_ci			case 's':
5605e5c12b0Sopenharmony_ci				c.safe_resize = 1;
5615e5c12b0Sopenharmony_ci				break;
5625e5c12b0Sopenharmony_ci			case 't':
5635e5c12b0Sopenharmony_ci				if (strncmp(optarg, "0x", 2))
5645e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIu64"",
5655e5c12b0Sopenharmony_ci							&c.target_sectors);
5665e5c12b0Sopenharmony_ci				else
5675e5c12b0Sopenharmony_ci					ret = sscanf(optarg, "%"PRIx64"",
5685e5c12b0Sopenharmony_ci							&c.target_sectors);
5695e5c12b0Sopenharmony_ci				break;
5705e5c12b0Sopenharmony_ci			case 'i':
5715e5c12b0Sopenharmony_ci				c.large_nat_bitmap = 1;
5725e5c12b0Sopenharmony_ci				break;
5735e5c12b0Sopenharmony_ci			case 'O':
5745e5c12b0Sopenharmony_ci				if (parse_feature(feature_table, optarg))
5755e5c12b0Sopenharmony_ci					resize_usage();
5765e5c12b0Sopenharmony_ci				break;
5775e5c12b0Sopenharmony_ci			case 'C':
5785e5c12b0Sopenharmony_ci				token = strtok(optarg, ":");
5795e5c12b0Sopenharmony_ci				val = f2fs_str2encoding(token);
5805e5c12b0Sopenharmony_ci				if (val < 0) {
5815e5c12b0Sopenharmony_ci					MSG(0, "\tError: Unknown encoding %s\n", token);
5825e5c12b0Sopenharmony_ci				}
5835e5c12b0Sopenharmony_ci				c.s_encoding = val;
5845e5c12b0Sopenharmony_ci				token = strtok(NULL, "");
5855e5c12b0Sopenharmony_ci				val = f2fs_str2encoding_flags(&token, &c.s_encoding_flags);
5865e5c12b0Sopenharmony_ci				if (val) {
5875e5c12b0Sopenharmony_ci					MSG(0, "\tError: Unknown flag %s\n",token);
5885e5c12b0Sopenharmony_ci				}
5895e5c12b0Sopenharmony_ci				c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD);
5905e5c12b0Sopenharmony_ci			case 'o':
5915e5c12b0Sopenharmony_ci				c.new_overprovision = atof(optarg);
5925e5c12b0Sopenharmony_ci				break;
5935e5c12b0Sopenharmony_ci			case 'V':
5945e5c12b0Sopenharmony_ci				show_version(prog);
5955e5c12b0Sopenharmony_ci				exit(0);
5965e5c12b0Sopenharmony_ci			default:
5975e5c12b0Sopenharmony_ci				err = EUNKNOWN_OPT;
5985e5c12b0Sopenharmony_ci				break;
5995e5c12b0Sopenharmony_ci			}
6005e5c12b0Sopenharmony_ci			ASSERT(ret >= 0);
6015e5c12b0Sopenharmony_ci			if (err != NOERROR)
6025e5c12b0Sopenharmony_ci				break;
6035e5c12b0Sopenharmony_ci		}
6045e5c12b0Sopenharmony_ci#endif
6055e5c12b0Sopenharmony_ci	} else if (!strcmp("sload.f2fs", prog)) {
6065e5c12b0Sopenharmony_ci#ifdef WITH_SLOAD
6075e5c12b0Sopenharmony_ci		const char *option_string = "cL:a:i:x:m:rC:d:f:p:s:St:T:VP";
6085e5c12b0Sopenharmony_ci#ifdef HAVE_LIBSELINUX
6095e5c12b0Sopenharmony_ci		int max_nr_opt = (int)sizeof(c.seopt_file) /
6105e5c12b0Sopenharmony_ci			sizeof(c.seopt_file[0]);
6115e5c12b0Sopenharmony_ci		char *token;
6125e5c12b0Sopenharmony_ci#endif
6135e5c12b0Sopenharmony_ci		char *p;
6145e5c12b0Sopenharmony_ci
6155e5c12b0Sopenharmony_ci		c.func = SLOAD;
6165e5c12b0Sopenharmony_ci		c.compress.cc.log_cluster_size = 2;
6175e5c12b0Sopenharmony_ci		c.compress.alg = COMPR_LZ4;
6185e5c12b0Sopenharmony_ci		c.compress.min_blocks = 1;
6195e5c12b0Sopenharmony_ci		c.compress.filter_ops = &ext_filter;
6205e5c12b0Sopenharmony_ci		while ((option = getopt(argc, argv, option_string)) != EOF) {
6215e5c12b0Sopenharmony_ci			unsigned int i;
6225e5c12b0Sopenharmony_ci			int val;
6235e5c12b0Sopenharmony_ci
6245e5c12b0Sopenharmony_ci			switch (option) {
6255e5c12b0Sopenharmony_ci			case 'c': /* compression support */
6265e5c12b0Sopenharmony_ci				c.compress.enabled = true;
6275e5c12b0Sopenharmony_ci				break;
6285e5c12b0Sopenharmony_ci			case 'L': /* compression: log of blocks-per-cluster */
6295e5c12b0Sopenharmony_ci				c.compress.required = true;
6305e5c12b0Sopenharmony_ci				val = atoi(optarg);
6315e5c12b0Sopenharmony_ci				if (val < MIN_COMPRESS_LOG_SIZE ||
6325e5c12b0Sopenharmony_ci						val > MAX_COMPRESS_LOG_SIZE) {
6335e5c12b0Sopenharmony_ci					MSG(0, "\tError: log of blocks per"
6345e5c12b0Sopenharmony_ci						" cluster must be in the range"
6355e5c12b0Sopenharmony_ci						" of %d .. %d.\n",
6365e5c12b0Sopenharmony_ci						MIN_COMPRESS_LOG_SIZE,
6375e5c12b0Sopenharmony_ci						MAX_COMPRESS_LOG_SIZE);
6385e5c12b0Sopenharmony_ci					error_out(prog);
6395e5c12b0Sopenharmony_ci				}
6405e5c12b0Sopenharmony_ci				c.compress.cc.log_cluster_size = val;
6415e5c12b0Sopenharmony_ci				break;
6425e5c12b0Sopenharmony_ci			case 'a': /* compression: choose algorithm */
6435e5c12b0Sopenharmony_ci				c.compress.required = true;
6445e5c12b0Sopenharmony_ci				c.compress.alg = MAX_COMPRESS_ALGS;
6455e5c12b0Sopenharmony_ci				for (i = 0; i < MAX_COMPRESS_ALGS; i++) {
6465e5c12b0Sopenharmony_ci					if (!strcmp(supported_comp_names[i],
6475e5c12b0Sopenharmony_ci								optarg)) {
6485e5c12b0Sopenharmony_ci						c.compress.alg = i;
6495e5c12b0Sopenharmony_ci						break;
6505e5c12b0Sopenharmony_ci					}
6515e5c12b0Sopenharmony_ci				}
6525e5c12b0Sopenharmony_ci				if (c.compress.alg == MAX_COMPRESS_ALGS) {
6535e5c12b0Sopenharmony_ci					MSG(0, "\tError: Unknown compression"
6545e5c12b0Sopenharmony_ci						" algorithm %s\n", optarg);
6555e5c12b0Sopenharmony_ci					error_out(prog);
6565e5c12b0Sopenharmony_ci				}
6575e5c12b0Sopenharmony_ci				break;
6585e5c12b0Sopenharmony_ci			case 'i': /* compress only these extensions */
6595e5c12b0Sopenharmony_ci				c.compress.required = true;
6605e5c12b0Sopenharmony_ci				if (c.compress.filter == COMPR_FILTER_ALLOW) {
6615e5c12b0Sopenharmony_ci					MSG(0, "\tError: could not mix option"
6625e5c12b0Sopenharmony_ci							" -i and -x\n");
6635e5c12b0Sopenharmony_ci					error_out(prog);
6645e5c12b0Sopenharmony_ci				}
6655e5c12b0Sopenharmony_ci				c.compress.filter = COMPR_FILTER_DENY;
6665e5c12b0Sopenharmony_ci				c.compress.filter_ops->add(optarg);
6675e5c12b0Sopenharmony_ci				break;
6685e5c12b0Sopenharmony_ci			case 'x': /* compress except for these extensions */
6695e5c12b0Sopenharmony_ci				c.compress.required = true;
6705e5c12b0Sopenharmony_ci				if (c.compress.filter == COMPR_FILTER_DENY) {
6715e5c12b0Sopenharmony_ci					MSG(0, "\tError: could not mix option"
6725e5c12b0Sopenharmony_ci							" -i and -x\n");
6735e5c12b0Sopenharmony_ci					error_out(prog);
6745e5c12b0Sopenharmony_ci				}
6755e5c12b0Sopenharmony_ci				c.compress.filter = COMPR_FILTER_ALLOW;
6765e5c12b0Sopenharmony_ci				c.compress.filter_ops->add(optarg);
6775e5c12b0Sopenharmony_ci				break;
6785e5c12b0Sopenharmony_ci			case 'm': /* minimum compressed blocks per cluster */
6795e5c12b0Sopenharmony_ci				c.compress.required = true;
6805e5c12b0Sopenharmony_ci				val = atoi(optarg);
6815e5c12b0Sopenharmony_ci				if (val <= 0) {
6825e5c12b0Sopenharmony_ci					MSG(0, "\tError: minimum compressed"
6835e5c12b0Sopenharmony_ci						" blocks per cluster must be"
6845e5c12b0Sopenharmony_ci						" positive.\n");
6855e5c12b0Sopenharmony_ci					error_out(prog);
6865e5c12b0Sopenharmony_ci				}
6875e5c12b0Sopenharmony_ci				c.compress.min_blocks = val;
6885e5c12b0Sopenharmony_ci				break;
6895e5c12b0Sopenharmony_ci			case 'r': /* for setting FI_COMPRESS_RELEASED */
6905e5c12b0Sopenharmony_ci				c.compress.required = true;
6915e5c12b0Sopenharmony_ci				c.compress.readonly = true;
6925e5c12b0Sopenharmony_ci				break;
6935e5c12b0Sopenharmony_ci			case 'C':
6945e5c12b0Sopenharmony_ci				c.fs_config_file = absolute_path(optarg);
6955e5c12b0Sopenharmony_ci				break;
6965e5c12b0Sopenharmony_ci			case 'd':
6975e5c12b0Sopenharmony_ci				if (!is_digits(optarg)) {
6985e5c12b0Sopenharmony_ci					err = EWRONG_OPT;
6995e5c12b0Sopenharmony_ci					break;
7005e5c12b0Sopenharmony_ci				}
7015e5c12b0Sopenharmony_ci				c.dbg_lv = atoi(optarg);
7025e5c12b0Sopenharmony_ci				MSG(0, "Info: Debug level = %d\n",
7035e5c12b0Sopenharmony_ci						c.dbg_lv);
7045e5c12b0Sopenharmony_ci				break;
7055e5c12b0Sopenharmony_ci			case 'f':
7065e5c12b0Sopenharmony_ci				c.from_dir = absolute_path(optarg);
7075e5c12b0Sopenharmony_ci				break;
7085e5c12b0Sopenharmony_ci			case 'p':
7095e5c12b0Sopenharmony_ci				c.target_out_dir = absolute_path(optarg);
7105e5c12b0Sopenharmony_ci				break;
7115e5c12b0Sopenharmony_ci			case 's':
7125e5c12b0Sopenharmony_ci#ifdef HAVE_LIBSELINUX
7135e5c12b0Sopenharmony_ci				token = strtok(optarg, ",");
7145e5c12b0Sopenharmony_ci				while (token) {
7155e5c12b0Sopenharmony_ci					if (c.nr_opt == max_nr_opt) {
7165e5c12b0Sopenharmony_ci						MSG(0, "\tError: Expected at most %d selinux opts\n",
7175e5c12b0Sopenharmony_ci										max_nr_opt);
7185e5c12b0Sopenharmony_ci						error_out(prog);
7195e5c12b0Sopenharmony_ci					}
7205e5c12b0Sopenharmony_ci					c.seopt_file[c.nr_opt].type =
7215e5c12b0Sopenharmony_ci								SELABEL_OPT_PATH;
7225e5c12b0Sopenharmony_ci					c.seopt_file[c.nr_opt].value =
7235e5c12b0Sopenharmony_ci								absolute_path(token);
7245e5c12b0Sopenharmony_ci					c.nr_opt++;
7255e5c12b0Sopenharmony_ci					token = strtok(NULL, ",");
7265e5c12b0Sopenharmony_ci				}
7275e5c12b0Sopenharmony_ci#else
7285e5c12b0Sopenharmony_ci				MSG(0, "Info: Not support selinux opts\n");
7295e5c12b0Sopenharmony_ci#endif
7305e5c12b0Sopenharmony_ci				break;
7315e5c12b0Sopenharmony_ci			case 'S':
7325e5c12b0Sopenharmony_ci				c.sparse_mode = 1;
7335e5c12b0Sopenharmony_ci				break;
7345e5c12b0Sopenharmony_ci			case 't':
7355e5c12b0Sopenharmony_ci				c.mount_point = (char *)optarg;
7365e5c12b0Sopenharmony_ci				break;
7375e5c12b0Sopenharmony_ci			case 'T':
7385e5c12b0Sopenharmony_ci				c.fixed_time = strtoul(optarg, &p, 0);
7395e5c12b0Sopenharmony_ci				break;
7405e5c12b0Sopenharmony_ci			case 'V':
7415e5c12b0Sopenharmony_ci				show_version(prog);
7425e5c12b0Sopenharmony_ci				exit(0);
7435e5c12b0Sopenharmony_ci			case 'P':
7445e5c12b0Sopenharmony_ci				c.preserve_perms = 1;
7455e5c12b0Sopenharmony_ci				break;
7465e5c12b0Sopenharmony_ci			default:
7475e5c12b0Sopenharmony_ci				err = EUNKNOWN_OPT;
7485e5c12b0Sopenharmony_ci				break;
7495e5c12b0Sopenharmony_ci			}
7505e5c12b0Sopenharmony_ci			if (err != NOERROR)
7515e5c12b0Sopenharmony_ci				break;
7525e5c12b0Sopenharmony_ci		}
7535e5c12b0Sopenharmony_ci		if (c.compress.required && !c.compress.enabled) {
7545e5c12b0Sopenharmony_ci			MSG(0, "\tError: compression sub-options are used"
7555e5c12b0Sopenharmony_ci				" without the compression enable (-c) option\n"
7565e5c12b0Sopenharmony_ci			);
7575e5c12b0Sopenharmony_ci			error_out(prog);
7585e5c12b0Sopenharmony_ci		}
7595e5c12b0Sopenharmony_ci		if (err == NOERROR && c.compress.enabled) {
7605e5c12b0Sopenharmony_ci			c.compress.cc.cluster_size = 1
7615e5c12b0Sopenharmony_ci				<< c.compress.cc.log_cluster_size;
7625e5c12b0Sopenharmony_ci			if (c.compress.filter == COMPR_FILTER_UNASSIGNED)
7635e5c12b0Sopenharmony_ci				c.compress.filter = COMPR_FILTER_ALLOW;
7645e5c12b0Sopenharmony_ci			if (c.compress.min_blocks >=
7655e5c12b0Sopenharmony_ci					c.compress.cc.cluster_size) {
7665e5c12b0Sopenharmony_ci				MSG(0, "\tError: minimum reduced blocks by"
7675e5c12b0Sopenharmony_ci					" compression per cluster must be at"
7685e5c12b0Sopenharmony_ci					" most one less than blocks per"
7695e5c12b0Sopenharmony_ci					" cluster, i.e. %d\n",
7705e5c12b0Sopenharmony_ci					c.compress.cc.cluster_size - 1);
7715e5c12b0Sopenharmony_ci				error_out(prog);
7725e5c12b0Sopenharmony_ci			}
7735e5c12b0Sopenharmony_ci		}
7745e5c12b0Sopenharmony_ci#endif /* WITH_SLOAD */
7755e5c12b0Sopenharmony_ci	} else if (!strcmp("f2fslabel", prog)) {
7765e5c12b0Sopenharmony_ci#ifdef WITH_LABEL
7775e5c12b0Sopenharmony_ci		const char *option_string = "V";
7785e5c12b0Sopenharmony_ci
7795e5c12b0Sopenharmony_ci		c.func = LABEL;
7805e5c12b0Sopenharmony_ci		while ((option = getopt(argc, argv, option_string)) != EOF) {
7815e5c12b0Sopenharmony_ci			switch (option) {
7825e5c12b0Sopenharmony_ci			case 'V':
7835e5c12b0Sopenharmony_ci				show_version(prog);
7845e5c12b0Sopenharmony_ci				exit(0);
7855e5c12b0Sopenharmony_ci			default:
7865e5c12b0Sopenharmony_ci				err = EUNKNOWN_OPT;
7875e5c12b0Sopenharmony_ci				break;
7885e5c12b0Sopenharmony_ci			}
7895e5c12b0Sopenharmony_ci			if (err != NOERROR)
7905e5c12b0Sopenharmony_ci				break;
7915e5c12b0Sopenharmony_ci		}
7925e5c12b0Sopenharmony_ci
7935e5c12b0Sopenharmony_ci		if (argc > (optind + 2)) { /* unknown argument(s) is(are) passed */
7945e5c12b0Sopenharmony_ci			optind += 2;
7955e5c12b0Sopenharmony_ci			err = EUNKNOWN_ARG;
7965e5c12b0Sopenharmony_ci		} else if (argc == (optind + 2)) { /* change label */
7975e5c12b0Sopenharmony_ci			c.vol_label = argv[optind + 1];
7985e5c12b0Sopenharmony_ci			argc--;
7995e5c12b0Sopenharmony_ci		} else { /* print label */
8005e5c12b0Sopenharmony_ci			/*
8015e5c12b0Sopenharmony_ci			 * Since vol_label was initialized as "", in order to
8025e5c12b0Sopenharmony_ci			 * distinguish between clear label and print, set
8035e5c12b0Sopenharmony_ci			 * vol_label as NULL for print case
8045e5c12b0Sopenharmony_ci			 */
8055e5c12b0Sopenharmony_ci			c.vol_label = NULL;
8065e5c12b0Sopenharmony_ci		}
8075e5c12b0Sopenharmony_ci#endif /* WITH_LABEL */
8085e5c12b0Sopenharmony_ci	}
8095e5c12b0Sopenharmony_ci
8105e5c12b0Sopenharmony_ci	if (err == NOERROR) {
8115e5c12b0Sopenharmony_ci		add_default_options();
8125e5c12b0Sopenharmony_ci
8135e5c12b0Sopenharmony_ci		if (optind >= argc) {
8145e5c12b0Sopenharmony_ci			MSG(0, "\tError: Device not specified\n");
8155e5c12b0Sopenharmony_ci			error_out(prog);
8165e5c12b0Sopenharmony_ci		}
8175e5c12b0Sopenharmony_ci
8185e5c12b0Sopenharmony_ci		c.devices[0].path = strdup(argv[optind]);
8195e5c12b0Sopenharmony_ci		if (argc > (optind + 1)) {
8205e5c12b0Sopenharmony_ci			c.dbg_lv = 0;
8215e5c12b0Sopenharmony_ci			err = EUNKNOWN_ARG;
8225e5c12b0Sopenharmony_ci		}
8235e5c12b0Sopenharmony_ci		if (err == NOERROR)
8245e5c12b0Sopenharmony_ci			return;
8255e5c12b0Sopenharmony_ci	}
8265e5c12b0Sopenharmony_ci
8275e5c12b0Sopenharmony_ci	/* print out error */
8285e5c12b0Sopenharmony_ci	switch (err) {
8295e5c12b0Sopenharmony_ci	case EWRONG_OPT:
8305e5c12b0Sopenharmony_ci		MSG(0, "\tError: Wrong option -%c %s\n", option, optarg);
8315e5c12b0Sopenharmony_ci		break;
8325e5c12b0Sopenharmony_ci	case ENEED_ARG:
8335e5c12b0Sopenharmony_ci		MSG(0, "\tError: Need argument for -%c\n", option);
8345e5c12b0Sopenharmony_ci		break;
8355e5c12b0Sopenharmony_ci	case EUNKNOWN_OPT:
8365e5c12b0Sopenharmony_ci		MSG(0, "\tError: Unknown option %c\n", option);
8375e5c12b0Sopenharmony_ci		break;
8385e5c12b0Sopenharmony_ci	case EUNKNOWN_ARG:
8395e5c12b0Sopenharmony_ci		MSG(0, "\tError: Unknown argument %s\n", argv[optind]);
8405e5c12b0Sopenharmony_ci		break;
8415e5c12b0Sopenharmony_ci	}
8425e5c12b0Sopenharmony_ci	error_out(prog);
8435e5c12b0Sopenharmony_ci}
8445e5c12b0Sopenharmony_ci
8455e5c12b0Sopenharmony_cistatic int do_fsck(struct f2fs_sb_info *sbi)
8465e5c12b0Sopenharmony_ci{
8475e5c12b0Sopenharmony_ci	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
8485e5c12b0Sopenharmony_ci	u32 flag = le32_to_cpu(ckpt->ckpt_flags);
8495e5c12b0Sopenharmony_ci	u32 blk_cnt;
8505e5c12b0Sopenharmony_ci	struct f2fs_compr_blk_cnt cbc;
8515e5c12b0Sopenharmony_ci	errcode_t ret;
8525e5c12b0Sopenharmony_ci
8535e5c12b0Sopenharmony_ci	fsck_init(sbi);
8545e5c12b0Sopenharmony_ci
8555e5c12b0Sopenharmony_ci	print_cp_state(flag);
8565e5c12b0Sopenharmony_ci
8575e5c12b0Sopenharmony_ci	fsck_chk_and_fix_write_pointers(sbi);
8585e5c12b0Sopenharmony_ci
8595e5c12b0Sopenharmony_ci	fsck_chk_curseg_info(sbi);
8605e5c12b0Sopenharmony_ci
8615e5c12b0Sopenharmony_ci	if (!c.fix_on && !c.bug_on) {
8625e5c12b0Sopenharmony_ci		switch (c.preen_mode) {
8635e5c12b0Sopenharmony_ci		case PREEN_MODE_1:
8645e5c12b0Sopenharmony_ci			if (fsck_chk_meta(sbi)) {
8655e5c12b0Sopenharmony_ci				MSG(0, "[FSCK] F2FS metadata   [Fail]");
8665e5c12b0Sopenharmony_ci				MSG(0, "\tError: meta does not match, "
8675e5c12b0Sopenharmony_ci					"force check all\n");
8685e5c12b0Sopenharmony_ci			} else {
8695e5c12b0Sopenharmony_ci				MSG(0, "[FSCK] F2FS metadata   [Ok..]");
8705e5c12b0Sopenharmony_ci				fsck_free(sbi);
8715e5c12b0Sopenharmony_ci				return FSCK_SUCCESS;
8725e5c12b0Sopenharmony_ci			}
8735e5c12b0Sopenharmony_ci
8745e5c12b0Sopenharmony_ci			if (!c.ro)
8755e5c12b0Sopenharmony_ci				c.fix_on = 1;
8765e5c12b0Sopenharmony_ci			break;
8775e5c12b0Sopenharmony_ci		}
8785e5c12b0Sopenharmony_ci	} else if (c.preen_mode) {
8795e5c12b0Sopenharmony_ci		/*
8805e5c12b0Sopenharmony_ci		 * we can hit this in 3 situations:
8815e5c12b0Sopenharmony_ci		 *  1. fsck -f, fix_on has already been set to 1 when
8825e5c12b0Sopenharmony_ci		 *     parsing options;
8835e5c12b0Sopenharmony_ci		 *  2. fsck -a && CP_FSCK_FLAG is set, fix_on has already
8845e5c12b0Sopenharmony_ci		 *     been set to 1 when checking CP_FSCK_FLAG;
8855e5c12b0Sopenharmony_ci		 *  3. fsck -p 1 && error is detected, then bug_on is set,
8865e5c12b0Sopenharmony_ci		 *     we set fix_on = 1 here, so that fsck can fix errors
8875e5c12b0Sopenharmony_ci		 *     automatically
8885e5c12b0Sopenharmony_ci		*/
8895e5c12b0Sopenharmony_ci		c.fix_on = 1;
8905e5c12b0Sopenharmony_ci	}
8915e5c12b0Sopenharmony_ci
8925e5c12b0Sopenharmony_ci	fsck_chk_checkpoint(sbi);
8935e5c12b0Sopenharmony_ci
8945e5c12b0Sopenharmony_ci	fsck_chk_quota_node(sbi);
8955e5c12b0Sopenharmony_ci
8965e5c12b0Sopenharmony_ci	/* Traverse all block recursively from root inode */
8975e5c12b0Sopenharmony_ci	blk_cnt = 1;
8985e5c12b0Sopenharmony_ci	cbc.cnt = 0;
8995e5c12b0Sopenharmony_ci	cbc.cheader_pgofs = CHEADER_PGOFS_NONE;
9005e5c12b0Sopenharmony_ci
9015e5c12b0Sopenharmony_ci	if (c.feature & cpu_to_le32(F2FS_FEATURE_QUOTA_INO)) {
9025e5c12b0Sopenharmony_ci		ret = quota_init_context(sbi);
9035e5c12b0Sopenharmony_ci		if (ret) {
9045e5c12b0Sopenharmony_ci			ASSERT_MSG("quota_init_context failure: %d", ret);
9055e5c12b0Sopenharmony_ci			return FSCK_OPERATIONAL_ERROR;
9065e5c12b0Sopenharmony_ci		}
9075e5c12b0Sopenharmony_ci	}
9085e5c12b0Sopenharmony_ci	fsck_chk_orphan_node(sbi);
9095e5c12b0Sopenharmony_ci	fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num,
9105e5c12b0Sopenharmony_ci			F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, NULL);
9115e5c12b0Sopenharmony_ci	fsck_chk_quota_files(sbi);
9125e5c12b0Sopenharmony_ci
9135e5c12b0Sopenharmony_ci	ret = fsck_verify(sbi);
9145e5c12b0Sopenharmony_ci	fsck_free(sbi);
9155e5c12b0Sopenharmony_ci
9165e5c12b0Sopenharmony_ci	if (!c.bug_on)
9175e5c12b0Sopenharmony_ci		return FSCK_SUCCESS;
9185e5c12b0Sopenharmony_ci	if (!ret)
9195e5c12b0Sopenharmony_ci		return FSCK_ERROR_CORRECTED;
9205e5c12b0Sopenharmony_ci	return FSCK_ERRORS_LEFT_UNCORRECTED;
9215e5c12b0Sopenharmony_ci}
9225e5c12b0Sopenharmony_ci
9235e5c12b0Sopenharmony_ci#ifdef WITH_DUMP
9245e5c12b0Sopenharmony_cistatic void do_dump(struct f2fs_sb_info *sbi)
9255e5c12b0Sopenharmony_ci{
9265e5c12b0Sopenharmony_ci	struct dump_option *opt = (struct dump_option *)c.private;
9275e5c12b0Sopenharmony_ci	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
9285e5c12b0Sopenharmony_ci	u32 flag = le32_to_cpu(ckpt->ckpt_flags);
9295e5c12b0Sopenharmony_ci
9305e5c12b0Sopenharmony_ci	if (opt->end_nat == -1)
9315e5c12b0Sopenharmony_ci		opt->end_nat = NM_I(sbi)->max_nid;
9325e5c12b0Sopenharmony_ci	if (opt->end_sit == -1)
9335e5c12b0Sopenharmony_ci		opt->end_sit = SM_I(sbi)->main_segments;
9345e5c12b0Sopenharmony_ci	if (opt->end_ssa == -1)
9355e5c12b0Sopenharmony_ci		opt->end_ssa = SM_I(sbi)->main_segments;
9365e5c12b0Sopenharmony_ci	if (opt->start_nat != -1)
9375e5c12b0Sopenharmony_ci		nat_dump(sbi, opt->start_nat, opt->end_nat);
9385e5c12b0Sopenharmony_ci	if (opt->start_sit != -1)
9395e5c12b0Sopenharmony_ci		sit_dump(sbi, opt->start_sit, opt->end_sit);
9405e5c12b0Sopenharmony_ci	if (opt->start_ssa != -1)
9415e5c12b0Sopenharmony_ci		ssa_dump(sbi, opt->start_ssa, opt->end_ssa);
9425e5c12b0Sopenharmony_ci	if (opt->blk_addr != -1)
9435e5c12b0Sopenharmony_ci		dump_info_from_blkaddr(sbi, opt->blk_addr);
9445e5c12b0Sopenharmony_ci	if (opt->nid)
9455e5c12b0Sopenharmony_ci		dump_node(sbi, opt->nid, 0);
9465e5c12b0Sopenharmony_ci	if (opt->scan_nid)
9475e5c12b0Sopenharmony_ci		dump_node_scan_disk(sbi, opt->scan_nid);
9485e5c12b0Sopenharmony_ci
9495e5c12b0Sopenharmony_ci	print_cp_state(flag);
9505e5c12b0Sopenharmony_ci
9515e5c12b0Sopenharmony_ci}
9525e5c12b0Sopenharmony_ci#endif
9535e5c12b0Sopenharmony_ci
9545e5c12b0Sopenharmony_ci#ifdef WITH_DEFRAG
9555e5c12b0Sopenharmony_cistatic int do_defrag(struct f2fs_sb_info *sbi)
9565e5c12b0Sopenharmony_ci{
9575e5c12b0Sopenharmony_ci	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
9585e5c12b0Sopenharmony_ci
9595e5c12b0Sopenharmony_ci	if (get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) {
9605e5c12b0Sopenharmony_ci		MSG(0, "Not support on readonly image.\n");
9615e5c12b0Sopenharmony_ci		return -1;
9625e5c12b0Sopenharmony_ci	}
9635e5c12b0Sopenharmony_ci
9645e5c12b0Sopenharmony_ci	if (c.defrag_start > get_sb(block_count))
9655e5c12b0Sopenharmony_ci		goto out_range;
9665e5c12b0Sopenharmony_ci	if (c.defrag_start < SM_I(sbi)->main_blkaddr)
9675e5c12b0Sopenharmony_ci		c.defrag_start = SM_I(sbi)->main_blkaddr;
9685e5c12b0Sopenharmony_ci
9695e5c12b0Sopenharmony_ci	if (c.defrag_len == 0)
9705e5c12b0Sopenharmony_ci		c.defrag_len = sbi->blocks_per_seg;
9715e5c12b0Sopenharmony_ci
9725e5c12b0Sopenharmony_ci	if (c.defrag_start + c.defrag_len > get_sb(block_count))
9735e5c12b0Sopenharmony_ci		c.defrag_len = get_sb(block_count) - c.defrag_start;
9745e5c12b0Sopenharmony_ci
9755e5c12b0Sopenharmony_ci	if (c.defrag_target == 0) {
9765e5c12b0Sopenharmony_ci		c.defrag_target = c.defrag_start - 1;
9775e5c12b0Sopenharmony_ci		if (!c.defrag_shrink)
9785e5c12b0Sopenharmony_ci			c.defrag_target += c.defrag_len + 1;
9795e5c12b0Sopenharmony_ci	}
9805e5c12b0Sopenharmony_ci
9815e5c12b0Sopenharmony_ci	if (c.defrag_target < SM_I(sbi)->main_blkaddr ||
9825e5c12b0Sopenharmony_ci			c.defrag_target > get_sb(block_count))
9835e5c12b0Sopenharmony_ci		goto out_range;
9845e5c12b0Sopenharmony_ci	if (c.defrag_target >= c.defrag_start &&
9855e5c12b0Sopenharmony_ci		c.defrag_target < c.defrag_start + c.defrag_len)
9865e5c12b0Sopenharmony_ci		goto out_range;
9875e5c12b0Sopenharmony_ci
9885e5c12b0Sopenharmony_ci	if (c.defrag_start > c.defrag_target)
9895e5c12b0Sopenharmony_ci		MSG(0, "Info: Move 0x%"PRIx64" <- [0x%"PRIx64"-0x%"PRIx64"]\n",
9905e5c12b0Sopenharmony_ci				c.defrag_target,
9915e5c12b0Sopenharmony_ci				c.defrag_start,
9925e5c12b0Sopenharmony_ci				c.defrag_start + c.defrag_len - 1);
9935e5c12b0Sopenharmony_ci	else
9945e5c12b0Sopenharmony_ci		MSG(0, "Info: Move [0x%"PRIx64"-0x%"PRIx64"] -> 0x%"PRIx64"\n",
9955e5c12b0Sopenharmony_ci				c.defrag_start,
9965e5c12b0Sopenharmony_ci				c.defrag_start + c.defrag_len - 1,
9975e5c12b0Sopenharmony_ci				c.defrag_target);
9985e5c12b0Sopenharmony_ci
9995e5c12b0Sopenharmony_ci	return f2fs_defragment(sbi, c.defrag_start, c.defrag_len,
10005e5c12b0Sopenharmony_ci			c.defrag_target, c.defrag_shrink);
10015e5c12b0Sopenharmony_ciout_range:
10025e5c12b0Sopenharmony_ci	ASSERT_MSG("Out-of-range [0x%"PRIx64" ~ 0x%"PRIx64"] to 0x%"PRIx64"",
10035e5c12b0Sopenharmony_ci				c.defrag_start,
10045e5c12b0Sopenharmony_ci				c.defrag_start + c.defrag_len - 1,
10055e5c12b0Sopenharmony_ci				c.defrag_target);
10065e5c12b0Sopenharmony_ci	return -1;
10075e5c12b0Sopenharmony_ci}
10085e5c12b0Sopenharmony_ci#endif
10095e5c12b0Sopenharmony_ci
10105e5c12b0Sopenharmony_ci#ifdef WITH_RESIZE
10115e5c12b0Sopenharmony_cistatic int do_resize(struct f2fs_sb_info *sbi)
10125e5c12b0Sopenharmony_ci{
10135e5c12b0Sopenharmony_ci	if (!c.target_sectors)
10145e5c12b0Sopenharmony_ci		c.target_sectors = c.total_sectors;
10155e5c12b0Sopenharmony_ci
10165e5c12b0Sopenharmony_ci	if (c.target_sectors > c.total_sectors) {
10175e5c12b0Sopenharmony_ci		ASSERT_MSG("Out-of-range Target=0x%"PRIx64" / 0x%"PRIx64"",
10185e5c12b0Sopenharmony_ci				c.target_sectors, c.total_sectors);
10195e5c12b0Sopenharmony_ci		return -1;
10205e5c12b0Sopenharmony_ci	}
10215e5c12b0Sopenharmony_ci
10225e5c12b0Sopenharmony_ci	return f2fs_resize(sbi);
10235e5c12b0Sopenharmony_ci}
10245e5c12b0Sopenharmony_ci#endif
10255e5c12b0Sopenharmony_ci
10265e5c12b0Sopenharmony_ci#ifdef WITH_SLOAD
10275e5c12b0Sopenharmony_cistatic int init_compr(struct f2fs_sb_info *sbi)
10285e5c12b0Sopenharmony_ci{
10295e5c12b0Sopenharmony_ci	if (!c.compress.enabled)
10305e5c12b0Sopenharmony_ci		return 0;
10315e5c12b0Sopenharmony_ci
10325e5c12b0Sopenharmony_ci	if (!(sbi->raw_super->feature
10335e5c12b0Sopenharmony_ci			& cpu_to_le32(F2FS_FEATURE_COMPRESSION))) {
10345e5c12b0Sopenharmony_ci		MSG(0, "Error: Compression (-c) was requested "
10355e5c12b0Sopenharmony_ci			"but the file system is not created "
10365e5c12b0Sopenharmony_ci			"with such feature.\n");
10375e5c12b0Sopenharmony_ci		return -1;
10385e5c12b0Sopenharmony_ci	}
10395e5c12b0Sopenharmony_ci	if (!supported_comp_ops[c.compress.alg].init) {
10405e5c12b0Sopenharmony_ci		MSG(0, "Error: The selected compression algorithm is not"
10415e5c12b0Sopenharmony_ci				" supported\n");
10425e5c12b0Sopenharmony_ci		return -1;
10435e5c12b0Sopenharmony_ci	}
10445e5c12b0Sopenharmony_ci	c.compress.ops = supported_comp_ops + c.compress.alg;
10455e5c12b0Sopenharmony_ci	c.compress.ops->init(&c.compress.cc);
10465e5c12b0Sopenharmony_ci	c.compress.ops->reset(&c.compress.cc);
10475e5c12b0Sopenharmony_ci	c.compress.cc.rlen = c.compress.cc.cluster_size * F2FS_BLKSIZE;
10485e5c12b0Sopenharmony_ci	return 0;
10495e5c12b0Sopenharmony_ci}
10505e5c12b0Sopenharmony_ci
10515e5c12b0Sopenharmony_cistatic int do_sload(struct f2fs_sb_info *sbi)
10525e5c12b0Sopenharmony_ci{
10535e5c12b0Sopenharmony_ci	if (!c.from_dir) {
10545e5c12b0Sopenharmony_ci		MSG(0, "Info: No source directory, but it's okay.\n");
10555e5c12b0Sopenharmony_ci		return 0;
10565e5c12b0Sopenharmony_ci	}
10575e5c12b0Sopenharmony_ci	if (!c.mount_point)
10585e5c12b0Sopenharmony_ci		c.mount_point = "/";
10595e5c12b0Sopenharmony_ci
10605e5c12b0Sopenharmony_ci	if (init_compr(sbi))
10615e5c12b0Sopenharmony_ci		return -1;
10625e5c12b0Sopenharmony_ci
10635e5c12b0Sopenharmony_ci	return f2fs_sload(sbi);
10645e5c12b0Sopenharmony_ci}
10655e5c12b0Sopenharmony_ci#endif
10665e5c12b0Sopenharmony_ci
10675e5c12b0Sopenharmony_ci#ifdef WITH_LABEL
10685e5c12b0Sopenharmony_cistatic int do_label(struct f2fs_sb_info *sbi)
10695e5c12b0Sopenharmony_ci{
10705e5c12b0Sopenharmony_ci	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
10715e5c12b0Sopenharmony_ci
10725e5c12b0Sopenharmony_ci	if (!c.vol_label) {
10735e5c12b0Sopenharmony_ci		char label[MAX_VOLUME_NAME];
10745e5c12b0Sopenharmony_ci
10755e5c12b0Sopenharmony_ci		utf16_to_utf8(label, sb->volume_name,
10765e5c12b0Sopenharmony_ci			      MAX_VOLUME_NAME, MAX_VOLUME_NAME);
10775e5c12b0Sopenharmony_ci		MSG(0, "Info: volume label = %s\n", label);
10785e5c12b0Sopenharmony_ci		return 0;
10795e5c12b0Sopenharmony_ci	}
10805e5c12b0Sopenharmony_ci
10815e5c12b0Sopenharmony_ci	if (strlen(c.vol_label) > MAX_VOLUME_NAME) {
10825e5c12b0Sopenharmony_ci		ERR_MSG("Label should not exceed %d characters\n", MAX_VOLUME_NAME);
10835e5c12b0Sopenharmony_ci		return -1;
10845e5c12b0Sopenharmony_ci	}
10855e5c12b0Sopenharmony_ci
10865e5c12b0Sopenharmony_ci	utf8_to_utf16(sb->volume_name, (const char *)c.vol_label,
10875e5c12b0Sopenharmony_ci		      MAX_VOLUME_NAME, strlen(c.vol_label));
10885e5c12b0Sopenharmony_ci
10895e5c12b0Sopenharmony_ci	update_superblock(sb, SB_MASK_ALL);
10905e5c12b0Sopenharmony_ci
10915e5c12b0Sopenharmony_ci	MSG(0, "Info: volume label is changed to %s\n", c.vol_label);
10925e5c12b0Sopenharmony_ci
10935e5c12b0Sopenharmony_ci	return 0;
10945e5c12b0Sopenharmony_ci}
10955e5c12b0Sopenharmony_ci#endif
10965e5c12b0Sopenharmony_ci
10975e5c12b0Sopenharmony_ci#ifdef HAVE_MACH_TIME_H
10985e5c12b0Sopenharmony_cistatic u64 get_boottime_ns()
10995e5c12b0Sopenharmony_ci{
11005e5c12b0Sopenharmony_ci	return mach_absolute_time();
11015e5c12b0Sopenharmony_ci}
11025e5c12b0Sopenharmony_ci#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_BOOTTIME)
11035e5c12b0Sopenharmony_cistatic u64 get_boottime_ns()
11045e5c12b0Sopenharmony_ci{
11055e5c12b0Sopenharmony_ci	struct timespec t;
11065e5c12b0Sopenharmony_ci	t.tv_sec = t.tv_nsec = 0;
11075e5c12b0Sopenharmony_ci	clock_gettime(CLOCK_BOOTTIME, &t);
11085e5c12b0Sopenharmony_ci	return (u64)t.tv_sec * 1000000000LL + t.tv_nsec;
11095e5c12b0Sopenharmony_ci}
11105e5c12b0Sopenharmony_ci#else
11115e5c12b0Sopenharmony_cistatic u64 get_boottime_ns()
11125e5c12b0Sopenharmony_ci{
11135e5c12b0Sopenharmony_ci	return 0;
11145e5c12b0Sopenharmony_ci}
11155e5c12b0Sopenharmony_ci#endif
11165e5c12b0Sopenharmony_ci
11175e5c12b0Sopenharmony_ciint main(int argc, char **argv)
11185e5c12b0Sopenharmony_ci{
11195e5c12b0Sopenharmony_ci	struct f2fs_sb_info *sbi;
11205e5c12b0Sopenharmony_ci	int ret = 0, ret2;
11215e5c12b0Sopenharmony_ci	u64 start = get_boottime_ns();
11225e5c12b0Sopenharmony_ci
11235e5c12b0Sopenharmony_ci	f2fs_init_configuration();
11245e5c12b0Sopenharmony_ci
11255e5c12b0Sopenharmony_ci	f2fs_parse_options(argc, argv);
11265e5c12b0Sopenharmony_ci
11275e5c12b0Sopenharmony_ci	if (c.func != DUMP && f2fs_devs_are_umounted() < 0) {
11285e5c12b0Sopenharmony_ci		if (errno == EBUSY) {
11295e5c12b0Sopenharmony_ci			ret = -1;
11305e5c12b0Sopenharmony_ci			if (c.func == FSCK)
11315e5c12b0Sopenharmony_ci				ret = FSCK_OPERATIONAL_ERROR;
11325e5c12b0Sopenharmony_ci			goto quick_err;
11335e5c12b0Sopenharmony_ci		}
11345e5c12b0Sopenharmony_ci		if (!c.ro || c.func == DEFRAG) {
11355e5c12b0Sopenharmony_ci			MSG(0, "\tError: Not available on mounted device!\n");
11365e5c12b0Sopenharmony_ci			ret = -1;
11375e5c12b0Sopenharmony_ci			if (c.func == FSCK)
11385e5c12b0Sopenharmony_ci				ret = FSCK_OPERATIONAL_ERROR;
11395e5c12b0Sopenharmony_ci			goto quick_err;
11405e5c12b0Sopenharmony_ci		}
11415e5c12b0Sopenharmony_ci
11425e5c12b0Sopenharmony_ci		/* allow ro-mounted partition */
11435e5c12b0Sopenharmony_ci		if (c.force) {
11445e5c12b0Sopenharmony_ci			MSG(0, "Info: Force to check/repair FS on RO mounted device\n");
11455e5c12b0Sopenharmony_ci		} else {
11465e5c12b0Sopenharmony_ci			MSG(0, "Info: Check FS only on RO mounted device\n");
11475e5c12b0Sopenharmony_ci			c.fix_on = 0;
11485e5c12b0Sopenharmony_ci			c.auto_fix = 0;
11495e5c12b0Sopenharmony_ci		}
11505e5c12b0Sopenharmony_ci	}
11515e5c12b0Sopenharmony_ci
11525e5c12b0Sopenharmony_ci	/* Get device */
11535e5c12b0Sopenharmony_ci	if (f2fs_get_device_info() < 0 || f2fs_get_f2fs_info() < 0) {
11545e5c12b0Sopenharmony_ci		ret = -1;
11555e5c12b0Sopenharmony_ci		if (c.func == FSCK)
11565e5c12b0Sopenharmony_ci			ret = FSCK_OPERATIONAL_ERROR;
11575e5c12b0Sopenharmony_ci		goto quick_err;
11585e5c12b0Sopenharmony_ci	}
11595e5c12b0Sopenharmony_ci
11605e5c12b0Sopenharmony_cifsck_again:
11615e5c12b0Sopenharmony_ci	memset(&gfsck, 0, sizeof(gfsck));
11625e5c12b0Sopenharmony_ci	gfsck.sbi.fsck = &gfsck;
11635e5c12b0Sopenharmony_ci	sbi = &gfsck.sbi;
11645e5c12b0Sopenharmony_ci
11655e5c12b0Sopenharmony_ci	ret = f2fs_do_mount(sbi);
11665e5c12b0Sopenharmony_ci	if (ret != 0) {
11675e5c12b0Sopenharmony_ci		if (ret == 1) {
11685e5c12b0Sopenharmony_ci			MSG(0, "Info: No error was reported\n");
11695e5c12b0Sopenharmony_ci			ret = 0;
11705e5c12b0Sopenharmony_ci		}
11715e5c12b0Sopenharmony_ci		goto out_err;
11725e5c12b0Sopenharmony_ci	}
11735e5c12b0Sopenharmony_ci
11745e5c12b0Sopenharmony_ci	switch (c.func) {
11755e5c12b0Sopenharmony_ci	case FSCK:
11765e5c12b0Sopenharmony_ci		ret = do_fsck(sbi);
11775e5c12b0Sopenharmony_ci		break;
11785e5c12b0Sopenharmony_ci#ifdef WITH_DUMP
11795e5c12b0Sopenharmony_ci	case DUMP:
11805e5c12b0Sopenharmony_ci		do_dump(sbi);
11815e5c12b0Sopenharmony_ci		break;
11825e5c12b0Sopenharmony_ci#endif
11835e5c12b0Sopenharmony_ci#ifdef WITH_DEFRAG
11845e5c12b0Sopenharmony_ci	case DEFRAG:
11855e5c12b0Sopenharmony_ci		ret = do_defrag(sbi);
11865e5c12b0Sopenharmony_ci		if (ret)
11875e5c12b0Sopenharmony_ci			goto out_err;
11885e5c12b0Sopenharmony_ci		break;
11895e5c12b0Sopenharmony_ci#endif
11905e5c12b0Sopenharmony_ci#ifdef WITH_RESIZE
11915e5c12b0Sopenharmony_ci	case RESIZE:
11925e5c12b0Sopenharmony_ci		if (do_resize(sbi))
11935e5c12b0Sopenharmony_ci			goto out_err;
11945e5c12b0Sopenharmony_ci		break;
11955e5c12b0Sopenharmony_ci#endif
11965e5c12b0Sopenharmony_ci#ifdef WITH_SLOAD
11975e5c12b0Sopenharmony_ci	case SLOAD:
11985e5c12b0Sopenharmony_ci		if (do_sload(sbi))
11995e5c12b0Sopenharmony_ci			goto out_err;
12005e5c12b0Sopenharmony_ci
12015e5c12b0Sopenharmony_ci		ret = f2fs_sparse_initialize_meta(sbi);
12025e5c12b0Sopenharmony_ci		if (ret < 0)
12035e5c12b0Sopenharmony_ci			goto out_err;
12045e5c12b0Sopenharmony_ci
12055e5c12b0Sopenharmony_ci		f2fs_do_umount(sbi);
12065e5c12b0Sopenharmony_ci
12075e5c12b0Sopenharmony_ci		/* fsck to fix missing quota */
12085e5c12b0Sopenharmony_ci		c.func = FSCK;
12095e5c12b0Sopenharmony_ci		c.fix_on = 1;
12105e5c12b0Sopenharmony_ci		goto fsck_again;
12115e5c12b0Sopenharmony_ci#endif
12125e5c12b0Sopenharmony_ci#ifdef WITH_LABEL
12135e5c12b0Sopenharmony_ci	case LABEL:
12145e5c12b0Sopenharmony_ci		if (do_label(sbi))
12155e5c12b0Sopenharmony_ci			goto out_err;
12165e5c12b0Sopenharmony_ci		break;
12175e5c12b0Sopenharmony_ci#endif
12185e5c12b0Sopenharmony_ci	default:
12195e5c12b0Sopenharmony_ci		ERR_MSG("Wrong program name\n");
12205e5c12b0Sopenharmony_ci		ASSERT(0);
12215e5c12b0Sopenharmony_ci	}
12225e5c12b0Sopenharmony_ci
12235e5c12b0Sopenharmony_ci	f2fs_do_umount(sbi);
12245e5c12b0Sopenharmony_ci
12255e5c12b0Sopenharmony_ci	if (c.func == FSCK && c.bug_on) {
12265e5c12b0Sopenharmony_ci		if (!c.ro && c.fix_on == 0 && c.auto_fix == 0 && !c.dry_run) {
12275e5c12b0Sopenharmony_ci			char ans[255] = {0};
12285e5c12b0Sopenharmony_ciretry:
12295e5c12b0Sopenharmony_ci			printf("Do you want to fix this partition? [Y/N] ");
12305e5c12b0Sopenharmony_ci			ret2 = scanf("%s", ans);
12315e5c12b0Sopenharmony_ci			ASSERT(ret2 >= 0);
12325e5c12b0Sopenharmony_ci			if (!strcasecmp(ans, "y"))
12335e5c12b0Sopenharmony_ci				c.fix_on = 1;
12345e5c12b0Sopenharmony_ci			else if (!strcasecmp(ans, "n"))
12355e5c12b0Sopenharmony_ci				c.fix_on = 0;
12365e5c12b0Sopenharmony_ci			else
12375e5c12b0Sopenharmony_ci				goto retry;
12385e5c12b0Sopenharmony_ci
12395e5c12b0Sopenharmony_ci			if (c.fix_on)
12405e5c12b0Sopenharmony_ci				goto fsck_again;
12415e5c12b0Sopenharmony_ci		}
12425e5c12b0Sopenharmony_ci	}
12435e5c12b0Sopenharmony_ci	ret2 = f2fs_finalize_device();
12445e5c12b0Sopenharmony_ci	if (ret2) {
12455e5c12b0Sopenharmony_ci		if (c.func == FSCK)
12465e5c12b0Sopenharmony_ci			return FSCK_OPERATIONAL_ERROR;
12475e5c12b0Sopenharmony_ci		return ret2;
12485e5c12b0Sopenharmony_ci	}
12495e5c12b0Sopenharmony_ci
12505e5c12b0Sopenharmony_ci	if (c.func == SLOAD)
12515e5c12b0Sopenharmony_ci		c.compress.filter_ops->destroy();
12525e5c12b0Sopenharmony_ci
12535e5c12b0Sopenharmony_ci	if (!c.show_file_map)
12545e5c12b0Sopenharmony_ci		printf("\nDone: %lf secs\n", (get_boottime_ns() - start) / 1000000000.0);
12555e5c12b0Sopenharmony_ci	return ret;
12565e5c12b0Sopenharmony_ci
12575e5c12b0Sopenharmony_ciout_err:
12585e5c12b0Sopenharmony_ci	if (sbi->ckpt)
12595e5c12b0Sopenharmony_ci		free(sbi->ckpt);
12605e5c12b0Sopenharmony_ci	if (sbi->raw_super)
12615e5c12b0Sopenharmony_ci		free(sbi->raw_super);
12625e5c12b0Sopenharmony_ciquick_err:
12635e5c12b0Sopenharmony_ci	f2fs_release_sparse_resource();
12645e5c12b0Sopenharmony_ci	return ret;
12655e5c12b0Sopenharmony_ci}
1266