18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2007 Oracle.  All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
78c2ecf20Sopenharmony_ci#include <linux/module.h>
88c2ecf20Sopenharmony_ci#include <linux/fs.h>
98c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
108c2ecf20Sopenharmony_ci#include <linux/highmem.h>
118c2ecf20Sopenharmony_ci#include <linux/time.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
148c2ecf20Sopenharmony_ci#include <linux/string.h>
158c2ecf20Sopenharmony_ci#include <linux/backing-dev.h>
168c2ecf20Sopenharmony_ci#include <linux/mount.h>
178c2ecf20Sopenharmony_ci#include <linux/writeback.h>
188c2ecf20Sopenharmony_ci#include <linux/statfs.h>
198c2ecf20Sopenharmony_ci#include <linux/compat.h>
208c2ecf20Sopenharmony_ci#include <linux/parser.h>
218c2ecf20Sopenharmony_ci#include <linux/ctype.h>
228c2ecf20Sopenharmony_ci#include <linux/namei.h>
238c2ecf20Sopenharmony_ci#include <linux/miscdevice.h>
248c2ecf20Sopenharmony_ci#include <linux/magic.h>
258c2ecf20Sopenharmony_ci#include <linux/slab.h>
268c2ecf20Sopenharmony_ci#include <linux/cleancache.h>
278c2ecf20Sopenharmony_ci#include <linux/ratelimit.h>
288c2ecf20Sopenharmony_ci#include <linux/crc32c.h>
298c2ecf20Sopenharmony_ci#include <linux/btrfs.h>
308c2ecf20Sopenharmony_ci#include "delayed-inode.h"
318c2ecf20Sopenharmony_ci#include "ctree.h"
328c2ecf20Sopenharmony_ci#include "disk-io.h"
338c2ecf20Sopenharmony_ci#include "transaction.h"
348c2ecf20Sopenharmony_ci#include "btrfs_inode.h"
358c2ecf20Sopenharmony_ci#include "print-tree.h"
368c2ecf20Sopenharmony_ci#include "props.h"
378c2ecf20Sopenharmony_ci#include "xattr.h"
388c2ecf20Sopenharmony_ci#include "volumes.h"
398c2ecf20Sopenharmony_ci#include "export.h"
408c2ecf20Sopenharmony_ci#include "compression.h"
418c2ecf20Sopenharmony_ci#include "rcu-string.h"
428c2ecf20Sopenharmony_ci#include "dev-replace.h"
438c2ecf20Sopenharmony_ci#include "free-space-cache.h"
448c2ecf20Sopenharmony_ci#include "backref.h"
458c2ecf20Sopenharmony_ci#include "space-info.h"
468c2ecf20Sopenharmony_ci#include "sysfs.h"
478c2ecf20Sopenharmony_ci#include "tests/btrfs-tests.h"
488c2ecf20Sopenharmony_ci#include "block-group.h"
498c2ecf20Sopenharmony_ci#include "discard.h"
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#include "qgroup.h"
528c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS
538c2ecf20Sopenharmony_ci#include <trace/events/btrfs.h>
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic const struct super_operations btrfs_super_ops;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/*
588c2ecf20Sopenharmony_ci * Types for mounting the default subvolume and a subvolume explicitly
598c2ecf20Sopenharmony_ci * requested by subvol=/path. That way the callchain is straightforward and we
608c2ecf20Sopenharmony_ci * don't have to play tricks with the mount options and recursive calls to
618c2ecf20Sopenharmony_ci * btrfs_mount.
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci * The new btrfs_root_fs_type also servers as a tag for the bdev_holder.
648c2ecf20Sopenharmony_ci */
658c2ecf20Sopenharmony_cistatic struct file_system_type btrfs_fs_type;
668c2ecf20Sopenharmony_cistatic struct file_system_type btrfs_root_fs_type;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic int btrfs_remount(struct super_block *sb, int *flags, char *data);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/*
718c2ecf20Sopenharmony_ci * Generally the error codes correspond to their respective errors, but there
728c2ecf20Sopenharmony_ci * are a few special cases.
738c2ecf20Sopenharmony_ci *
748c2ecf20Sopenharmony_ci * EUCLEAN: Any sort of corruption that we encounter.  The tree-checker for
758c2ecf20Sopenharmony_ci *          instance will return EUCLEAN if any of the blocks are corrupted in
768c2ecf20Sopenharmony_ci *          a way that is problematic.  We want to reserve EUCLEAN for these
778c2ecf20Sopenharmony_ci *          sort of corruptions.
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci * EROFS: If we check BTRFS_FS_STATE_ERROR and fail out with a return error, we
808c2ecf20Sopenharmony_ci *        need to use EROFS for this case.  We will have no idea of the
818c2ecf20Sopenharmony_ci *        original failure, that will have been reported at the time we tripped
828c2ecf20Sopenharmony_ci *        over the error.  Each subsequent error that doesn't have any context
838c2ecf20Sopenharmony_ci *        of the original error should use EROFS when handling BTRFS_FS_STATE_ERROR.
848c2ecf20Sopenharmony_ci */
858c2ecf20Sopenharmony_ciconst char * __attribute_const__ btrfs_decode_error(int errno)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	char *errstr = "unknown";
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	switch (errno) {
908c2ecf20Sopenharmony_ci	case -ENOENT:		/* -2 */
918c2ecf20Sopenharmony_ci		errstr = "No such entry";
928c2ecf20Sopenharmony_ci		break;
938c2ecf20Sopenharmony_ci	case -EIO:		/* -5 */
948c2ecf20Sopenharmony_ci		errstr = "IO failure";
958c2ecf20Sopenharmony_ci		break;
968c2ecf20Sopenharmony_ci	case -ENOMEM:		/* -12*/
978c2ecf20Sopenharmony_ci		errstr = "Out of memory";
988c2ecf20Sopenharmony_ci		break;
998c2ecf20Sopenharmony_ci	case -EEXIST:		/* -17 */
1008c2ecf20Sopenharmony_ci		errstr = "Object already exists";
1018c2ecf20Sopenharmony_ci		break;
1028c2ecf20Sopenharmony_ci	case -ENOSPC:		/* -28 */
1038c2ecf20Sopenharmony_ci		errstr = "No space left";
1048c2ecf20Sopenharmony_ci		break;
1058c2ecf20Sopenharmony_ci	case -EROFS:		/* -30 */
1068c2ecf20Sopenharmony_ci		errstr = "Readonly filesystem";
1078c2ecf20Sopenharmony_ci		break;
1088c2ecf20Sopenharmony_ci	case -EOPNOTSUPP:	/* -95 */
1098c2ecf20Sopenharmony_ci		errstr = "Operation not supported";
1108c2ecf20Sopenharmony_ci		break;
1118c2ecf20Sopenharmony_ci	case -EUCLEAN:		/* -117 */
1128c2ecf20Sopenharmony_ci		errstr = "Filesystem corrupted";
1138c2ecf20Sopenharmony_ci		break;
1148c2ecf20Sopenharmony_ci	case -EDQUOT:		/* -122 */
1158c2ecf20Sopenharmony_ci		errstr = "Quota exceeded";
1168c2ecf20Sopenharmony_ci		break;
1178c2ecf20Sopenharmony_ci	}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	return errstr;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci/*
1238c2ecf20Sopenharmony_ci * __btrfs_handle_fs_error decodes expected errors from the caller and
1248c2ecf20Sopenharmony_ci * invokes the appropriate error response.
1258c2ecf20Sopenharmony_ci */
1268c2ecf20Sopenharmony_ci__cold
1278c2ecf20Sopenharmony_civoid __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function,
1288c2ecf20Sopenharmony_ci		       unsigned int line, int errno, const char *fmt, ...)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	struct super_block *sb = fs_info->sb;
1318c2ecf20Sopenharmony_ci#ifdef CONFIG_PRINTK
1328c2ecf20Sopenharmony_ci	const char *errstr;
1338c2ecf20Sopenharmony_ci#endif
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	/*
1368c2ecf20Sopenharmony_ci	 * Special case: if the error is EROFS, and we're already
1378c2ecf20Sopenharmony_ci	 * under SB_RDONLY, then it is safe here.
1388c2ecf20Sopenharmony_ci	 */
1398c2ecf20Sopenharmony_ci	if (errno == -EROFS && sb_rdonly(sb))
1408c2ecf20Sopenharmony_ci  		return;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci#ifdef CONFIG_PRINTK
1438c2ecf20Sopenharmony_ci	errstr = btrfs_decode_error(errno);
1448c2ecf20Sopenharmony_ci	if (fmt) {
1458c2ecf20Sopenharmony_ci		struct va_format vaf;
1468c2ecf20Sopenharmony_ci		va_list args;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci		va_start(args, fmt);
1498c2ecf20Sopenharmony_ci		vaf.fmt = fmt;
1508c2ecf20Sopenharmony_ci		vaf.va = &args;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci		pr_crit("BTRFS: error (device %s) in %s:%d: errno=%d %s (%pV)\n",
1538c2ecf20Sopenharmony_ci			sb->s_id, function, line, errno, errstr, &vaf);
1548c2ecf20Sopenharmony_ci		va_end(args);
1558c2ecf20Sopenharmony_ci	} else {
1568c2ecf20Sopenharmony_ci		pr_crit("BTRFS: error (device %s) in %s:%d: errno=%d %s\n",
1578c2ecf20Sopenharmony_ci			sb->s_id, function, line, errno, errstr);
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci#endif
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	/*
1628c2ecf20Sopenharmony_ci	 * Today we only save the error info to memory.  Long term we'll
1638c2ecf20Sopenharmony_ci	 * also send it down to the disk
1648c2ecf20Sopenharmony_ci	 */
1658c2ecf20Sopenharmony_ci	set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	/* Don't go through full error handling during mount */
1688c2ecf20Sopenharmony_ci	if (!(sb->s_flags & SB_BORN))
1698c2ecf20Sopenharmony_ci		return;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (sb_rdonly(sb))
1728c2ecf20Sopenharmony_ci		return;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	btrfs_discard_stop(fs_info);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	/* btrfs handle error by forcing the filesystem readonly */
1778c2ecf20Sopenharmony_ci	sb->s_flags |= SB_RDONLY;
1788c2ecf20Sopenharmony_ci	btrfs_info(fs_info, "forced readonly");
1798c2ecf20Sopenharmony_ci	/*
1808c2ecf20Sopenharmony_ci	 * Note that a running device replace operation is not canceled here
1818c2ecf20Sopenharmony_ci	 * although there is no way to update the progress. It would add the
1828c2ecf20Sopenharmony_ci	 * risk of a deadlock, therefore the canceling is omitted. The only
1838c2ecf20Sopenharmony_ci	 * penalty is that some I/O remains active until the procedure
1848c2ecf20Sopenharmony_ci	 * completes. The next time when the filesystem is mounted writable
1858c2ecf20Sopenharmony_ci	 * again, the device replace operation continues.
1868c2ecf20Sopenharmony_ci	 */
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci#ifdef CONFIG_PRINTK
1908c2ecf20Sopenharmony_cistatic const char * const logtypes[] = {
1918c2ecf20Sopenharmony_ci	"emergency",
1928c2ecf20Sopenharmony_ci	"alert",
1938c2ecf20Sopenharmony_ci	"critical",
1948c2ecf20Sopenharmony_ci	"error",
1958c2ecf20Sopenharmony_ci	"warning",
1968c2ecf20Sopenharmony_ci	"notice",
1978c2ecf20Sopenharmony_ci	"info",
1988c2ecf20Sopenharmony_ci	"debug",
1998c2ecf20Sopenharmony_ci};
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci/*
2038c2ecf20Sopenharmony_ci * Use one ratelimit state per log level so that a flood of less important
2048c2ecf20Sopenharmony_ci * messages doesn't cause more important ones to be dropped.
2058c2ecf20Sopenharmony_ci */
2068c2ecf20Sopenharmony_cistatic struct ratelimit_state printk_limits[] = {
2078c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[0], DEFAULT_RATELIMIT_INTERVAL, 100),
2088c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[1], DEFAULT_RATELIMIT_INTERVAL, 100),
2098c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[2], DEFAULT_RATELIMIT_INTERVAL, 100),
2108c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[3], DEFAULT_RATELIMIT_INTERVAL, 100),
2118c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[4], DEFAULT_RATELIMIT_INTERVAL, 100),
2128c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[5], DEFAULT_RATELIMIT_INTERVAL, 100),
2138c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[6], DEFAULT_RATELIMIT_INTERVAL, 100),
2148c2ecf20Sopenharmony_ci	RATELIMIT_STATE_INIT(printk_limits[7], DEFAULT_RATELIMIT_INTERVAL, 100),
2158c2ecf20Sopenharmony_ci};
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_civoid __cold btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	char lvl[PRINTK_MAX_SINGLE_HEADER_LEN + 1] = "\0";
2208c2ecf20Sopenharmony_ci	struct va_format vaf;
2218c2ecf20Sopenharmony_ci	va_list args;
2228c2ecf20Sopenharmony_ci	int kern_level;
2238c2ecf20Sopenharmony_ci	const char *type = logtypes[4];
2248c2ecf20Sopenharmony_ci	struct ratelimit_state *ratelimit = &printk_limits[4];
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	va_start(args, fmt);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	while ((kern_level = printk_get_level(fmt)) != 0) {
2298c2ecf20Sopenharmony_ci		size_t size = printk_skip_level(fmt) - fmt;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci		if (kern_level >= '0' && kern_level <= '7') {
2328c2ecf20Sopenharmony_ci			memcpy(lvl, fmt,  size);
2338c2ecf20Sopenharmony_ci			lvl[size] = '\0';
2348c2ecf20Sopenharmony_ci			type = logtypes[kern_level - '0'];
2358c2ecf20Sopenharmony_ci			ratelimit = &printk_limits[kern_level - '0'];
2368c2ecf20Sopenharmony_ci		}
2378c2ecf20Sopenharmony_ci		fmt += size;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	vaf.fmt = fmt;
2418c2ecf20Sopenharmony_ci	vaf.va = &args;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	if (__ratelimit(ratelimit))
2448c2ecf20Sopenharmony_ci		printk("%sBTRFS %s (device %s): %pV\n", lvl, type,
2458c2ecf20Sopenharmony_ci			fs_info ? fs_info->sb->s_id : "<unknown>", &vaf);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	va_end(args);
2488c2ecf20Sopenharmony_ci}
2498c2ecf20Sopenharmony_ci#endif
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci/*
2528c2ecf20Sopenharmony_ci * We only mark the transaction aborted and then set the file system read-only.
2538c2ecf20Sopenharmony_ci * This will prevent new transactions from starting or trying to join this
2548c2ecf20Sopenharmony_ci * one.
2558c2ecf20Sopenharmony_ci *
2568c2ecf20Sopenharmony_ci * This means that error recovery at the call site is limited to freeing
2578c2ecf20Sopenharmony_ci * any local memory allocations and passing the error code up without
2588c2ecf20Sopenharmony_ci * further cleanup. The transaction should complete as it normally would
2598c2ecf20Sopenharmony_ci * in the call path but will return -EIO.
2608c2ecf20Sopenharmony_ci *
2618c2ecf20Sopenharmony_ci * We'll complete the cleanup in btrfs_end_transaction and
2628c2ecf20Sopenharmony_ci * btrfs_commit_transaction.
2638c2ecf20Sopenharmony_ci */
2648c2ecf20Sopenharmony_ci__cold
2658c2ecf20Sopenharmony_civoid __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
2668c2ecf20Sopenharmony_ci			       const char *function,
2678c2ecf20Sopenharmony_ci			       unsigned int line, int errno)
2688c2ecf20Sopenharmony_ci{
2698c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = trans->fs_info;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	WRITE_ONCE(trans->aborted, errno);
2728c2ecf20Sopenharmony_ci	/* Nothing used. The other threads that have joined this
2738c2ecf20Sopenharmony_ci	 * transaction may be able to continue. */
2748c2ecf20Sopenharmony_ci	if (!trans->dirty && list_empty(&trans->new_bgs)) {
2758c2ecf20Sopenharmony_ci		const char *errstr;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci		errstr = btrfs_decode_error(errno);
2788c2ecf20Sopenharmony_ci		btrfs_warn(fs_info,
2798c2ecf20Sopenharmony_ci		           "%s:%d: Aborting unused transaction(%s).",
2808c2ecf20Sopenharmony_ci		           function, line, errstr);
2818c2ecf20Sopenharmony_ci		return;
2828c2ecf20Sopenharmony_ci	}
2838c2ecf20Sopenharmony_ci	WRITE_ONCE(trans->transaction->aborted, errno);
2848c2ecf20Sopenharmony_ci	/* Wake up anybody who may be waiting on this transaction */
2858c2ecf20Sopenharmony_ci	wake_up(&fs_info->transaction_wait);
2868c2ecf20Sopenharmony_ci	wake_up(&fs_info->transaction_blocked_wait);
2878c2ecf20Sopenharmony_ci	__btrfs_handle_fs_error(fs_info, function, line, errno, NULL);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci/*
2908c2ecf20Sopenharmony_ci * __btrfs_panic decodes unexpected, fatal errors from the caller,
2918c2ecf20Sopenharmony_ci * issues an alert, and either panics or BUGs, depending on mount options.
2928c2ecf20Sopenharmony_ci */
2938c2ecf20Sopenharmony_ci__cold
2948c2ecf20Sopenharmony_civoid __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function,
2958c2ecf20Sopenharmony_ci		   unsigned int line, int errno, const char *fmt, ...)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	char *s_id = "<unknown>";
2988c2ecf20Sopenharmony_ci	const char *errstr;
2998c2ecf20Sopenharmony_ci	struct va_format vaf = { .fmt = fmt };
3008c2ecf20Sopenharmony_ci	va_list args;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (fs_info)
3038c2ecf20Sopenharmony_ci		s_id = fs_info->sb->s_id;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	va_start(args, fmt);
3068c2ecf20Sopenharmony_ci	vaf.va = &args;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	errstr = btrfs_decode_error(errno);
3098c2ecf20Sopenharmony_ci	if (fs_info && (btrfs_test_opt(fs_info, PANIC_ON_FATAL_ERROR)))
3108c2ecf20Sopenharmony_ci		panic(KERN_CRIT "BTRFS panic (device %s) in %s:%d: %pV (errno=%d %s)\n",
3118c2ecf20Sopenharmony_ci			s_id, function, line, &vaf, errno, errstr);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	btrfs_crit(fs_info, "panic in %s:%d: %pV (errno=%d %s)",
3148c2ecf20Sopenharmony_ci		   function, line, &vaf, errno, errstr);
3158c2ecf20Sopenharmony_ci	va_end(args);
3168c2ecf20Sopenharmony_ci	/* Caller calls BUG() */
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_cistatic void btrfs_put_super(struct super_block *sb)
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	close_ctree(btrfs_sb(sb));
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cienum {
3258c2ecf20Sopenharmony_ci	Opt_acl, Opt_noacl,
3268c2ecf20Sopenharmony_ci	Opt_clear_cache,
3278c2ecf20Sopenharmony_ci	Opt_commit_interval,
3288c2ecf20Sopenharmony_ci	Opt_compress,
3298c2ecf20Sopenharmony_ci	Opt_compress_force,
3308c2ecf20Sopenharmony_ci	Opt_compress_force_type,
3318c2ecf20Sopenharmony_ci	Opt_compress_type,
3328c2ecf20Sopenharmony_ci	Opt_degraded,
3338c2ecf20Sopenharmony_ci	Opt_device,
3348c2ecf20Sopenharmony_ci	Opt_fatal_errors,
3358c2ecf20Sopenharmony_ci	Opt_flushoncommit, Opt_noflushoncommit,
3368c2ecf20Sopenharmony_ci	Opt_inode_cache, Opt_noinode_cache,
3378c2ecf20Sopenharmony_ci	Opt_max_inline,
3388c2ecf20Sopenharmony_ci	Opt_barrier, Opt_nobarrier,
3398c2ecf20Sopenharmony_ci	Opt_datacow, Opt_nodatacow,
3408c2ecf20Sopenharmony_ci	Opt_datasum, Opt_nodatasum,
3418c2ecf20Sopenharmony_ci	Opt_defrag, Opt_nodefrag,
3428c2ecf20Sopenharmony_ci	Opt_discard, Opt_nodiscard,
3438c2ecf20Sopenharmony_ci	Opt_discard_mode,
3448c2ecf20Sopenharmony_ci	Opt_norecovery,
3458c2ecf20Sopenharmony_ci	Opt_ratio,
3468c2ecf20Sopenharmony_ci	Opt_rescan_uuid_tree,
3478c2ecf20Sopenharmony_ci	Opt_skip_balance,
3488c2ecf20Sopenharmony_ci	Opt_space_cache, Opt_no_space_cache,
3498c2ecf20Sopenharmony_ci	Opt_space_cache_version,
3508c2ecf20Sopenharmony_ci	Opt_ssd, Opt_nossd,
3518c2ecf20Sopenharmony_ci	Opt_ssd_spread, Opt_nossd_spread,
3528c2ecf20Sopenharmony_ci	Opt_subvol,
3538c2ecf20Sopenharmony_ci	Opt_subvol_empty,
3548c2ecf20Sopenharmony_ci	Opt_subvolid,
3558c2ecf20Sopenharmony_ci	Opt_thread_pool,
3568c2ecf20Sopenharmony_ci	Opt_treelog, Opt_notreelog,
3578c2ecf20Sopenharmony_ci	Opt_user_subvol_rm_allowed,
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	/* Rescue options */
3608c2ecf20Sopenharmony_ci	Opt_rescue,
3618c2ecf20Sopenharmony_ci	Opt_usebackuproot,
3628c2ecf20Sopenharmony_ci	Opt_nologreplay,
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	/* Deprecated options */
3658c2ecf20Sopenharmony_ci	Opt_recovery,
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	/* Debugging options */
3688c2ecf20Sopenharmony_ci	Opt_check_integrity,
3698c2ecf20Sopenharmony_ci	Opt_check_integrity_including_extent_data,
3708c2ecf20Sopenharmony_ci	Opt_check_integrity_print_mask,
3718c2ecf20Sopenharmony_ci	Opt_enospc_debug, Opt_noenospc_debug,
3728c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG
3738c2ecf20Sopenharmony_ci	Opt_fragment_data, Opt_fragment_metadata, Opt_fragment_all,
3748c2ecf20Sopenharmony_ci#endif
3758c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_REF_VERIFY
3768c2ecf20Sopenharmony_ci	Opt_ref_verify,
3778c2ecf20Sopenharmony_ci#endif
3788c2ecf20Sopenharmony_ci	Opt_err,
3798c2ecf20Sopenharmony_ci};
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_cistatic const match_table_t tokens = {
3828c2ecf20Sopenharmony_ci	{Opt_acl, "acl"},
3838c2ecf20Sopenharmony_ci	{Opt_noacl, "noacl"},
3848c2ecf20Sopenharmony_ci	{Opt_clear_cache, "clear_cache"},
3858c2ecf20Sopenharmony_ci	{Opt_commit_interval, "commit=%u"},
3868c2ecf20Sopenharmony_ci	{Opt_compress, "compress"},
3878c2ecf20Sopenharmony_ci	{Opt_compress_type, "compress=%s"},
3888c2ecf20Sopenharmony_ci	{Opt_compress_force, "compress-force"},
3898c2ecf20Sopenharmony_ci	{Opt_compress_force_type, "compress-force=%s"},
3908c2ecf20Sopenharmony_ci	{Opt_degraded, "degraded"},
3918c2ecf20Sopenharmony_ci	{Opt_device, "device=%s"},
3928c2ecf20Sopenharmony_ci	{Opt_fatal_errors, "fatal_errors=%s"},
3938c2ecf20Sopenharmony_ci	{Opt_flushoncommit, "flushoncommit"},
3948c2ecf20Sopenharmony_ci	{Opt_noflushoncommit, "noflushoncommit"},
3958c2ecf20Sopenharmony_ci	{Opt_inode_cache, "inode_cache"},
3968c2ecf20Sopenharmony_ci	{Opt_noinode_cache, "noinode_cache"},
3978c2ecf20Sopenharmony_ci	{Opt_max_inline, "max_inline=%s"},
3988c2ecf20Sopenharmony_ci	{Opt_barrier, "barrier"},
3998c2ecf20Sopenharmony_ci	{Opt_nobarrier, "nobarrier"},
4008c2ecf20Sopenharmony_ci	{Opt_datacow, "datacow"},
4018c2ecf20Sopenharmony_ci	{Opt_nodatacow, "nodatacow"},
4028c2ecf20Sopenharmony_ci	{Opt_datasum, "datasum"},
4038c2ecf20Sopenharmony_ci	{Opt_nodatasum, "nodatasum"},
4048c2ecf20Sopenharmony_ci	{Opt_defrag, "autodefrag"},
4058c2ecf20Sopenharmony_ci	{Opt_nodefrag, "noautodefrag"},
4068c2ecf20Sopenharmony_ci	{Opt_discard, "discard"},
4078c2ecf20Sopenharmony_ci	{Opt_discard_mode, "discard=%s"},
4088c2ecf20Sopenharmony_ci	{Opt_nodiscard, "nodiscard"},
4098c2ecf20Sopenharmony_ci	{Opt_norecovery, "norecovery"},
4108c2ecf20Sopenharmony_ci	{Opt_ratio, "metadata_ratio=%u"},
4118c2ecf20Sopenharmony_ci	{Opt_rescan_uuid_tree, "rescan_uuid_tree"},
4128c2ecf20Sopenharmony_ci	{Opt_skip_balance, "skip_balance"},
4138c2ecf20Sopenharmony_ci	{Opt_space_cache, "space_cache"},
4148c2ecf20Sopenharmony_ci	{Opt_no_space_cache, "nospace_cache"},
4158c2ecf20Sopenharmony_ci	{Opt_space_cache_version, "space_cache=%s"},
4168c2ecf20Sopenharmony_ci	{Opt_ssd, "ssd"},
4178c2ecf20Sopenharmony_ci	{Opt_nossd, "nossd"},
4188c2ecf20Sopenharmony_ci	{Opt_ssd_spread, "ssd_spread"},
4198c2ecf20Sopenharmony_ci	{Opt_nossd_spread, "nossd_spread"},
4208c2ecf20Sopenharmony_ci	{Opt_subvol, "subvol=%s"},
4218c2ecf20Sopenharmony_ci	{Opt_subvol_empty, "subvol="},
4228c2ecf20Sopenharmony_ci	{Opt_subvolid, "subvolid=%s"},
4238c2ecf20Sopenharmony_ci	{Opt_thread_pool, "thread_pool=%u"},
4248c2ecf20Sopenharmony_ci	{Opt_treelog, "treelog"},
4258c2ecf20Sopenharmony_ci	{Opt_notreelog, "notreelog"},
4268c2ecf20Sopenharmony_ci	{Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"},
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* Rescue options */
4298c2ecf20Sopenharmony_ci	{Opt_rescue, "rescue=%s"},
4308c2ecf20Sopenharmony_ci	/* Deprecated, with alias rescue=nologreplay */
4318c2ecf20Sopenharmony_ci	{Opt_nologreplay, "nologreplay"},
4328c2ecf20Sopenharmony_ci	/* Deprecated, with alias rescue=usebackuproot */
4338c2ecf20Sopenharmony_ci	{Opt_usebackuproot, "usebackuproot"},
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	/* Deprecated options */
4368c2ecf20Sopenharmony_ci	{Opt_recovery, "recovery"},
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	/* Debugging options */
4398c2ecf20Sopenharmony_ci	{Opt_check_integrity, "check_int"},
4408c2ecf20Sopenharmony_ci	{Opt_check_integrity_including_extent_data, "check_int_data"},
4418c2ecf20Sopenharmony_ci	{Opt_check_integrity_print_mask, "check_int_print_mask=%u"},
4428c2ecf20Sopenharmony_ci	{Opt_enospc_debug, "enospc_debug"},
4438c2ecf20Sopenharmony_ci	{Opt_noenospc_debug, "noenospc_debug"},
4448c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG
4458c2ecf20Sopenharmony_ci	{Opt_fragment_data, "fragment=data"},
4468c2ecf20Sopenharmony_ci	{Opt_fragment_metadata, "fragment=metadata"},
4478c2ecf20Sopenharmony_ci	{Opt_fragment_all, "fragment=all"},
4488c2ecf20Sopenharmony_ci#endif
4498c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_REF_VERIFY
4508c2ecf20Sopenharmony_ci	{Opt_ref_verify, "ref_verify"},
4518c2ecf20Sopenharmony_ci#endif
4528c2ecf20Sopenharmony_ci	{Opt_err, NULL},
4538c2ecf20Sopenharmony_ci};
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_cistatic const match_table_t rescue_tokens = {
4568c2ecf20Sopenharmony_ci	{Opt_usebackuproot, "usebackuproot"},
4578c2ecf20Sopenharmony_ci	{Opt_nologreplay, "nologreplay"},
4588c2ecf20Sopenharmony_ci	{Opt_err, NULL},
4598c2ecf20Sopenharmony_ci};
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic int parse_rescue_options(struct btrfs_fs_info *info, const char *options)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	char *opts;
4648c2ecf20Sopenharmony_ci	char *orig;
4658c2ecf20Sopenharmony_ci	char *p;
4668c2ecf20Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
4678c2ecf20Sopenharmony_ci	int ret = 0;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	opts = kstrdup(options, GFP_KERNEL);
4708c2ecf20Sopenharmony_ci	if (!opts)
4718c2ecf20Sopenharmony_ci		return -ENOMEM;
4728c2ecf20Sopenharmony_ci	orig = opts;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	while ((p = strsep(&opts, ":")) != NULL) {
4758c2ecf20Sopenharmony_ci		int token;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		if (!*p)
4788c2ecf20Sopenharmony_ci			continue;
4798c2ecf20Sopenharmony_ci		token = match_token(p, rescue_tokens, args);
4808c2ecf20Sopenharmony_ci		switch (token){
4818c2ecf20Sopenharmony_ci		case Opt_usebackuproot:
4828c2ecf20Sopenharmony_ci			btrfs_info(info,
4838c2ecf20Sopenharmony_ci				   "trying to use backup root at mount time");
4848c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, USEBACKUPROOT);
4858c2ecf20Sopenharmony_ci			break;
4868c2ecf20Sopenharmony_ci		case Opt_nologreplay:
4878c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, NOLOGREPLAY,
4888c2ecf20Sopenharmony_ci					   "disabling log replay at mount time");
4898c2ecf20Sopenharmony_ci			break;
4908c2ecf20Sopenharmony_ci		case Opt_err:
4918c2ecf20Sopenharmony_ci			btrfs_info(info, "unrecognized rescue option '%s'", p);
4928c2ecf20Sopenharmony_ci			ret = -EINVAL;
4938c2ecf20Sopenharmony_ci			goto out;
4948c2ecf20Sopenharmony_ci		default:
4958c2ecf20Sopenharmony_ci			break;
4968c2ecf20Sopenharmony_ci		}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ciout:
5008c2ecf20Sopenharmony_ci	kfree(orig);
5018c2ecf20Sopenharmony_ci	return ret;
5028c2ecf20Sopenharmony_ci}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci/*
5058c2ecf20Sopenharmony_ci * Regular mount options parser.  Everything that is needed only when
5068c2ecf20Sopenharmony_ci * reading in a new superblock is parsed here.
5078c2ecf20Sopenharmony_ci * XXX JDM: This needs to be cleaned up for remount.
5088c2ecf20Sopenharmony_ci */
5098c2ecf20Sopenharmony_ciint btrfs_parse_options(struct btrfs_fs_info *info, char *options,
5108c2ecf20Sopenharmony_ci			unsigned long new_flags)
5118c2ecf20Sopenharmony_ci{
5128c2ecf20Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
5138c2ecf20Sopenharmony_ci	char *p, *num;
5148c2ecf20Sopenharmony_ci	u64 cache_gen;
5158c2ecf20Sopenharmony_ci	int intarg;
5168c2ecf20Sopenharmony_ci	int ret = 0;
5178c2ecf20Sopenharmony_ci	char *compress_type;
5188c2ecf20Sopenharmony_ci	bool compress_force = false;
5198c2ecf20Sopenharmony_ci	enum btrfs_compression_type saved_compress_type;
5208c2ecf20Sopenharmony_ci	int saved_compress_level;
5218c2ecf20Sopenharmony_ci	bool saved_compress_force;
5228c2ecf20Sopenharmony_ci	int no_compress = 0;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	cache_gen = btrfs_super_cache_generation(info->super_copy);
5258c2ecf20Sopenharmony_ci	if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE))
5268c2ecf20Sopenharmony_ci		btrfs_set_opt(info->mount_opt, FREE_SPACE_TREE);
5278c2ecf20Sopenharmony_ci	else if (cache_gen)
5288c2ecf20Sopenharmony_ci		btrfs_set_opt(info->mount_opt, SPACE_CACHE);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	/*
5318c2ecf20Sopenharmony_ci	 * Even the options are empty, we still need to do extra check
5328c2ecf20Sopenharmony_ci	 * against new flags
5338c2ecf20Sopenharmony_ci	 */
5348c2ecf20Sopenharmony_ci	if (!options)
5358c2ecf20Sopenharmony_ci		goto check;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	while ((p = strsep(&options, ",")) != NULL) {
5388c2ecf20Sopenharmony_ci		int token;
5398c2ecf20Sopenharmony_ci		if (!*p)
5408c2ecf20Sopenharmony_ci			continue;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci		token = match_token(p, tokens, args);
5438c2ecf20Sopenharmony_ci		switch (token) {
5448c2ecf20Sopenharmony_ci		case Opt_degraded:
5458c2ecf20Sopenharmony_ci			btrfs_info(info, "allowing degraded mounts");
5468c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, DEGRADED);
5478c2ecf20Sopenharmony_ci			break;
5488c2ecf20Sopenharmony_ci		case Opt_subvol:
5498c2ecf20Sopenharmony_ci		case Opt_subvol_empty:
5508c2ecf20Sopenharmony_ci		case Opt_subvolid:
5518c2ecf20Sopenharmony_ci		case Opt_device:
5528c2ecf20Sopenharmony_ci			/*
5538c2ecf20Sopenharmony_ci			 * These are parsed by btrfs_parse_subvol_options or
5548c2ecf20Sopenharmony_ci			 * btrfs_parse_device_options and can be ignored here.
5558c2ecf20Sopenharmony_ci			 */
5568c2ecf20Sopenharmony_ci			break;
5578c2ecf20Sopenharmony_ci		case Opt_nodatasum:
5588c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, NODATASUM,
5598c2ecf20Sopenharmony_ci					   "setting nodatasum");
5608c2ecf20Sopenharmony_ci			break;
5618c2ecf20Sopenharmony_ci		case Opt_datasum:
5628c2ecf20Sopenharmony_ci			if (btrfs_test_opt(info, NODATASUM)) {
5638c2ecf20Sopenharmony_ci				if (btrfs_test_opt(info, NODATACOW))
5648c2ecf20Sopenharmony_ci					btrfs_info(info,
5658c2ecf20Sopenharmony_ci						   "setting datasum, datacow enabled");
5668c2ecf20Sopenharmony_ci				else
5678c2ecf20Sopenharmony_ci					btrfs_info(info, "setting datasum");
5688c2ecf20Sopenharmony_ci			}
5698c2ecf20Sopenharmony_ci			btrfs_clear_opt(info->mount_opt, NODATACOW);
5708c2ecf20Sopenharmony_ci			btrfs_clear_opt(info->mount_opt, NODATASUM);
5718c2ecf20Sopenharmony_ci			break;
5728c2ecf20Sopenharmony_ci		case Opt_nodatacow:
5738c2ecf20Sopenharmony_ci			if (!btrfs_test_opt(info, NODATACOW)) {
5748c2ecf20Sopenharmony_ci				if (!btrfs_test_opt(info, COMPRESS) ||
5758c2ecf20Sopenharmony_ci				    !btrfs_test_opt(info, FORCE_COMPRESS)) {
5768c2ecf20Sopenharmony_ci					btrfs_info(info,
5778c2ecf20Sopenharmony_ci						   "setting nodatacow, compression disabled");
5788c2ecf20Sopenharmony_ci				} else {
5798c2ecf20Sopenharmony_ci					btrfs_info(info, "setting nodatacow");
5808c2ecf20Sopenharmony_ci				}
5818c2ecf20Sopenharmony_ci			}
5828c2ecf20Sopenharmony_ci			btrfs_clear_opt(info->mount_opt, COMPRESS);
5838c2ecf20Sopenharmony_ci			btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
5848c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, NODATACOW);
5858c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, NODATASUM);
5868c2ecf20Sopenharmony_ci			break;
5878c2ecf20Sopenharmony_ci		case Opt_datacow:
5888c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, NODATACOW,
5898c2ecf20Sopenharmony_ci					     "setting datacow");
5908c2ecf20Sopenharmony_ci			break;
5918c2ecf20Sopenharmony_ci		case Opt_compress_force:
5928c2ecf20Sopenharmony_ci		case Opt_compress_force_type:
5938c2ecf20Sopenharmony_ci			compress_force = true;
5948c2ecf20Sopenharmony_ci			fallthrough;
5958c2ecf20Sopenharmony_ci		case Opt_compress:
5968c2ecf20Sopenharmony_ci		case Opt_compress_type:
5978c2ecf20Sopenharmony_ci			saved_compress_type = btrfs_test_opt(info,
5988c2ecf20Sopenharmony_ci							     COMPRESS) ?
5998c2ecf20Sopenharmony_ci				info->compress_type : BTRFS_COMPRESS_NONE;
6008c2ecf20Sopenharmony_ci			saved_compress_force =
6018c2ecf20Sopenharmony_ci				btrfs_test_opt(info, FORCE_COMPRESS);
6028c2ecf20Sopenharmony_ci			saved_compress_level = info->compress_level;
6038c2ecf20Sopenharmony_ci			if (token == Opt_compress ||
6048c2ecf20Sopenharmony_ci			    token == Opt_compress_force ||
6058c2ecf20Sopenharmony_ci			    strncmp(args[0].from, "zlib", 4) == 0) {
6068c2ecf20Sopenharmony_ci				compress_type = "zlib";
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci				info->compress_type = BTRFS_COMPRESS_ZLIB;
6098c2ecf20Sopenharmony_ci				info->compress_level = BTRFS_ZLIB_DEFAULT_LEVEL;
6108c2ecf20Sopenharmony_ci				/*
6118c2ecf20Sopenharmony_ci				 * args[0] contains uninitialized data since
6128c2ecf20Sopenharmony_ci				 * for these tokens we don't expect any
6138c2ecf20Sopenharmony_ci				 * parameter.
6148c2ecf20Sopenharmony_ci				 */
6158c2ecf20Sopenharmony_ci				if (token != Opt_compress &&
6168c2ecf20Sopenharmony_ci				    token != Opt_compress_force)
6178c2ecf20Sopenharmony_ci					info->compress_level =
6188c2ecf20Sopenharmony_ci					  btrfs_compress_str2level(
6198c2ecf20Sopenharmony_ci							BTRFS_COMPRESS_ZLIB,
6208c2ecf20Sopenharmony_ci							args[0].from + 4);
6218c2ecf20Sopenharmony_ci				btrfs_set_opt(info->mount_opt, COMPRESS);
6228c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, NODATACOW);
6238c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, NODATASUM);
6248c2ecf20Sopenharmony_ci				no_compress = 0;
6258c2ecf20Sopenharmony_ci			} else if (strncmp(args[0].from, "lzo", 3) == 0) {
6268c2ecf20Sopenharmony_ci				compress_type = "lzo";
6278c2ecf20Sopenharmony_ci				info->compress_type = BTRFS_COMPRESS_LZO;
6288c2ecf20Sopenharmony_ci				info->compress_level = 0;
6298c2ecf20Sopenharmony_ci				btrfs_set_opt(info->mount_opt, COMPRESS);
6308c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, NODATACOW);
6318c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, NODATASUM);
6328c2ecf20Sopenharmony_ci				btrfs_set_fs_incompat(info, COMPRESS_LZO);
6338c2ecf20Sopenharmony_ci				no_compress = 0;
6348c2ecf20Sopenharmony_ci			} else if (strncmp(args[0].from, "zstd", 4) == 0) {
6358c2ecf20Sopenharmony_ci				compress_type = "zstd";
6368c2ecf20Sopenharmony_ci				info->compress_type = BTRFS_COMPRESS_ZSTD;
6378c2ecf20Sopenharmony_ci				info->compress_level =
6388c2ecf20Sopenharmony_ci					btrfs_compress_str2level(
6398c2ecf20Sopenharmony_ci							 BTRFS_COMPRESS_ZSTD,
6408c2ecf20Sopenharmony_ci							 args[0].from + 4);
6418c2ecf20Sopenharmony_ci				btrfs_set_opt(info->mount_opt, COMPRESS);
6428c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, NODATACOW);
6438c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, NODATASUM);
6448c2ecf20Sopenharmony_ci				btrfs_set_fs_incompat(info, COMPRESS_ZSTD);
6458c2ecf20Sopenharmony_ci				no_compress = 0;
6468c2ecf20Sopenharmony_ci			} else if (strncmp(args[0].from, "no", 2) == 0) {
6478c2ecf20Sopenharmony_ci				compress_type = "no";
6488c2ecf20Sopenharmony_ci				info->compress_level = 0;
6498c2ecf20Sopenharmony_ci				info->compress_type = 0;
6508c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, COMPRESS);
6518c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
6528c2ecf20Sopenharmony_ci				compress_force = false;
6538c2ecf20Sopenharmony_ci				no_compress++;
6548c2ecf20Sopenharmony_ci			} else {
6558c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized compression value %s",
6568c2ecf20Sopenharmony_ci					  args[0].from);
6578c2ecf20Sopenharmony_ci				ret = -EINVAL;
6588c2ecf20Sopenharmony_ci				goto out;
6598c2ecf20Sopenharmony_ci			}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci			if (compress_force) {
6628c2ecf20Sopenharmony_ci				btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
6638c2ecf20Sopenharmony_ci			} else {
6648c2ecf20Sopenharmony_ci				/*
6658c2ecf20Sopenharmony_ci				 * If we remount from compress-force=xxx to
6668c2ecf20Sopenharmony_ci				 * compress=xxx, we need clear FORCE_COMPRESS
6678c2ecf20Sopenharmony_ci				 * flag, otherwise, there is no way for users
6688c2ecf20Sopenharmony_ci				 * to disable forcible compression separately.
6698c2ecf20Sopenharmony_ci				 */
6708c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
6718c2ecf20Sopenharmony_ci			}
6728c2ecf20Sopenharmony_ci			if (no_compress == 1) {
6738c2ecf20Sopenharmony_ci				btrfs_info(info, "use no compression");
6748c2ecf20Sopenharmony_ci			} else if ((info->compress_type != saved_compress_type) ||
6758c2ecf20Sopenharmony_ci				   (compress_force != saved_compress_force) ||
6768c2ecf20Sopenharmony_ci				   (info->compress_level != saved_compress_level)) {
6778c2ecf20Sopenharmony_ci				btrfs_info(info, "%s %s compression, level %d",
6788c2ecf20Sopenharmony_ci					   (compress_force) ? "force" : "use",
6798c2ecf20Sopenharmony_ci					   compress_type, info->compress_level);
6808c2ecf20Sopenharmony_ci			}
6818c2ecf20Sopenharmony_ci			compress_force = false;
6828c2ecf20Sopenharmony_ci			break;
6838c2ecf20Sopenharmony_ci		case Opt_ssd:
6848c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, SSD,
6858c2ecf20Sopenharmony_ci					   "enabling ssd optimizations");
6868c2ecf20Sopenharmony_ci			btrfs_clear_opt(info->mount_opt, NOSSD);
6878c2ecf20Sopenharmony_ci			break;
6888c2ecf20Sopenharmony_ci		case Opt_ssd_spread:
6898c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, SSD,
6908c2ecf20Sopenharmony_ci					   "enabling ssd optimizations");
6918c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, SSD_SPREAD,
6928c2ecf20Sopenharmony_ci					   "using spread ssd allocation scheme");
6938c2ecf20Sopenharmony_ci			btrfs_clear_opt(info->mount_opt, NOSSD);
6948c2ecf20Sopenharmony_ci			break;
6958c2ecf20Sopenharmony_ci		case Opt_nossd:
6968c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, NOSSD);
6978c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, SSD,
6988c2ecf20Sopenharmony_ci					     "not using ssd optimizations");
6998c2ecf20Sopenharmony_ci			fallthrough;
7008c2ecf20Sopenharmony_ci		case Opt_nossd_spread:
7018c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, SSD_SPREAD,
7028c2ecf20Sopenharmony_ci					     "not using spread ssd allocation scheme");
7038c2ecf20Sopenharmony_ci			break;
7048c2ecf20Sopenharmony_ci		case Opt_barrier:
7058c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, NOBARRIER,
7068c2ecf20Sopenharmony_ci					     "turning on barriers");
7078c2ecf20Sopenharmony_ci			break;
7088c2ecf20Sopenharmony_ci		case Opt_nobarrier:
7098c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, NOBARRIER,
7108c2ecf20Sopenharmony_ci					   "turning off barriers");
7118c2ecf20Sopenharmony_ci			break;
7128c2ecf20Sopenharmony_ci		case Opt_thread_pool:
7138c2ecf20Sopenharmony_ci			ret = match_int(&args[0], &intarg);
7148c2ecf20Sopenharmony_ci			if (ret) {
7158c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized thread_pool value %s",
7168c2ecf20Sopenharmony_ci					  args[0].from);
7178c2ecf20Sopenharmony_ci				goto out;
7188c2ecf20Sopenharmony_ci			} else if (intarg == 0) {
7198c2ecf20Sopenharmony_ci				btrfs_err(info, "invalid value 0 for thread_pool");
7208c2ecf20Sopenharmony_ci				ret = -EINVAL;
7218c2ecf20Sopenharmony_ci				goto out;
7228c2ecf20Sopenharmony_ci			}
7238c2ecf20Sopenharmony_ci			info->thread_pool_size = intarg;
7248c2ecf20Sopenharmony_ci			break;
7258c2ecf20Sopenharmony_ci		case Opt_max_inline:
7268c2ecf20Sopenharmony_ci			num = match_strdup(&args[0]);
7278c2ecf20Sopenharmony_ci			if (num) {
7288c2ecf20Sopenharmony_ci				info->max_inline = memparse(num, NULL);
7298c2ecf20Sopenharmony_ci				kfree(num);
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci				if (info->max_inline) {
7328c2ecf20Sopenharmony_ci					info->max_inline = min_t(u64,
7338c2ecf20Sopenharmony_ci						info->max_inline,
7348c2ecf20Sopenharmony_ci						info->sectorsize);
7358c2ecf20Sopenharmony_ci				}
7368c2ecf20Sopenharmony_ci				btrfs_info(info, "max_inline at %llu",
7378c2ecf20Sopenharmony_ci					   info->max_inline);
7388c2ecf20Sopenharmony_ci			} else {
7398c2ecf20Sopenharmony_ci				ret = -ENOMEM;
7408c2ecf20Sopenharmony_ci				goto out;
7418c2ecf20Sopenharmony_ci			}
7428c2ecf20Sopenharmony_ci			break;
7438c2ecf20Sopenharmony_ci		case Opt_acl:
7448c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_POSIX_ACL
7458c2ecf20Sopenharmony_ci			info->sb->s_flags |= SB_POSIXACL;
7468c2ecf20Sopenharmony_ci			break;
7478c2ecf20Sopenharmony_ci#else
7488c2ecf20Sopenharmony_ci			btrfs_err(info, "support for ACL not compiled in!");
7498c2ecf20Sopenharmony_ci			ret = -EINVAL;
7508c2ecf20Sopenharmony_ci			goto out;
7518c2ecf20Sopenharmony_ci#endif
7528c2ecf20Sopenharmony_ci		case Opt_noacl:
7538c2ecf20Sopenharmony_ci			info->sb->s_flags &= ~SB_POSIXACL;
7548c2ecf20Sopenharmony_ci			break;
7558c2ecf20Sopenharmony_ci		case Opt_notreelog:
7568c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, NOTREELOG,
7578c2ecf20Sopenharmony_ci					   "disabling tree log");
7588c2ecf20Sopenharmony_ci			break;
7598c2ecf20Sopenharmony_ci		case Opt_treelog:
7608c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, NOTREELOG,
7618c2ecf20Sopenharmony_ci					     "enabling tree log");
7628c2ecf20Sopenharmony_ci			break;
7638c2ecf20Sopenharmony_ci		case Opt_norecovery:
7648c2ecf20Sopenharmony_ci		case Opt_nologreplay:
7658c2ecf20Sopenharmony_ci			btrfs_warn(info,
7668c2ecf20Sopenharmony_ci		"'nologreplay' is deprecated, use 'rescue=nologreplay' instead");
7678c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, NOLOGREPLAY,
7688c2ecf20Sopenharmony_ci					   "disabling log replay at mount time");
7698c2ecf20Sopenharmony_ci			break;
7708c2ecf20Sopenharmony_ci		case Opt_flushoncommit:
7718c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, FLUSHONCOMMIT,
7728c2ecf20Sopenharmony_ci					   "turning on flush-on-commit");
7738c2ecf20Sopenharmony_ci			break;
7748c2ecf20Sopenharmony_ci		case Opt_noflushoncommit:
7758c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, FLUSHONCOMMIT,
7768c2ecf20Sopenharmony_ci					     "turning off flush-on-commit");
7778c2ecf20Sopenharmony_ci			break;
7788c2ecf20Sopenharmony_ci		case Opt_ratio:
7798c2ecf20Sopenharmony_ci			ret = match_int(&args[0], &intarg);
7808c2ecf20Sopenharmony_ci			if (ret) {
7818c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized metadata_ratio value %s",
7828c2ecf20Sopenharmony_ci					  args[0].from);
7838c2ecf20Sopenharmony_ci				goto out;
7848c2ecf20Sopenharmony_ci			}
7858c2ecf20Sopenharmony_ci			info->metadata_ratio = intarg;
7868c2ecf20Sopenharmony_ci			btrfs_info(info, "metadata ratio %u",
7878c2ecf20Sopenharmony_ci				   info->metadata_ratio);
7888c2ecf20Sopenharmony_ci			break;
7898c2ecf20Sopenharmony_ci		case Opt_discard:
7908c2ecf20Sopenharmony_ci		case Opt_discard_mode:
7918c2ecf20Sopenharmony_ci			if (token == Opt_discard ||
7928c2ecf20Sopenharmony_ci			    strcmp(args[0].from, "sync") == 0) {
7938c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, DISCARD_ASYNC);
7948c2ecf20Sopenharmony_ci				btrfs_set_and_info(info, DISCARD_SYNC,
7958c2ecf20Sopenharmony_ci						   "turning on sync discard");
7968c2ecf20Sopenharmony_ci			} else if (strcmp(args[0].from, "async") == 0) {
7978c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt, DISCARD_SYNC);
7988c2ecf20Sopenharmony_ci				btrfs_set_and_info(info, DISCARD_ASYNC,
7998c2ecf20Sopenharmony_ci						   "turning on async discard");
8008c2ecf20Sopenharmony_ci			} else {
8018c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized discard mode value %s",
8028c2ecf20Sopenharmony_ci					  args[0].from);
8038c2ecf20Sopenharmony_ci				ret = -EINVAL;
8048c2ecf20Sopenharmony_ci				goto out;
8058c2ecf20Sopenharmony_ci			}
8068c2ecf20Sopenharmony_ci			break;
8078c2ecf20Sopenharmony_ci		case Opt_nodiscard:
8088c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, DISCARD_SYNC,
8098c2ecf20Sopenharmony_ci					     "turning off discard");
8108c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, DISCARD_ASYNC,
8118c2ecf20Sopenharmony_ci					     "turning off async discard");
8128c2ecf20Sopenharmony_ci			break;
8138c2ecf20Sopenharmony_ci		case Opt_space_cache:
8148c2ecf20Sopenharmony_ci		case Opt_space_cache_version:
8158c2ecf20Sopenharmony_ci			if (token == Opt_space_cache ||
8168c2ecf20Sopenharmony_ci			    strcmp(args[0].from, "v1") == 0) {
8178c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt,
8188c2ecf20Sopenharmony_ci						FREE_SPACE_TREE);
8198c2ecf20Sopenharmony_ci				btrfs_set_and_info(info, SPACE_CACHE,
8208c2ecf20Sopenharmony_ci					   "enabling disk space caching");
8218c2ecf20Sopenharmony_ci			} else if (strcmp(args[0].from, "v2") == 0) {
8228c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt,
8238c2ecf20Sopenharmony_ci						SPACE_CACHE);
8248c2ecf20Sopenharmony_ci				btrfs_set_and_info(info, FREE_SPACE_TREE,
8258c2ecf20Sopenharmony_ci						   "enabling free space tree");
8268c2ecf20Sopenharmony_ci			} else {
8278c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized space_cache value %s",
8288c2ecf20Sopenharmony_ci					  args[0].from);
8298c2ecf20Sopenharmony_ci				ret = -EINVAL;
8308c2ecf20Sopenharmony_ci				goto out;
8318c2ecf20Sopenharmony_ci			}
8328c2ecf20Sopenharmony_ci			break;
8338c2ecf20Sopenharmony_ci		case Opt_rescan_uuid_tree:
8348c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, RESCAN_UUID_TREE);
8358c2ecf20Sopenharmony_ci			break;
8368c2ecf20Sopenharmony_ci		case Opt_no_space_cache:
8378c2ecf20Sopenharmony_ci			if (btrfs_test_opt(info, SPACE_CACHE)) {
8388c2ecf20Sopenharmony_ci				btrfs_clear_and_info(info, SPACE_CACHE,
8398c2ecf20Sopenharmony_ci					     "disabling disk space caching");
8408c2ecf20Sopenharmony_ci			}
8418c2ecf20Sopenharmony_ci			if (btrfs_test_opt(info, FREE_SPACE_TREE)) {
8428c2ecf20Sopenharmony_ci				btrfs_clear_and_info(info, FREE_SPACE_TREE,
8438c2ecf20Sopenharmony_ci					     "disabling free space tree");
8448c2ecf20Sopenharmony_ci			}
8458c2ecf20Sopenharmony_ci			break;
8468c2ecf20Sopenharmony_ci		case Opt_inode_cache:
8478c2ecf20Sopenharmony_ci			btrfs_warn(info,
8488c2ecf20Sopenharmony_ci	"the 'inode_cache' option is deprecated and will have no effect from 5.11");
8498c2ecf20Sopenharmony_ci			btrfs_set_pending_and_info(info, INODE_MAP_CACHE,
8508c2ecf20Sopenharmony_ci					   "enabling inode map caching");
8518c2ecf20Sopenharmony_ci			break;
8528c2ecf20Sopenharmony_ci		case Opt_noinode_cache:
8538c2ecf20Sopenharmony_ci			btrfs_clear_pending_and_info(info, INODE_MAP_CACHE,
8548c2ecf20Sopenharmony_ci					     "disabling inode map caching");
8558c2ecf20Sopenharmony_ci			break;
8568c2ecf20Sopenharmony_ci		case Opt_clear_cache:
8578c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, CLEAR_CACHE,
8588c2ecf20Sopenharmony_ci					   "force clearing of disk cache");
8598c2ecf20Sopenharmony_ci			break;
8608c2ecf20Sopenharmony_ci		case Opt_user_subvol_rm_allowed:
8618c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, USER_SUBVOL_RM_ALLOWED);
8628c2ecf20Sopenharmony_ci			break;
8638c2ecf20Sopenharmony_ci		case Opt_enospc_debug:
8648c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, ENOSPC_DEBUG);
8658c2ecf20Sopenharmony_ci			break;
8668c2ecf20Sopenharmony_ci		case Opt_noenospc_debug:
8678c2ecf20Sopenharmony_ci			btrfs_clear_opt(info->mount_opt, ENOSPC_DEBUG);
8688c2ecf20Sopenharmony_ci			break;
8698c2ecf20Sopenharmony_ci		case Opt_defrag:
8708c2ecf20Sopenharmony_ci			btrfs_set_and_info(info, AUTO_DEFRAG,
8718c2ecf20Sopenharmony_ci					   "enabling auto defrag");
8728c2ecf20Sopenharmony_ci			break;
8738c2ecf20Sopenharmony_ci		case Opt_nodefrag:
8748c2ecf20Sopenharmony_ci			btrfs_clear_and_info(info, AUTO_DEFRAG,
8758c2ecf20Sopenharmony_ci					     "disabling auto defrag");
8768c2ecf20Sopenharmony_ci			break;
8778c2ecf20Sopenharmony_ci		case Opt_recovery:
8788c2ecf20Sopenharmony_ci		case Opt_usebackuproot:
8798c2ecf20Sopenharmony_ci			btrfs_warn(info,
8808c2ecf20Sopenharmony_ci			"'%s' is deprecated, use 'rescue=usebackuproot' instead",
8818c2ecf20Sopenharmony_ci				   token == Opt_recovery ? "recovery" :
8828c2ecf20Sopenharmony_ci				   "usebackuproot");
8838c2ecf20Sopenharmony_ci			btrfs_info(info,
8848c2ecf20Sopenharmony_ci				   "trying to use backup root at mount time");
8858c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, USEBACKUPROOT);
8868c2ecf20Sopenharmony_ci			break;
8878c2ecf20Sopenharmony_ci		case Opt_skip_balance:
8888c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, SKIP_BALANCE);
8898c2ecf20Sopenharmony_ci			break;
8908c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
8918c2ecf20Sopenharmony_ci		case Opt_check_integrity_including_extent_data:
8928c2ecf20Sopenharmony_ci			btrfs_info(info,
8938c2ecf20Sopenharmony_ci				   "enabling check integrity including extent data");
8948c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt,
8958c2ecf20Sopenharmony_ci				      CHECK_INTEGRITY_INCLUDING_EXTENT_DATA);
8968c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
8978c2ecf20Sopenharmony_ci			break;
8988c2ecf20Sopenharmony_ci		case Opt_check_integrity:
8998c2ecf20Sopenharmony_ci			btrfs_info(info, "enabling check integrity");
9008c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, CHECK_INTEGRITY);
9018c2ecf20Sopenharmony_ci			break;
9028c2ecf20Sopenharmony_ci		case Opt_check_integrity_print_mask:
9038c2ecf20Sopenharmony_ci			ret = match_int(&args[0], &intarg);
9048c2ecf20Sopenharmony_ci			if (ret) {
9058c2ecf20Sopenharmony_ci				btrfs_err(info,
9068c2ecf20Sopenharmony_ci				"unrecognized check_integrity_print_mask value %s",
9078c2ecf20Sopenharmony_ci					args[0].from);
9088c2ecf20Sopenharmony_ci				goto out;
9098c2ecf20Sopenharmony_ci			}
9108c2ecf20Sopenharmony_ci			info->check_integrity_print_mask = intarg;
9118c2ecf20Sopenharmony_ci			btrfs_info(info, "check_integrity_print_mask 0x%x",
9128c2ecf20Sopenharmony_ci				   info->check_integrity_print_mask);
9138c2ecf20Sopenharmony_ci			break;
9148c2ecf20Sopenharmony_ci#else
9158c2ecf20Sopenharmony_ci		case Opt_check_integrity_including_extent_data:
9168c2ecf20Sopenharmony_ci		case Opt_check_integrity:
9178c2ecf20Sopenharmony_ci		case Opt_check_integrity_print_mask:
9188c2ecf20Sopenharmony_ci			btrfs_err(info,
9198c2ecf20Sopenharmony_ci				  "support for check_integrity* not compiled in!");
9208c2ecf20Sopenharmony_ci			ret = -EINVAL;
9218c2ecf20Sopenharmony_ci			goto out;
9228c2ecf20Sopenharmony_ci#endif
9238c2ecf20Sopenharmony_ci		case Opt_fatal_errors:
9248c2ecf20Sopenharmony_ci			if (strcmp(args[0].from, "panic") == 0) {
9258c2ecf20Sopenharmony_ci				btrfs_set_opt(info->mount_opt,
9268c2ecf20Sopenharmony_ci					      PANIC_ON_FATAL_ERROR);
9278c2ecf20Sopenharmony_ci			} else if (strcmp(args[0].from, "bug") == 0) {
9288c2ecf20Sopenharmony_ci				btrfs_clear_opt(info->mount_opt,
9298c2ecf20Sopenharmony_ci					      PANIC_ON_FATAL_ERROR);
9308c2ecf20Sopenharmony_ci			} else {
9318c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized fatal_errors value %s",
9328c2ecf20Sopenharmony_ci					  args[0].from);
9338c2ecf20Sopenharmony_ci				ret = -EINVAL;
9348c2ecf20Sopenharmony_ci				goto out;
9358c2ecf20Sopenharmony_ci			}
9368c2ecf20Sopenharmony_ci			break;
9378c2ecf20Sopenharmony_ci		case Opt_commit_interval:
9388c2ecf20Sopenharmony_ci			intarg = 0;
9398c2ecf20Sopenharmony_ci			ret = match_int(&args[0], &intarg);
9408c2ecf20Sopenharmony_ci			if (ret) {
9418c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized commit_interval value %s",
9428c2ecf20Sopenharmony_ci					  args[0].from);
9438c2ecf20Sopenharmony_ci				ret = -EINVAL;
9448c2ecf20Sopenharmony_ci				goto out;
9458c2ecf20Sopenharmony_ci			}
9468c2ecf20Sopenharmony_ci			if (intarg == 0) {
9478c2ecf20Sopenharmony_ci				btrfs_info(info,
9488c2ecf20Sopenharmony_ci					   "using default commit interval %us",
9498c2ecf20Sopenharmony_ci					   BTRFS_DEFAULT_COMMIT_INTERVAL);
9508c2ecf20Sopenharmony_ci				intarg = BTRFS_DEFAULT_COMMIT_INTERVAL;
9518c2ecf20Sopenharmony_ci			} else if (intarg > 300) {
9528c2ecf20Sopenharmony_ci				btrfs_warn(info, "excessive commit interval %d",
9538c2ecf20Sopenharmony_ci					   intarg);
9548c2ecf20Sopenharmony_ci			}
9558c2ecf20Sopenharmony_ci			info->commit_interval = intarg;
9568c2ecf20Sopenharmony_ci			break;
9578c2ecf20Sopenharmony_ci		case Opt_rescue:
9588c2ecf20Sopenharmony_ci			ret = parse_rescue_options(info, args[0].from);
9598c2ecf20Sopenharmony_ci			if (ret < 0) {
9608c2ecf20Sopenharmony_ci				btrfs_err(info, "unrecognized rescue value %s",
9618c2ecf20Sopenharmony_ci					  args[0].from);
9628c2ecf20Sopenharmony_ci				goto out;
9638c2ecf20Sopenharmony_ci			}
9648c2ecf20Sopenharmony_ci			break;
9658c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG
9668c2ecf20Sopenharmony_ci		case Opt_fragment_all:
9678c2ecf20Sopenharmony_ci			btrfs_info(info, "fragmenting all space");
9688c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, FRAGMENT_DATA);
9698c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, FRAGMENT_METADATA);
9708c2ecf20Sopenharmony_ci			break;
9718c2ecf20Sopenharmony_ci		case Opt_fragment_metadata:
9728c2ecf20Sopenharmony_ci			btrfs_info(info, "fragmenting metadata");
9738c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt,
9748c2ecf20Sopenharmony_ci				      FRAGMENT_METADATA);
9758c2ecf20Sopenharmony_ci			break;
9768c2ecf20Sopenharmony_ci		case Opt_fragment_data:
9778c2ecf20Sopenharmony_ci			btrfs_info(info, "fragmenting data");
9788c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, FRAGMENT_DATA);
9798c2ecf20Sopenharmony_ci			break;
9808c2ecf20Sopenharmony_ci#endif
9818c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_REF_VERIFY
9828c2ecf20Sopenharmony_ci		case Opt_ref_verify:
9838c2ecf20Sopenharmony_ci			btrfs_info(info, "doing ref verification");
9848c2ecf20Sopenharmony_ci			btrfs_set_opt(info->mount_opt, REF_VERIFY);
9858c2ecf20Sopenharmony_ci			break;
9868c2ecf20Sopenharmony_ci#endif
9878c2ecf20Sopenharmony_ci		case Opt_err:
9888c2ecf20Sopenharmony_ci			btrfs_err(info, "unrecognized mount option '%s'", p);
9898c2ecf20Sopenharmony_ci			ret = -EINVAL;
9908c2ecf20Sopenharmony_ci			goto out;
9918c2ecf20Sopenharmony_ci		default:
9928c2ecf20Sopenharmony_ci			break;
9938c2ecf20Sopenharmony_ci		}
9948c2ecf20Sopenharmony_ci	}
9958c2ecf20Sopenharmony_cicheck:
9968c2ecf20Sopenharmony_ci	/*
9978c2ecf20Sopenharmony_ci	 * Extra check for current option against current flag
9988c2ecf20Sopenharmony_ci	 */
9998c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, NOLOGREPLAY) && !(new_flags & SB_RDONLY)) {
10008c2ecf20Sopenharmony_ci		btrfs_err(info,
10018c2ecf20Sopenharmony_ci			  "nologreplay must be used with ro mount option");
10028c2ecf20Sopenharmony_ci		ret = -EINVAL;
10038c2ecf20Sopenharmony_ci	}
10048c2ecf20Sopenharmony_ciout:
10058c2ecf20Sopenharmony_ci	if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE) &&
10068c2ecf20Sopenharmony_ci	    !btrfs_test_opt(info, FREE_SPACE_TREE) &&
10078c2ecf20Sopenharmony_ci	    !btrfs_test_opt(info, CLEAR_CACHE)) {
10088c2ecf20Sopenharmony_ci		btrfs_err(info, "cannot disable free space tree");
10098c2ecf20Sopenharmony_ci		ret = -EINVAL;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	}
10128c2ecf20Sopenharmony_ci	if (!ret && btrfs_test_opt(info, SPACE_CACHE))
10138c2ecf20Sopenharmony_ci		btrfs_info(info, "disk space caching is enabled");
10148c2ecf20Sopenharmony_ci	if (!ret && btrfs_test_opt(info, FREE_SPACE_TREE))
10158c2ecf20Sopenharmony_ci		btrfs_info(info, "using free space tree");
10168c2ecf20Sopenharmony_ci	return ret;
10178c2ecf20Sopenharmony_ci}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci/*
10208c2ecf20Sopenharmony_ci * Parse mount options that are required early in the mount process.
10218c2ecf20Sopenharmony_ci *
10228c2ecf20Sopenharmony_ci * All other options will be parsed on much later in the mount process and
10238c2ecf20Sopenharmony_ci * only when we need to allocate a new super block.
10248c2ecf20Sopenharmony_ci */
10258c2ecf20Sopenharmony_cistatic int btrfs_parse_device_options(const char *options, fmode_t flags,
10268c2ecf20Sopenharmony_ci				      void *holder)
10278c2ecf20Sopenharmony_ci{
10288c2ecf20Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
10298c2ecf20Sopenharmony_ci	char *device_name, *opts, *orig, *p;
10308c2ecf20Sopenharmony_ci	struct btrfs_device *device = NULL;
10318c2ecf20Sopenharmony_ci	int error = 0;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	lockdep_assert_held(&uuid_mutex);
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	if (!options)
10368c2ecf20Sopenharmony_ci		return 0;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	/*
10398c2ecf20Sopenharmony_ci	 * strsep changes the string, duplicate it because btrfs_parse_options
10408c2ecf20Sopenharmony_ci	 * gets called later
10418c2ecf20Sopenharmony_ci	 */
10428c2ecf20Sopenharmony_ci	opts = kstrdup(options, GFP_KERNEL);
10438c2ecf20Sopenharmony_ci	if (!opts)
10448c2ecf20Sopenharmony_ci		return -ENOMEM;
10458c2ecf20Sopenharmony_ci	orig = opts;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	while ((p = strsep(&opts, ",")) != NULL) {
10488c2ecf20Sopenharmony_ci		int token;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		if (!*p)
10518c2ecf20Sopenharmony_ci			continue;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci		token = match_token(p, tokens, args);
10548c2ecf20Sopenharmony_ci		if (token == Opt_device) {
10558c2ecf20Sopenharmony_ci			device_name = match_strdup(&args[0]);
10568c2ecf20Sopenharmony_ci			if (!device_name) {
10578c2ecf20Sopenharmony_ci				error = -ENOMEM;
10588c2ecf20Sopenharmony_ci				goto out;
10598c2ecf20Sopenharmony_ci			}
10608c2ecf20Sopenharmony_ci			device = btrfs_scan_one_device(device_name, flags,
10618c2ecf20Sopenharmony_ci					holder);
10628c2ecf20Sopenharmony_ci			kfree(device_name);
10638c2ecf20Sopenharmony_ci			if (IS_ERR(device)) {
10648c2ecf20Sopenharmony_ci				error = PTR_ERR(device);
10658c2ecf20Sopenharmony_ci				goto out;
10668c2ecf20Sopenharmony_ci			}
10678c2ecf20Sopenharmony_ci		}
10688c2ecf20Sopenharmony_ci	}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ciout:
10718c2ecf20Sopenharmony_ci	kfree(orig);
10728c2ecf20Sopenharmony_ci	return error;
10738c2ecf20Sopenharmony_ci}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci/*
10768c2ecf20Sopenharmony_ci * Parse mount options that are related to subvolume id
10778c2ecf20Sopenharmony_ci *
10788c2ecf20Sopenharmony_ci * The value is later passed to mount_subvol()
10798c2ecf20Sopenharmony_ci */
10808c2ecf20Sopenharmony_cistatic int btrfs_parse_subvol_options(const char *options, char **subvol_name,
10818c2ecf20Sopenharmony_ci		u64 *subvol_objectid)
10828c2ecf20Sopenharmony_ci{
10838c2ecf20Sopenharmony_ci	substring_t args[MAX_OPT_ARGS];
10848c2ecf20Sopenharmony_ci	char *opts, *orig, *p;
10858c2ecf20Sopenharmony_ci	int error = 0;
10868c2ecf20Sopenharmony_ci	u64 subvolid;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	if (!options)
10898c2ecf20Sopenharmony_ci		return 0;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	/*
10928c2ecf20Sopenharmony_ci	 * strsep changes the string, duplicate it because
10938c2ecf20Sopenharmony_ci	 * btrfs_parse_device_options gets called later
10948c2ecf20Sopenharmony_ci	 */
10958c2ecf20Sopenharmony_ci	opts = kstrdup(options, GFP_KERNEL);
10968c2ecf20Sopenharmony_ci	if (!opts)
10978c2ecf20Sopenharmony_ci		return -ENOMEM;
10988c2ecf20Sopenharmony_ci	orig = opts;
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	while ((p = strsep(&opts, ",")) != NULL) {
11018c2ecf20Sopenharmony_ci		int token;
11028c2ecf20Sopenharmony_ci		if (!*p)
11038c2ecf20Sopenharmony_ci			continue;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		token = match_token(p, tokens, args);
11068c2ecf20Sopenharmony_ci		switch (token) {
11078c2ecf20Sopenharmony_ci		case Opt_subvol:
11088c2ecf20Sopenharmony_ci			kfree(*subvol_name);
11098c2ecf20Sopenharmony_ci			*subvol_name = match_strdup(&args[0]);
11108c2ecf20Sopenharmony_ci			if (!*subvol_name) {
11118c2ecf20Sopenharmony_ci				error = -ENOMEM;
11128c2ecf20Sopenharmony_ci				goto out;
11138c2ecf20Sopenharmony_ci			}
11148c2ecf20Sopenharmony_ci			break;
11158c2ecf20Sopenharmony_ci		case Opt_subvolid:
11168c2ecf20Sopenharmony_ci			error = match_u64(&args[0], &subvolid);
11178c2ecf20Sopenharmony_ci			if (error)
11188c2ecf20Sopenharmony_ci				goto out;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci			/* we want the original fs_tree */
11218c2ecf20Sopenharmony_ci			if (subvolid == 0)
11228c2ecf20Sopenharmony_ci				subvolid = BTRFS_FS_TREE_OBJECTID;
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci			*subvol_objectid = subvolid;
11258c2ecf20Sopenharmony_ci			break;
11268c2ecf20Sopenharmony_ci		default:
11278c2ecf20Sopenharmony_ci			break;
11288c2ecf20Sopenharmony_ci		}
11298c2ecf20Sopenharmony_ci	}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ciout:
11328c2ecf20Sopenharmony_ci	kfree(orig);
11338c2ecf20Sopenharmony_ci	return error;
11348c2ecf20Sopenharmony_ci}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_cichar *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
11378c2ecf20Sopenharmony_ci					  u64 subvol_objectid)
11388c2ecf20Sopenharmony_ci{
11398c2ecf20Sopenharmony_ci	struct btrfs_root *root = fs_info->tree_root;
11408c2ecf20Sopenharmony_ci	struct btrfs_root *fs_root = NULL;
11418c2ecf20Sopenharmony_ci	struct btrfs_root_ref *root_ref;
11428c2ecf20Sopenharmony_ci	struct btrfs_inode_ref *inode_ref;
11438c2ecf20Sopenharmony_ci	struct btrfs_key key;
11448c2ecf20Sopenharmony_ci	struct btrfs_path *path = NULL;
11458c2ecf20Sopenharmony_ci	char *name = NULL, *ptr;
11468c2ecf20Sopenharmony_ci	u64 dirid;
11478c2ecf20Sopenharmony_ci	int len;
11488c2ecf20Sopenharmony_ci	int ret;
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
11518c2ecf20Sopenharmony_ci	if (!path) {
11528c2ecf20Sopenharmony_ci		ret = -ENOMEM;
11538c2ecf20Sopenharmony_ci		goto err;
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci	path->leave_spinning = 1;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	name = kmalloc(PATH_MAX, GFP_KERNEL);
11588c2ecf20Sopenharmony_ci	if (!name) {
11598c2ecf20Sopenharmony_ci		ret = -ENOMEM;
11608c2ecf20Sopenharmony_ci		goto err;
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci	ptr = name + PATH_MAX - 1;
11638c2ecf20Sopenharmony_ci	ptr[0] = '\0';
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci	/*
11668c2ecf20Sopenharmony_ci	 * Walk up the subvolume trees in the tree of tree roots by root
11678c2ecf20Sopenharmony_ci	 * backrefs until we hit the top-level subvolume.
11688c2ecf20Sopenharmony_ci	 */
11698c2ecf20Sopenharmony_ci	while (subvol_objectid != BTRFS_FS_TREE_OBJECTID) {
11708c2ecf20Sopenharmony_ci		key.objectid = subvol_objectid;
11718c2ecf20Sopenharmony_ci		key.type = BTRFS_ROOT_BACKREF_KEY;
11728c2ecf20Sopenharmony_ci		key.offset = (u64)-1;
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
11758c2ecf20Sopenharmony_ci		if (ret < 0) {
11768c2ecf20Sopenharmony_ci			goto err;
11778c2ecf20Sopenharmony_ci		} else if (ret > 0) {
11788c2ecf20Sopenharmony_ci			ret = btrfs_previous_item(root, path, subvol_objectid,
11798c2ecf20Sopenharmony_ci						  BTRFS_ROOT_BACKREF_KEY);
11808c2ecf20Sopenharmony_ci			if (ret < 0) {
11818c2ecf20Sopenharmony_ci				goto err;
11828c2ecf20Sopenharmony_ci			} else if (ret > 0) {
11838c2ecf20Sopenharmony_ci				ret = -ENOENT;
11848c2ecf20Sopenharmony_ci				goto err;
11858c2ecf20Sopenharmony_ci			}
11868c2ecf20Sopenharmony_ci		}
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci		btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
11898c2ecf20Sopenharmony_ci		subvol_objectid = key.offset;
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci		root_ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
11928c2ecf20Sopenharmony_ci					  struct btrfs_root_ref);
11938c2ecf20Sopenharmony_ci		len = btrfs_root_ref_name_len(path->nodes[0], root_ref);
11948c2ecf20Sopenharmony_ci		ptr -= len + 1;
11958c2ecf20Sopenharmony_ci		if (ptr < name) {
11968c2ecf20Sopenharmony_ci			ret = -ENAMETOOLONG;
11978c2ecf20Sopenharmony_ci			goto err;
11988c2ecf20Sopenharmony_ci		}
11998c2ecf20Sopenharmony_ci		read_extent_buffer(path->nodes[0], ptr + 1,
12008c2ecf20Sopenharmony_ci				   (unsigned long)(root_ref + 1), len);
12018c2ecf20Sopenharmony_ci		ptr[0] = '/';
12028c2ecf20Sopenharmony_ci		dirid = btrfs_root_ref_dirid(path->nodes[0], root_ref);
12038c2ecf20Sopenharmony_ci		btrfs_release_path(path);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci		fs_root = btrfs_get_fs_root(fs_info, subvol_objectid, true);
12068c2ecf20Sopenharmony_ci		if (IS_ERR(fs_root)) {
12078c2ecf20Sopenharmony_ci			ret = PTR_ERR(fs_root);
12088c2ecf20Sopenharmony_ci			fs_root = NULL;
12098c2ecf20Sopenharmony_ci			goto err;
12108c2ecf20Sopenharmony_ci		}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci		/*
12138c2ecf20Sopenharmony_ci		 * Walk up the filesystem tree by inode refs until we hit the
12148c2ecf20Sopenharmony_ci		 * root directory.
12158c2ecf20Sopenharmony_ci		 */
12168c2ecf20Sopenharmony_ci		while (dirid != BTRFS_FIRST_FREE_OBJECTID) {
12178c2ecf20Sopenharmony_ci			key.objectid = dirid;
12188c2ecf20Sopenharmony_ci			key.type = BTRFS_INODE_REF_KEY;
12198c2ecf20Sopenharmony_ci			key.offset = (u64)-1;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci			ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
12228c2ecf20Sopenharmony_ci			if (ret < 0) {
12238c2ecf20Sopenharmony_ci				goto err;
12248c2ecf20Sopenharmony_ci			} else if (ret > 0) {
12258c2ecf20Sopenharmony_ci				ret = btrfs_previous_item(fs_root, path, dirid,
12268c2ecf20Sopenharmony_ci							  BTRFS_INODE_REF_KEY);
12278c2ecf20Sopenharmony_ci				if (ret < 0) {
12288c2ecf20Sopenharmony_ci					goto err;
12298c2ecf20Sopenharmony_ci				} else if (ret > 0) {
12308c2ecf20Sopenharmony_ci					ret = -ENOENT;
12318c2ecf20Sopenharmony_ci					goto err;
12328c2ecf20Sopenharmony_ci				}
12338c2ecf20Sopenharmony_ci			}
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci			btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
12368c2ecf20Sopenharmony_ci			dirid = key.offset;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci			inode_ref = btrfs_item_ptr(path->nodes[0],
12398c2ecf20Sopenharmony_ci						   path->slots[0],
12408c2ecf20Sopenharmony_ci						   struct btrfs_inode_ref);
12418c2ecf20Sopenharmony_ci			len = btrfs_inode_ref_name_len(path->nodes[0],
12428c2ecf20Sopenharmony_ci						       inode_ref);
12438c2ecf20Sopenharmony_ci			ptr -= len + 1;
12448c2ecf20Sopenharmony_ci			if (ptr < name) {
12458c2ecf20Sopenharmony_ci				ret = -ENAMETOOLONG;
12468c2ecf20Sopenharmony_ci				goto err;
12478c2ecf20Sopenharmony_ci			}
12488c2ecf20Sopenharmony_ci			read_extent_buffer(path->nodes[0], ptr + 1,
12498c2ecf20Sopenharmony_ci					   (unsigned long)(inode_ref + 1), len);
12508c2ecf20Sopenharmony_ci			ptr[0] = '/';
12518c2ecf20Sopenharmony_ci			btrfs_release_path(path);
12528c2ecf20Sopenharmony_ci		}
12538c2ecf20Sopenharmony_ci		btrfs_put_root(fs_root);
12548c2ecf20Sopenharmony_ci		fs_root = NULL;
12558c2ecf20Sopenharmony_ci	}
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	btrfs_free_path(path);
12588c2ecf20Sopenharmony_ci	if (ptr == name + PATH_MAX - 1) {
12598c2ecf20Sopenharmony_ci		name[0] = '/';
12608c2ecf20Sopenharmony_ci		name[1] = '\0';
12618c2ecf20Sopenharmony_ci	} else {
12628c2ecf20Sopenharmony_ci		memmove(name, ptr, name + PATH_MAX - ptr);
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci	return name;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_cierr:
12678c2ecf20Sopenharmony_ci	btrfs_put_root(fs_root);
12688c2ecf20Sopenharmony_ci	btrfs_free_path(path);
12698c2ecf20Sopenharmony_ci	kfree(name);
12708c2ecf20Sopenharmony_ci	return ERR_PTR(ret);
12718c2ecf20Sopenharmony_ci}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_cistatic int get_default_subvol_objectid(struct btrfs_fs_info *fs_info, u64 *objectid)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	struct btrfs_root *root = fs_info->tree_root;
12768c2ecf20Sopenharmony_ci	struct btrfs_dir_item *di;
12778c2ecf20Sopenharmony_ci	struct btrfs_path *path;
12788c2ecf20Sopenharmony_ci	struct btrfs_key location;
12798c2ecf20Sopenharmony_ci	u64 dir_id;
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	path = btrfs_alloc_path();
12828c2ecf20Sopenharmony_ci	if (!path)
12838c2ecf20Sopenharmony_ci		return -ENOMEM;
12848c2ecf20Sopenharmony_ci	path->leave_spinning = 1;
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	/*
12878c2ecf20Sopenharmony_ci	 * Find the "default" dir item which points to the root item that we
12888c2ecf20Sopenharmony_ci	 * will mount by default if we haven't been given a specific subvolume
12898c2ecf20Sopenharmony_ci	 * to mount.
12908c2ecf20Sopenharmony_ci	 */
12918c2ecf20Sopenharmony_ci	dir_id = btrfs_super_root_dir(fs_info->super_copy);
12928c2ecf20Sopenharmony_ci	di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0);
12938c2ecf20Sopenharmony_ci	if (IS_ERR(di)) {
12948c2ecf20Sopenharmony_ci		btrfs_free_path(path);
12958c2ecf20Sopenharmony_ci		return PTR_ERR(di);
12968c2ecf20Sopenharmony_ci	}
12978c2ecf20Sopenharmony_ci	if (!di) {
12988c2ecf20Sopenharmony_ci		/*
12998c2ecf20Sopenharmony_ci		 * Ok the default dir item isn't there.  This is weird since
13008c2ecf20Sopenharmony_ci		 * it's always been there, but don't freak out, just try and
13018c2ecf20Sopenharmony_ci		 * mount the top-level subvolume.
13028c2ecf20Sopenharmony_ci		 */
13038c2ecf20Sopenharmony_ci		btrfs_free_path(path);
13048c2ecf20Sopenharmony_ci		*objectid = BTRFS_FS_TREE_OBJECTID;
13058c2ecf20Sopenharmony_ci		return 0;
13068c2ecf20Sopenharmony_ci	}
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
13098c2ecf20Sopenharmony_ci	btrfs_free_path(path);
13108c2ecf20Sopenharmony_ci	*objectid = location.objectid;
13118c2ecf20Sopenharmony_ci	return 0;
13128c2ecf20Sopenharmony_ci}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_cistatic int btrfs_fill_super(struct super_block *sb,
13158c2ecf20Sopenharmony_ci			    struct btrfs_fs_devices *fs_devices,
13168c2ecf20Sopenharmony_ci			    void *data)
13178c2ecf20Sopenharmony_ci{
13188c2ecf20Sopenharmony_ci	struct inode *inode;
13198c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
13208c2ecf20Sopenharmony_ci	int err;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	sb->s_maxbytes = MAX_LFS_FILESIZE;
13238c2ecf20Sopenharmony_ci	sb->s_magic = BTRFS_SUPER_MAGIC;
13248c2ecf20Sopenharmony_ci	sb->s_op = &btrfs_super_ops;
13258c2ecf20Sopenharmony_ci	sb->s_d_op = &btrfs_dentry_operations;
13268c2ecf20Sopenharmony_ci	sb->s_export_op = &btrfs_export_ops;
13278c2ecf20Sopenharmony_ci	sb->s_xattr = btrfs_xattr_handlers;
13288c2ecf20Sopenharmony_ci	sb->s_time_gran = 1;
13298c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_POSIX_ACL
13308c2ecf20Sopenharmony_ci	sb->s_flags |= SB_POSIXACL;
13318c2ecf20Sopenharmony_ci#endif
13328c2ecf20Sopenharmony_ci	sb->s_flags |= SB_I_VERSION;
13338c2ecf20Sopenharmony_ci	sb->s_iflags |= SB_I_CGROUPWB;
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_ci	err = super_setup_bdi(sb);
13368c2ecf20Sopenharmony_ci	if (err) {
13378c2ecf20Sopenharmony_ci		btrfs_err(fs_info, "super_setup_bdi failed");
13388c2ecf20Sopenharmony_ci		return err;
13398c2ecf20Sopenharmony_ci	}
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	err = open_ctree(sb, fs_devices, (char *)data);
13428c2ecf20Sopenharmony_ci	if (err) {
13438c2ecf20Sopenharmony_ci		btrfs_err(fs_info, "open_ctree failed");
13448c2ecf20Sopenharmony_ci		return err;
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	inode = btrfs_iget(sb, BTRFS_FIRST_FREE_OBJECTID, fs_info->fs_root);
13488c2ecf20Sopenharmony_ci	if (IS_ERR(inode)) {
13498c2ecf20Sopenharmony_ci		err = PTR_ERR(inode);
13508c2ecf20Sopenharmony_ci		goto fail_close;
13518c2ecf20Sopenharmony_ci	}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	sb->s_root = d_make_root(inode);
13548c2ecf20Sopenharmony_ci	if (!sb->s_root) {
13558c2ecf20Sopenharmony_ci		err = -ENOMEM;
13568c2ecf20Sopenharmony_ci		goto fail_close;
13578c2ecf20Sopenharmony_ci	}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	cleancache_init_fs(sb);
13608c2ecf20Sopenharmony_ci	sb->s_flags |= SB_ACTIVE;
13618c2ecf20Sopenharmony_ci	return 0;
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_cifail_close:
13648c2ecf20Sopenharmony_ci	close_ctree(fs_info);
13658c2ecf20Sopenharmony_ci	return err;
13668c2ecf20Sopenharmony_ci}
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ciint btrfs_sync_fs(struct super_block *sb, int wait)
13698c2ecf20Sopenharmony_ci{
13708c2ecf20Sopenharmony_ci	struct btrfs_trans_handle *trans;
13718c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
13728c2ecf20Sopenharmony_ci	struct btrfs_root *root = fs_info->tree_root;
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci	trace_btrfs_sync_fs(fs_info, wait);
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	if (!wait) {
13778c2ecf20Sopenharmony_ci		filemap_flush(fs_info->btree_inode->i_mapping);
13788c2ecf20Sopenharmony_ci		return 0;
13798c2ecf20Sopenharmony_ci	}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	trans = btrfs_attach_transaction_barrier(root);
13848c2ecf20Sopenharmony_ci	if (IS_ERR(trans)) {
13858c2ecf20Sopenharmony_ci		/* no transaction, don't bother */
13868c2ecf20Sopenharmony_ci		if (PTR_ERR(trans) == -ENOENT) {
13878c2ecf20Sopenharmony_ci			/*
13888c2ecf20Sopenharmony_ci			 * Exit unless we have some pending changes
13898c2ecf20Sopenharmony_ci			 * that need to go through commit
13908c2ecf20Sopenharmony_ci			 */
13918c2ecf20Sopenharmony_ci			if (fs_info->pending_changes == 0)
13928c2ecf20Sopenharmony_ci				return 0;
13938c2ecf20Sopenharmony_ci			/*
13948c2ecf20Sopenharmony_ci			 * A non-blocking test if the fs is frozen. We must not
13958c2ecf20Sopenharmony_ci			 * start a new transaction here otherwise a deadlock
13968c2ecf20Sopenharmony_ci			 * happens. The pending operations are delayed to the
13978c2ecf20Sopenharmony_ci			 * next commit after thawing.
13988c2ecf20Sopenharmony_ci			 */
13998c2ecf20Sopenharmony_ci			if (sb_start_write_trylock(sb))
14008c2ecf20Sopenharmony_ci				sb_end_write(sb);
14018c2ecf20Sopenharmony_ci			else
14028c2ecf20Sopenharmony_ci				return 0;
14038c2ecf20Sopenharmony_ci			trans = btrfs_start_transaction(root, 0);
14048c2ecf20Sopenharmony_ci		}
14058c2ecf20Sopenharmony_ci		if (IS_ERR(trans))
14068c2ecf20Sopenharmony_ci			return PTR_ERR(trans);
14078c2ecf20Sopenharmony_ci	}
14088c2ecf20Sopenharmony_ci	return btrfs_commit_transaction(trans);
14098c2ecf20Sopenharmony_ci}
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_cistatic int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
14128c2ecf20Sopenharmony_ci{
14138c2ecf20Sopenharmony_ci	struct btrfs_fs_info *info = btrfs_sb(dentry->d_sb);
14148c2ecf20Sopenharmony_ci	const char *compress_type;
14158c2ecf20Sopenharmony_ci	const char *subvol_name;
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, DEGRADED))
14188c2ecf20Sopenharmony_ci		seq_puts(seq, ",degraded");
14198c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, NODATASUM))
14208c2ecf20Sopenharmony_ci		seq_puts(seq, ",nodatasum");
14218c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, NODATACOW))
14228c2ecf20Sopenharmony_ci		seq_puts(seq, ",nodatacow");
14238c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, NOBARRIER))
14248c2ecf20Sopenharmony_ci		seq_puts(seq, ",nobarrier");
14258c2ecf20Sopenharmony_ci	if (info->max_inline != BTRFS_DEFAULT_MAX_INLINE)
14268c2ecf20Sopenharmony_ci		seq_printf(seq, ",max_inline=%llu", info->max_inline);
14278c2ecf20Sopenharmony_ci	if (info->thread_pool_size !=  min_t(unsigned long,
14288c2ecf20Sopenharmony_ci					     num_online_cpus() + 2, 8))
14298c2ecf20Sopenharmony_ci		seq_printf(seq, ",thread_pool=%u", info->thread_pool_size);
14308c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, COMPRESS)) {
14318c2ecf20Sopenharmony_ci		compress_type = btrfs_compress_type2str(info->compress_type);
14328c2ecf20Sopenharmony_ci		if (btrfs_test_opt(info, FORCE_COMPRESS))
14338c2ecf20Sopenharmony_ci			seq_printf(seq, ",compress-force=%s", compress_type);
14348c2ecf20Sopenharmony_ci		else
14358c2ecf20Sopenharmony_ci			seq_printf(seq, ",compress=%s", compress_type);
14368c2ecf20Sopenharmony_ci		if (info->compress_level)
14378c2ecf20Sopenharmony_ci			seq_printf(seq, ":%d", info->compress_level);
14388c2ecf20Sopenharmony_ci	}
14398c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, NOSSD))
14408c2ecf20Sopenharmony_ci		seq_puts(seq, ",nossd");
14418c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, SSD_SPREAD))
14428c2ecf20Sopenharmony_ci		seq_puts(seq, ",ssd_spread");
14438c2ecf20Sopenharmony_ci	else if (btrfs_test_opt(info, SSD))
14448c2ecf20Sopenharmony_ci		seq_puts(seq, ",ssd");
14458c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, NOTREELOG))
14468c2ecf20Sopenharmony_ci		seq_puts(seq, ",notreelog");
14478c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, NOLOGREPLAY))
14488c2ecf20Sopenharmony_ci		seq_puts(seq, ",rescue=nologreplay");
14498c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, FLUSHONCOMMIT))
14508c2ecf20Sopenharmony_ci		seq_puts(seq, ",flushoncommit");
14518c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, DISCARD_SYNC))
14528c2ecf20Sopenharmony_ci		seq_puts(seq, ",discard");
14538c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, DISCARD_ASYNC))
14548c2ecf20Sopenharmony_ci		seq_puts(seq, ",discard=async");
14558c2ecf20Sopenharmony_ci	if (!(info->sb->s_flags & SB_POSIXACL))
14568c2ecf20Sopenharmony_ci		seq_puts(seq, ",noacl");
14578c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, SPACE_CACHE))
14588c2ecf20Sopenharmony_ci		seq_puts(seq, ",space_cache");
14598c2ecf20Sopenharmony_ci	else if (btrfs_test_opt(info, FREE_SPACE_TREE))
14608c2ecf20Sopenharmony_ci		seq_puts(seq, ",space_cache=v2");
14618c2ecf20Sopenharmony_ci	else
14628c2ecf20Sopenharmony_ci		seq_puts(seq, ",nospace_cache");
14638c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, RESCAN_UUID_TREE))
14648c2ecf20Sopenharmony_ci		seq_puts(seq, ",rescan_uuid_tree");
14658c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, CLEAR_CACHE))
14668c2ecf20Sopenharmony_ci		seq_puts(seq, ",clear_cache");
14678c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, USER_SUBVOL_RM_ALLOWED))
14688c2ecf20Sopenharmony_ci		seq_puts(seq, ",user_subvol_rm_allowed");
14698c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, ENOSPC_DEBUG))
14708c2ecf20Sopenharmony_ci		seq_puts(seq, ",enospc_debug");
14718c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, AUTO_DEFRAG))
14728c2ecf20Sopenharmony_ci		seq_puts(seq, ",autodefrag");
14738c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, INODE_MAP_CACHE))
14748c2ecf20Sopenharmony_ci		seq_puts(seq, ",inode_cache");
14758c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, SKIP_BALANCE))
14768c2ecf20Sopenharmony_ci		seq_puts(seq, ",skip_balance");
14778c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
14788c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, CHECK_INTEGRITY_INCLUDING_EXTENT_DATA))
14798c2ecf20Sopenharmony_ci		seq_puts(seq, ",check_int_data");
14808c2ecf20Sopenharmony_ci	else if (btrfs_test_opt(info, CHECK_INTEGRITY))
14818c2ecf20Sopenharmony_ci		seq_puts(seq, ",check_int");
14828c2ecf20Sopenharmony_ci	if (info->check_integrity_print_mask)
14838c2ecf20Sopenharmony_ci		seq_printf(seq, ",check_int_print_mask=%d",
14848c2ecf20Sopenharmony_ci				info->check_integrity_print_mask);
14858c2ecf20Sopenharmony_ci#endif
14868c2ecf20Sopenharmony_ci	if (info->metadata_ratio)
14878c2ecf20Sopenharmony_ci		seq_printf(seq, ",metadata_ratio=%u", info->metadata_ratio);
14888c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, PANIC_ON_FATAL_ERROR))
14898c2ecf20Sopenharmony_ci		seq_puts(seq, ",fatal_errors=panic");
14908c2ecf20Sopenharmony_ci	if (info->commit_interval != BTRFS_DEFAULT_COMMIT_INTERVAL)
14918c2ecf20Sopenharmony_ci		seq_printf(seq, ",commit=%u", info->commit_interval);
14928c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG
14938c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, FRAGMENT_DATA))
14948c2ecf20Sopenharmony_ci		seq_puts(seq, ",fragment=data");
14958c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, FRAGMENT_METADATA))
14968c2ecf20Sopenharmony_ci		seq_puts(seq, ",fragment=metadata");
14978c2ecf20Sopenharmony_ci#endif
14988c2ecf20Sopenharmony_ci	if (btrfs_test_opt(info, REF_VERIFY))
14998c2ecf20Sopenharmony_ci		seq_puts(seq, ",ref_verify");
15008c2ecf20Sopenharmony_ci	seq_printf(seq, ",subvolid=%llu",
15018c2ecf20Sopenharmony_ci		  BTRFS_I(d_inode(dentry))->root->root_key.objectid);
15028c2ecf20Sopenharmony_ci	subvol_name = btrfs_get_subvol_name_from_objectid(info,
15038c2ecf20Sopenharmony_ci			BTRFS_I(d_inode(dentry))->root->root_key.objectid);
15048c2ecf20Sopenharmony_ci	if (!IS_ERR(subvol_name)) {
15058c2ecf20Sopenharmony_ci		seq_puts(seq, ",subvol=");
15068c2ecf20Sopenharmony_ci		seq_escape(seq, subvol_name, " \t\n\\");
15078c2ecf20Sopenharmony_ci		kfree(subvol_name);
15088c2ecf20Sopenharmony_ci	}
15098c2ecf20Sopenharmony_ci	return 0;
15108c2ecf20Sopenharmony_ci}
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_cistatic int btrfs_test_super(struct super_block *s, void *data)
15138c2ecf20Sopenharmony_ci{
15148c2ecf20Sopenharmony_ci	struct btrfs_fs_info *p = data;
15158c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(s);
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	return fs_info->fs_devices == p->fs_devices;
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_cistatic int btrfs_set_super(struct super_block *s, void *data)
15218c2ecf20Sopenharmony_ci{
15228c2ecf20Sopenharmony_ci	int err = set_anon_super(s, data);
15238c2ecf20Sopenharmony_ci	if (!err)
15248c2ecf20Sopenharmony_ci		s->s_fs_info = data;
15258c2ecf20Sopenharmony_ci	return err;
15268c2ecf20Sopenharmony_ci}
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci/*
15298c2ecf20Sopenharmony_ci * subvolumes are identified by ino 256
15308c2ecf20Sopenharmony_ci */
15318c2ecf20Sopenharmony_cistatic inline int is_subvolume_inode(struct inode *inode)
15328c2ecf20Sopenharmony_ci{
15338c2ecf20Sopenharmony_ci	if (inode && inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
15348c2ecf20Sopenharmony_ci		return 1;
15358c2ecf20Sopenharmony_ci	return 0;
15368c2ecf20Sopenharmony_ci}
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_cistatic struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
15398c2ecf20Sopenharmony_ci				   struct vfsmount *mnt)
15408c2ecf20Sopenharmony_ci{
15418c2ecf20Sopenharmony_ci	struct dentry *root;
15428c2ecf20Sopenharmony_ci	int ret;
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci	if (!subvol_name) {
15458c2ecf20Sopenharmony_ci		if (!subvol_objectid) {
15468c2ecf20Sopenharmony_ci			ret = get_default_subvol_objectid(btrfs_sb(mnt->mnt_sb),
15478c2ecf20Sopenharmony_ci							  &subvol_objectid);
15488c2ecf20Sopenharmony_ci			if (ret) {
15498c2ecf20Sopenharmony_ci				root = ERR_PTR(ret);
15508c2ecf20Sopenharmony_ci				goto out;
15518c2ecf20Sopenharmony_ci			}
15528c2ecf20Sopenharmony_ci		}
15538c2ecf20Sopenharmony_ci		subvol_name = btrfs_get_subvol_name_from_objectid(
15548c2ecf20Sopenharmony_ci					btrfs_sb(mnt->mnt_sb), subvol_objectid);
15558c2ecf20Sopenharmony_ci		if (IS_ERR(subvol_name)) {
15568c2ecf20Sopenharmony_ci			root = ERR_CAST(subvol_name);
15578c2ecf20Sopenharmony_ci			subvol_name = NULL;
15588c2ecf20Sopenharmony_ci			goto out;
15598c2ecf20Sopenharmony_ci		}
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	}
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	root = mount_subtree(mnt, subvol_name);
15648c2ecf20Sopenharmony_ci	/* mount_subtree() drops our reference on the vfsmount. */
15658c2ecf20Sopenharmony_ci	mnt = NULL;
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	if (!IS_ERR(root)) {
15688c2ecf20Sopenharmony_ci		struct super_block *s = root->d_sb;
15698c2ecf20Sopenharmony_ci		struct btrfs_fs_info *fs_info = btrfs_sb(s);
15708c2ecf20Sopenharmony_ci		struct inode *root_inode = d_inode(root);
15718c2ecf20Sopenharmony_ci		u64 root_objectid = BTRFS_I(root_inode)->root->root_key.objectid;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci		ret = 0;
15748c2ecf20Sopenharmony_ci		if (!is_subvolume_inode(root_inode)) {
15758c2ecf20Sopenharmony_ci			btrfs_err(fs_info, "'%s' is not a valid subvolume",
15768c2ecf20Sopenharmony_ci			       subvol_name);
15778c2ecf20Sopenharmony_ci			ret = -EINVAL;
15788c2ecf20Sopenharmony_ci		}
15798c2ecf20Sopenharmony_ci		if (subvol_objectid && root_objectid != subvol_objectid) {
15808c2ecf20Sopenharmony_ci			/*
15818c2ecf20Sopenharmony_ci			 * This will also catch a race condition where a
15828c2ecf20Sopenharmony_ci			 * subvolume which was passed by ID is renamed and
15838c2ecf20Sopenharmony_ci			 * another subvolume is renamed over the old location.
15848c2ecf20Sopenharmony_ci			 */
15858c2ecf20Sopenharmony_ci			btrfs_err(fs_info,
15868c2ecf20Sopenharmony_ci				  "subvol '%s' does not match subvolid %llu",
15878c2ecf20Sopenharmony_ci				  subvol_name, subvol_objectid);
15888c2ecf20Sopenharmony_ci			ret = -EINVAL;
15898c2ecf20Sopenharmony_ci		}
15908c2ecf20Sopenharmony_ci		if (ret) {
15918c2ecf20Sopenharmony_ci			dput(root);
15928c2ecf20Sopenharmony_ci			root = ERR_PTR(ret);
15938c2ecf20Sopenharmony_ci			deactivate_locked_super(s);
15948c2ecf20Sopenharmony_ci		}
15958c2ecf20Sopenharmony_ci	}
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ciout:
15988c2ecf20Sopenharmony_ci	mntput(mnt);
15998c2ecf20Sopenharmony_ci	kfree(subvol_name);
16008c2ecf20Sopenharmony_ci	return root;
16018c2ecf20Sopenharmony_ci}
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci/*
16048c2ecf20Sopenharmony_ci * Find a superblock for the given device / mount point.
16058c2ecf20Sopenharmony_ci *
16068c2ecf20Sopenharmony_ci * Note: This is based on mount_bdev from fs/super.c with a few additions
16078c2ecf20Sopenharmony_ci *       for multiple device setup.  Make sure to keep it in sync.
16088c2ecf20Sopenharmony_ci */
16098c2ecf20Sopenharmony_cistatic struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
16108c2ecf20Sopenharmony_ci		int flags, const char *device_name, void *data)
16118c2ecf20Sopenharmony_ci{
16128c2ecf20Sopenharmony_ci	struct block_device *bdev = NULL;
16138c2ecf20Sopenharmony_ci	struct super_block *s;
16148c2ecf20Sopenharmony_ci	struct btrfs_device *device = NULL;
16158c2ecf20Sopenharmony_ci	struct btrfs_fs_devices *fs_devices = NULL;
16168c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = NULL;
16178c2ecf20Sopenharmony_ci	void *new_sec_opts = NULL;
16188c2ecf20Sopenharmony_ci	fmode_t mode = FMODE_READ;
16198c2ecf20Sopenharmony_ci	int error = 0;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	if (!(flags & SB_RDONLY))
16228c2ecf20Sopenharmony_ci		mode |= FMODE_WRITE;
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	if (data) {
16258c2ecf20Sopenharmony_ci		error = security_sb_eat_lsm_opts(data, &new_sec_opts);
16268c2ecf20Sopenharmony_ci		if (error)
16278c2ecf20Sopenharmony_ci			return ERR_PTR(error);
16288c2ecf20Sopenharmony_ci	}
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	/*
16318c2ecf20Sopenharmony_ci	 * Setup a dummy root and fs_info for test/set super.  This is because
16328c2ecf20Sopenharmony_ci	 * we don't actually fill this stuff out until open_ctree, but we need
16338c2ecf20Sopenharmony_ci	 * then open_ctree will properly initialize the file system specific
16348c2ecf20Sopenharmony_ci	 * settings later.  btrfs_init_fs_info initializes the static elements
16358c2ecf20Sopenharmony_ci	 * of the fs_info (locks and such) to make cleanup easier if we find a
16368c2ecf20Sopenharmony_ci	 * superblock with our given fs_devices later on at sget() time.
16378c2ecf20Sopenharmony_ci	 */
16388c2ecf20Sopenharmony_ci	fs_info = kvzalloc(sizeof(struct btrfs_fs_info), GFP_KERNEL);
16398c2ecf20Sopenharmony_ci	if (!fs_info) {
16408c2ecf20Sopenharmony_ci		error = -ENOMEM;
16418c2ecf20Sopenharmony_ci		goto error_sec_opts;
16428c2ecf20Sopenharmony_ci	}
16438c2ecf20Sopenharmony_ci	btrfs_init_fs_info(fs_info);
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
16468c2ecf20Sopenharmony_ci	fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
16478c2ecf20Sopenharmony_ci	if (!fs_info->super_copy || !fs_info->super_for_commit) {
16488c2ecf20Sopenharmony_ci		error = -ENOMEM;
16498c2ecf20Sopenharmony_ci		goto error_fs_info;
16508c2ecf20Sopenharmony_ci	}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	mutex_lock(&uuid_mutex);
16538c2ecf20Sopenharmony_ci	error = btrfs_parse_device_options(data, mode, fs_type);
16548c2ecf20Sopenharmony_ci	if (error) {
16558c2ecf20Sopenharmony_ci		mutex_unlock(&uuid_mutex);
16568c2ecf20Sopenharmony_ci		goto error_fs_info;
16578c2ecf20Sopenharmony_ci	}
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	device = btrfs_scan_one_device(device_name, mode, fs_type);
16608c2ecf20Sopenharmony_ci	if (IS_ERR(device)) {
16618c2ecf20Sopenharmony_ci		mutex_unlock(&uuid_mutex);
16628c2ecf20Sopenharmony_ci		error = PTR_ERR(device);
16638c2ecf20Sopenharmony_ci		goto error_fs_info;
16648c2ecf20Sopenharmony_ci	}
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci	fs_devices = device->fs_devices;
16678c2ecf20Sopenharmony_ci	fs_info->fs_devices = fs_devices;
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	error = btrfs_open_devices(fs_devices, mode, fs_type);
16708c2ecf20Sopenharmony_ci	mutex_unlock(&uuid_mutex);
16718c2ecf20Sopenharmony_ci	if (error)
16728c2ecf20Sopenharmony_ci		goto error_fs_info;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	if (!(flags & SB_RDONLY) && fs_devices->rw_devices == 0) {
16758c2ecf20Sopenharmony_ci		error = -EACCES;
16768c2ecf20Sopenharmony_ci		goto error_close_devices;
16778c2ecf20Sopenharmony_ci	}
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci	bdev = fs_devices->latest_bdev;
16808c2ecf20Sopenharmony_ci	s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | SB_NOSEC,
16818c2ecf20Sopenharmony_ci		 fs_info);
16828c2ecf20Sopenharmony_ci	if (IS_ERR(s)) {
16838c2ecf20Sopenharmony_ci		error = PTR_ERR(s);
16848c2ecf20Sopenharmony_ci		goto error_close_devices;
16858c2ecf20Sopenharmony_ci	}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	if (s->s_root) {
16888c2ecf20Sopenharmony_ci		btrfs_close_devices(fs_devices);
16898c2ecf20Sopenharmony_ci		btrfs_free_fs_info(fs_info);
16908c2ecf20Sopenharmony_ci		if ((flags ^ s->s_flags) & SB_RDONLY)
16918c2ecf20Sopenharmony_ci			error = -EBUSY;
16928c2ecf20Sopenharmony_ci	} else {
16938c2ecf20Sopenharmony_ci		snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
16948c2ecf20Sopenharmony_ci		btrfs_sb(s)->bdev_holder = fs_type;
16958c2ecf20Sopenharmony_ci		error = btrfs_fill_super(s, fs_devices, data);
16968c2ecf20Sopenharmony_ci	}
16978c2ecf20Sopenharmony_ci	if (!error)
16988c2ecf20Sopenharmony_ci		error = security_sb_set_mnt_opts(s, new_sec_opts, 0, NULL);
16998c2ecf20Sopenharmony_ci	security_free_mnt_opts(&new_sec_opts);
17008c2ecf20Sopenharmony_ci	if (error) {
17018c2ecf20Sopenharmony_ci		deactivate_locked_super(s);
17028c2ecf20Sopenharmony_ci		return ERR_PTR(error);
17038c2ecf20Sopenharmony_ci	}
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci	return dget(s->s_root);
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_cierror_close_devices:
17088c2ecf20Sopenharmony_ci	btrfs_close_devices(fs_devices);
17098c2ecf20Sopenharmony_cierror_fs_info:
17108c2ecf20Sopenharmony_ci	btrfs_free_fs_info(fs_info);
17118c2ecf20Sopenharmony_cierror_sec_opts:
17128c2ecf20Sopenharmony_ci	security_free_mnt_opts(&new_sec_opts);
17138c2ecf20Sopenharmony_ci	return ERR_PTR(error);
17148c2ecf20Sopenharmony_ci}
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci/*
17178c2ecf20Sopenharmony_ci * Mount function which is called by VFS layer.
17188c2ecf20Sopenharmony_ci *
17198c2ecf20Sopenharmony_ci * In order to allow mounting a subvolume directly, btrfs uses mount_subtree()
17208c2ecf20Sopenharmony_ci * which needs vfsmount* of device's root (/).  This means device's root has to
17218c2ecf20Sopenharmony_ci * be mounted internally in any case.
17228c2ecf20Sopenharmony_ci *
17238c2ecf20Sopenharmony_ci * Operation flow:
17248c2ecf20Sopenharmony_ci *   1. Parse subvol id related options for later use in mount_subvol().
17258c2ecf20Sopenharmony_ci *
17268c2ecf20Sopenharmony_ci *   2. Mount device's root (/) by calling vfs_kern_mount().
17278c2ecf20Sopenharmony_ci *
17288c2ecf20Sopenharmony_ci *      NOTE: vfs_kern_mount() is used by VFS to call btrfs_mount() in the
17298c2ecf20Sopenharmony_ci *      first place. In order to avoid calling btrfs_mount() again, we use
17308c2ecf20Sopenharmony_ci *      different file_system_type which is not registered to VFS by
17318c2ecf20Sopenharmony_ci *      register_filesystem() (btrfs_root_fs_type). As a result,
17328c2ecf20Sopenharmony_ci *      btrfs_mount_root() is called. The return value will be used by
17338c2ecf20Sopenharmony_ci *      mount_subtree() in mount_subvol().
17348c2ecf20Sopenharmony_ci *
17358c2ecf20Sopenharmony_ci *   3. Call mount_subvol() to get the dentry of subvolume. Since there is
17368c2ecf20Sopenharmony_ci *      "btrfs subvolume set-default", mount_subvol() is called always.
17378c2ecf20Sopenharmony_ci */
17388c2ecf20Sopenharmony_cistatic struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
17398c2ecf20Sopenharmony_ci		const char *device_name, void *data)
17408c2ecf20Sopenharmony_ci{
17418c2ecf20Sopenharmony_ci	struct vfsmount *mnt_root;
17428c2ecf20Sopenharmony_ci	struct dentry *root;
17438c2ecf20Sopenharmony_ci	char *subvol_name = NULL;
17448c2ecf20Sopenharmony_ci	u64 subvol_objectid = 0;
17458c2ecf20Sopenharmony_ci	int error = 0;
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci	error = btrfs_parse_subvol_options(data, &subvol_name,
17488c2ecf20Sopenharmony_ci					&subvol_objectid);
17498c2ecf20Sopenharmony_ci	if (error) {
17508c2ecf20Sopenharmony_ci		kfree(subvol_name);
17518c2ecf20Sopenharmony_ci		return ERR_PTR(error);
17528c2ecf20Sopenharmony_ci	}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci	/* mount device's root (/) */
17558c2ecf20Sopenharmony_ci	mnt_root = vfs_kern_mount(&btrfs_root_fs_type, flags, device_name, data);
17568c2ecf20Sopenharmony_ci	if (PTR_ERR_OR_ZERO(mnt_root) == -EBUSY) {
17578c2ecf20Sopenharmony_ci		if (flags & SB_RDONLY) {
17588c2ecf20Sopenharmony_ci			mnt_root = vfs_kern_mount(&btrfs_root_fs_type,
17598c2ecf20Sopenharmony_ci				flags & ~SB_RDONLY, device_name, data);
17608c2ecf20Sopenharmony_ci		} else {
17618c2ecf20Sopenharmony_ci			mnt_root = vfs_kern_mount(&btrfs_root_fs_type,
17628c2ecf20Sopenharmony_ci				flags | SB_RDONLY, device_name, data);
17638c2ecf20Sopenharmony_ci			if (IS_ERR(mnt_root)) {
17648c2ecf20Sopenharmony_ci				root = ERR_CAST(mnt_root);
17658c2ecf20Sopenharmony_ci				kfree(subvol_name);
17668c2ecf20Sopenharmony_ci				goto out;
17678c2ecf20Sopenharmony_ci			}
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci			down_write(&mnt_root->mnt_sb->s_umount);
17708c2ecf20Sopenharmony_ci			error = btrfs_remount(mnt_root->mnt_sb, &flags, NULL);
17718c2ecf20Sopenharmony_ci			up_write(&mnt_root->mnt_sb->s_umount);
17728c2ecf20Sopenharmony_ci			if (error < 0) {
17738c2ecf20Sopenharmony_ci				root = ERR_PTR(error);
17748c2ecf20Sopenharmony_ci				mntput(mnt_root);
17758c2ecf20Sopenharmony_ci				kfree(subvol_name);
17768c2ecf20Sopenharmony_ci				goto out;
17778c2ecf20Sopenharmony_ci			}
17788c2ecf20Sopenharmony_ci		}
17798c2ecf20Sopenharmony_ci	}
17808c2ecf20Sopenharmony_ci	if (IS_ERR(mnt_root)) {
17818c2ecf20Sopenharmony_ci		root = ERR_CAST(mnt_root);
17828c2ecf20Sopenharmony_ci		kfree(subvol_name);
17838c2ecf20Sopenharmony_ci		goto out;
17848c2ecf20Sopenharmony_ci	}
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci	/* mount_subvol() will free subvol_name and mnt_root */
17878c2ecf20Sopenharmony_ci	root = mount_subvol(subvol_name, subvol_objectid, mnt_root);
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ciout:
17908c2ecf20Sopenharmony_ci	return root;
17918c2ecf20Sopenharmony_ci}
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_cistatic void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
17948c2ecf20Sopenharmony_ci				     u32 new_pool_size, u32 old_pool_size)
17958c2ecf20Sopenharmony_ci{
17968c2ecf20Sopenharmony_ci	if (new_pool_size == old_pool_size)
17978c2ecf20Sopenharmony_ci		return;
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci	fs_info->thread_pool_size = new_pool_size;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	btrfs_info(fs_info, "resize thread pool %d -> %d",
18028c2ecf20Sopenharmony_ci	       old_pool_size, new_pool_size);
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->workers, new_pool_size);
18058c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->delalloc_workers, new_pool_size);
18068c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->caching_workers, new_pool_size);
18078c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->endio_workers, new_pool_size);
18088c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->endio_meta_workers, new_pool_size);
18098c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->endio_meta_write_workers,
18108c2ecf20Sopenharmony_ci				new_pool_size);
18118c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->endio_write_workers, new_pool_size);
18128c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->endio_freespace_worker, new_pool_size);
18138c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->delayed_workers, new_pool_size);
18148c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->readahead_workers, new_pool_size);
18158c2ecf20Sopenharmony_ci	btrfs_workqueue_set_max(fs_info->scrub_wr_completion_workers,
18168c2ecf20Sopenharmony_ci				new_pool_size);
18178c2ecf20Sopenharmony_ci}
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_cistatic inline void btrfs_remount_begin(struct btrfs_fs_info *fs_info,
18208c2ecf20Sopenharmony_ci				       unsigned long old_opts, int flags)
18218c2ecf20Sopenharmony_ci{
18228c2ecf20Sopenharmony_ci	if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
18238c2ecf20Sopenharmony_ci	    (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) ||
18248c2ecf20Sopenharmony_ci	     (flags & SB_RDONLY))) {
18258c2ecf20Sopenharmony_ci		/* wait for any defraggers to finish */
18268c2ecf20Sopenharmony_ci		wait_event(fs_info->transaction_wait,
18278c2ecf20Sopenharmony_ci			   (atomic_read(&fs_info->defrag_running) == 0));
18288c2ecf20Sopenharmony_ci		if (flags & SB_RDONLY)
18298c2ecf20Sopenharmony_ci			sync_filesystem(fs_info->sb);
18308c2ecf20Sopenharmony_ci	}
18318c2ecf20Sopenharmony_ci}
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_cistatic inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,
18348c2ecf20Sopenharmony_ci					 unsigned long old_opts)
18358c2ecf20Sopenharmony_ci{
18368c2ecf20Sopenharmony_ci	/*
18378c2ecf20Sopenharmony_ci	 * We need to cleanup all defragable inodes if the autodefragment is
18388c2ecf20Sopenharmony_ci	 * close or the filesystem is read only.
18398c2ecf20Sopenharmony_ci	 */
18408c2ecf20Sopenharmony_ci	if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
18418c2ecf20Sopenharmony_ci	    (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) || sb_rdonly(fs_info->sb))) {
18428c2ecf20Sopenharmony_ci		btrfs_cleanup_defrag_inodes(fs_info);
18438c2ecf20Sopenharmony_ci	}
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci	/* If we toggled discard async */
18468c2ecf20Sopenharmony_ci	if (!btrfs_raw_test_opt(old_opts, DISCARD_ASYNC) &&
18478c2ecf20Sopenharmony_ci	    btrfs_test_opt(fs_info, DISCARD_ASYNC))
18488c2ecf20Sopenharmony_ci		btrfs_discard_resume(fs_info);
18498c2ecf20Sopenharmony_ci	else if (btrfs_raw_test_opt(old_opts, DISCARD_ASYNC) &&
18508c2ecf20Sopenharmony_ci		 !btrfs_test_opt(fs_info, DISCARD_ASYNC))
18518c2ecf20Sopenharmony_ci		btrfs_discard_cleanup(fs_info);
18528c2ecf20Sopenharmony_ci}
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_cistatic int btrfs_remount(struct super_block *sb, int *flags, char *data)
18558c2ecf20Sopenharmony_ci{
18568c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
18578c2ecf20Sopenharmony_ci	struct btrfs_root *root = fs_info->tree_root;
18588c2ecf20Sopenharmony_ci	unsigned old_flags = sb->s_flags;
18598c2ecf20Sopenharmony_ci	unsigned long old_opts = fs_info->mount_opt;
18608c2ecf20Sopenharmony_ci	unsigned long old_compress_type = fs_info->compress_type;
18618c2ecf20Sopenharmony_ci	u64 old_max_inline = fs_info->max_inline;
18628c2ecf20Sopenharmony_ci	u32 old_thread_pool_size = fs_info->thread_pool_size;
18638c2ecf20Sopenharmony_ci	u32 old_metadata_ratio = fs_info->metadata_ratio;
18648c2ecf20Sopenharmony_ci	int ret;
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	sync_filesystem(sb);
18678c2ecf20Sopenharmony_ci	set_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	if (data) {
18708c2ecf20Sopenharmony_ci		void *new_sec_opts = NULL;
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ci		ret = security_sb_eat_lsm_opts(data, &new_sec_opts);
18738c2ecf20Sopenharmony_ci		if (!ret)
18748c2ecf20Sopenharmony_ci			ret = security_sb_remount(sb, new_sec_opts);
18758c2ecf20Sopenharmony_ci		security_free_mnt_opts(&new_sec_opts);
18768c2ecf20Sopenharmony_ci		if (ret)
18778c2ecf20Sopenharmony_ci			goto restore;
18788c2ecf20Sopenharmony_ci	}
18798c2ecf20Sopenharmony_ci
18808c2ecf20Sopenharmony_ci	ret = btrfs_parse_options(fs_info, data, *flags);
18818c2ecf20Sopenharmony_ci	if (ret)
18828c2ecf20Sopenharmony_ci		goto restore;
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci	btrfs_remount_begin(fs_info, old_opts, *flags);
18858c2ecf20Sopenharmony_ci	btrfs_resize_thread_pool(fs_info,
18868c2ecf20Sopenharmony_ci		fs_info->thread_pool_size, old_thread_pool_size);
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ci	if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb))
18898c2ecf20Sopenharmony_ci		goto out;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	if (*flags & SB_RDONLY) {
18928c2ecf20Sopenharmony_ci		/*
18938c2ecf20Sopenharmony_ci		 * this also happens on 'umount -rf' or on shutdown, when
18948c2ecf20Sopenharmony_ci		 * the filesystem is busy.
18958c2ecf20Sopenharmony_ci		 */
18968c2ecf20Sopenharmony_ci		cancel_work_sync(&fs_info->async_reclaim_work);
18978c2ecf20Sopenharmony_ci		cancel_work_sync(&fs_info->async_data_reclaim_work);
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci		btrfs_discard_cleanup(fs_info);
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci		/* wait for the uuid_scan task to finish */
19028c2ecf20Sopenharmony_ci		down(&fs_info->uuid_tree_rescan_sem);
19038c2ecf20Sopenharmony_ci		/* avoid complains from lockdep et al. */
19048c2ecf20Sopenharmony_ci		up(&fs_info->uuid_tree_rescan_sem);
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci		sb->s_flags |= SB_RDONLY;
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci		/*
19098c2ecf20Sopenharmony_ci		 * Setting SB_RDONLY will put the cleaner thread to
19108c2ecf20Sopenharmony_ci		 * sleep at the next loop if it's already active.
19118c2ecf20Sopenharmony_ci		 * If it's already asleep, we'll leave unused block
19128c2ecf20Sopenharmony_ci		 * groups on disk until we're mounted read-write again
19138c2ecf20Sopenharmony_ci		 * unless we clean them up here.
19148c2ecf20Sopenharmony_ci		 */
19158c2ecf20Sopenharmony_ci		btrfs_delete_unused_bgs(fs_info);
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci		btrfs_dev_replace_suspend_for_unmount(fs_info);
19188c2ecf20Sopenharmony_ci		btrfs_scrub_cancel(fs_info);
19198c2ecf20Sopenharmony_ci		btrfs_pause_balance(fs_info);
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci		/*
19228c2ecf20Sopenharmony_ci		 * Pause the qgroup rescan worker if it is running. We don't want
19238c2ecf20Sopenharmony_ci		 * it to be still running after we are in RO mode, as after that,
19248c2ecf20Sopenharmony_ci		 * by the time we unmount, it might have left a transaction open,
19258c2ecf20Sopenharmony_ci		 * so we would leak the transaction and/or crash.
19268c2ecf20Sopenharmony_ci		 */
19278c2ecf20Sopenharmony_ci		btrfs_qgroup_wait_for_completion(fs_info, false);
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_ci		ret = btrfs_commit_super(fs_info);
19308c2ecf20Sopenharmony_ci		if (ret)
19318c2ecf20Sopenharmony_ci			goto restore;
19328c2ecf20Sopenharmony_ci	} else {
19338c2ecf20Sopenharmony_ci		if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
19348c2ecf20Sopenharmony_ci			btrfs_err(fs_info,
19358c2ecf20Sopenharmony_ci				"Remounting read-write after error is not allowed");
19368c2ecf20Sopenharmony_ci			ret = -EINVAL;
19378c2ecf20Sopenharmony_ci			goto restore;
19388c2ecf20Sopenharmony_ci		}
19398c2ecf20Sopenharmony_ci		if (fs_info->fs_devices->rw_devices == 0) {
19408c2ecf20Sopenharmony_ci			ret = -EACCES;
19418c2ecf20Sopenharmony_ci			goto restore;
19428c2ecf20Sopenharmony_ci		}
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci		if (!btrfs_check_rw_degradable(fs_info, NULL)) {
19458c2ecf20Sopenharmony_ci			btrfs_warn(fs_info,
19468c2ecf20Sopenharmony_ci		"too many missing devices, writable remount is not allowed");
19478c2ecf20Sopenharmony_ci			ret = -EACCES;
19488c2ecf20Sopenharmony_ci			goto restore;
19498c2ecf20Sopenharmony_ci		}
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci		if (btrfs_super_log_root(fs_info->super_copy) != 0) {
19528c2ecf20Sopenharmony_ci			btrfs_warn(fs_info,
19538c2ecf20Sopenharmony_ci		"mount required to replay tree-log, cannot remount read-write");
19548c2ecf20Sopenharmony_ci			ret = -EINVAL;
19558c2ecf20Sopenharmony_ci			goto restore;
19568c2ecf20Sopenharmony_ci		}
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci		ret = btrfs_cleanup_fs_roots(fs_info);
19598c2ecf20Sopenharmony_ci		if (ret)
19608c2ecf20Sopenharmony_ci			goto restore;
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci		/* recover relocation */
19638c2ecf20Sopenharmony_ci		mutex_lock(&fs_info->cleaner_mutex);
19648c2ecf20Sopenharmony_ci		ret = btrfs_recover_relocation(root);
19658c2ecf20Sopenharmony_ci		mutex_unlock(&fs_info->cleaner_mutex);
19668c2ecf20Sopenharmony_ci		if (ret)
19678c2ecf20Sopenharmony_ci			goto restore;
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_ci		ret = btrfs_resume_balance_async(fs_info);
19708c2ecf20Sopenharmony_ci		if (ret)
19718c2ecf20Sopenharmony_ci			goto restore;
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci		ret = btrfs_resume_dev_replace_async(fs_info);
19748c2ecf20Sopenharmony_ci		if (ret) {
19758c2ecf20Sopenharmony_ci			btrfs_warn(fs_info, "failed to resume dev_replace");
19768c2ecf20Sopenharmony_ci			goto restore;
19778c2ecf20Sopenharmony_ci		}
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci		btrfs_qgroup_rescan_resume(fs_info);
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci		if (!fs_info->uuid_root) {
19828c2ecf20Sopenharmony_ci			btrfs_info(fs_info, "creating UUID tree");
19838c2ecf20Sopenharmony_ci			ret = btrfs_create_uuid_tree(fs_info);
19848c2ecf20Sopenharmony_ci			if (ret) {
19858c2ecf20Sopenharmony_ci				btrfs_warn(fs_info,
19868c2ecf20Sopenharmony_ci					   "failed to create the UUID tree %d",
19878c2ecf20Sopenharmony_ci					   ret);
19888c2ecf20Sopenharmony_ci				goto restore;
19898c2ecf20Sopenharmony_ci			}
19908c2ecf20Sopenharmony_ci		}
19918c2ecf20Sopenharmony_ci		sb->s_flags &= ~SB_RDONLY;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci		set_bit(BTRFS_FS_OPEN, &fs_info->flags);
19948c2ecf20Sopenharmony_ci	}
19958c2ecf20Sopenharmony_ciout:
19968c2ecf20Sopenharmony_ci	/*
19978c2ecf20Sopenharmony_ci	 * We need to set SB_I_VERSION here otherwise it'll get cleared by VFS,
19988c2ecf20Sopenharmony_ci	 * since the absence of the flag means it can be toggled off by remount.
19998c2ecf20Sopenharmony_ci	 */
20008c2ecf20Sopenharmony_ci	*flags |= SB_I_VERSION;
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci	wake_up_process(fs_info->transaction_kthread);
20038c2ecf20Sopenharmony_ci	btrfs_remount_cleanup(fs_info, old_opts);
20048c2ecf20Sopenharmony_ci	clear_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci	return 0;
20078c2ecf20Sopenharmony_ci
20088c2ecf20Sopenharmony_cirestore:
20098c2ecf20Sopenharmony_ci	/* We've hit an error - don't reset SB_RDONLY */
20108c2ecf20Sopenharmony_ci	if (sb_rdonly(sb))
20118c2ecf20Sopenharmony_ci		old_flags |= SB_RDONLY;
20128c2ecf20Sopenharmony_ci	sb->s_flags = old_flags;
20138c2ecf20Sopenharmony_ci	fs_info->mount_opt = old_opts;
20148c2ecf20Sopenharmony_ci	fs_info->compress_type = old_compress_type;
20158c2ecf20Sopenharmony_ci	fs_info->max_inline = old_max_inline;
20168c2ecf20Sopenharmony_ci	btrfs_resize_thread_pool(fs_info,
20178c2ecf20Sopenharmony_ci		old_thread_pool_size, fs_info->thread_pool_size);
20188c2ecf20Sopenharmony_ci	fs_info->metadata_ratio = old_metadata_ratio;
20198c2ecf20Sopenharmony_ci	btrfs_remount_cleanup(fs_info, old_opts);
20208c2ecf20Sopenharmony_ci	clear_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	return ret;
20238c2ecf20Sopenharmony_ci}
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci/* Used to sort the devices by max_avail(descending sort) */
20268c2ecf20Sopenharmony_cistatic inline int btrfs_cmp_device_free_bytes(const void *dev_info1,
20278c2ecf20Sopenharmony_ci				       const void *dev_info2)
20288c2ecf20Sopenharmony_ci{
20298c2ecf20Sopenharmony_ci	if (((struct btrfs_device_info *)dev_info1)->max_avail >
20308c2ecf20Sopenharmony_ci	    ((struct btrfs_device_info *)dev_info2)->max_avail)
20318c2ecf20Sopenharmony_ci		return -1;
20328c2ecf20Sopenharmony_ci	else if (((struct btrfs_device_info *)dev_info1)->max_avail <
20338c2ecf20Sopenharmony_ci		 ((struct btrfs_device_info *)dev_info2)->max_avail)
20348c2ecf20Sopenharmony_ci		return 1;
20358c2ecf20Sopenharmony_ci	else
20368c2ecf20Sopenharmony_ci	return 0;
20378c2ecf20Sopenharmony_ci}
20388c2ecf20Sopenharmony_ci
20398c2ecf20Sopenharmony_ci/*
20408c2ecf20Sopenharmony_ci * sort the devices by max_avail, in which max free extent size of each device
20418c2ecf20Sopenharmony_ci * is stored.(Descending Sort)
20428c2ecf20Sopenharmony_ci */
20438c2ecf20Sopenharmony_cistatic inline void btrfs_descending_sort_devices(
20448c2ecf20Sopenharmony_ci					struct btrfs_device_info *devices,
20458c2ecf20Sopenharmony_ci					size_t nr_devices)
20468c2ecf20Sopenharmony_ci{
20478c2ecf20Sopenharmony_ci	sort(devices, nr_devices, sizeof(struct btrfs_device_info),
20488c2ecf20Sopenharmony_ci	     btrfs_cmp_device_free_bytes, NULL);
20498c2ecf20Sopenharmony_ci}
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci/*
20528c2ecf20Sopenharmony_ci * The helper to calc the free space on the devices that can be used to store
20538c2ecf20Sopenharmony_ci * file data.
20548c2ecf20Sopenharmony_ci */
20558c2ecf20Sopenharmony_cistatic inline int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info,
20568c2ecf20Sopenharmony_ci					      u64 *free_bytes)
20578c2ecf20Sopenharmony_ci{
20588c2ecf20Sopenharmony_ci	struct btrfs_device_info *devices_info;
20598c2ecf20Sopenharmony_ci	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
20608c2ecf20Sopenharmony_ci	struct btrfs_device *device;
20618c2ecf20Sopenharmony_ci	u64 type;
20628c2ecf20Sopenharmony_ci	u64 avail_space;
20638c2ecf20Sopenharmony_ci	u64 min_stripe_size;
20648c2ecf20Sopenharmony_ci	int num_stripes = 1;
20658c2ecf20Sopenharmony_ci	int i = 0, nr_devices;
20668c2ecf20Sopenharmony_ci	const struct btrfs_raid_attr *rattr;
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci	/*
20698c2ecf20Sopenharmony_ci	 * We aren't under the device list lock, so this is racy-ish, but good
20708c2ecf20Sopenharmony_ci	 * enough for our purposes.
20718c2ecf20Sopenharmony_ci	 */
20728c2ecf20Sopenharmony_ci	nr_devices = fs_info->fs_devices->open_devices;
20738c2ecf20Sopenharmony_ci	if (!nr_devices) {
20748c2ecf20Sopenharmony_ci		smp_mb();
20758c2ecf20Sopenharmony_ci		nr_devices = fs_info->fs_devices->open_devices;
20768c2ecf20Sopenharmony_ci		ASSERT(nr_devices);
20778c2ecf20Sopenharmony_ci		if (!nr_devices) {
20788c2ecf20Sopenharmony_ci			*free_bytes = 0;
20798c2ecf20Sopenharmony_ci			return 0;
20808c2ecf20Sopenharmony_ci		}
20818c2ecf20Sopenharmony_ci	}
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci	devices_info = kmalloc_array(nr_devices, sizeof(*devices_info),
20848c2ecf20Sopenharmony_ci			       GFP_KERNEL);
20858c2ecf20Sopenharmony_ci	if (!devices_info)
20868c2ecf20Sopenharmony_ci		return -ENOMEM;
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ci	/* calc min stripe number for data space allocation */
20898c2ecf20Sopenharmony_ci	type = btrfs_data_alloc_profile(fs_info);
20908c2ecf20Sopenharmony_ci	rattr = &btrfs_raid_array[btrfs_bg_flags_to_raid_index(type)];
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_ci	if (type & BTRFS_BLOCK_GROUP_RAID0)
20938c2ecf20Sopenharmony_ci		num_stripes = nr_devices;
20948c2ecf20Sopenharmony_ci	else if (type & BTRFS_BLOCK_GROUP_RAID1)
20958c2ecf20Sopenharmony_ci		num_stripes = 2;
20968c2ecf20Sopenharmony_ci	else if (type & BTRFS_BLOCK_GROUP_RAID1C3)
20978c2ecf20Sopenharmony_ci		num_stripes = 3;
20988c2ecf20Sopenharmony_ci	else if (type & BTRFS_BLOCK_GROUP_RAID1C4)
20998c2ecf20Sopenharmony_ci		num_stripes = 4;
21008c2ecf20Sopenharmony_ci	else if (type & BTRFS_BLOCK_GROUP_RAID10)
21018c2ecf20Sopenharmony_ci		num_stripes = 4;
21028c2ecf20Sopenharmony_ci
21038c2ecf20Sopenharmony_ci	/* Adjust for more than 1 stripe per device */
21048c2ecf20Sopenharmony_ci	min_stripe_size = rattr->dev_stripes * BTRFS_STRIPE_LEN;
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	rcu_read_lock();
21078c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(device, &fs_devices->devices, dev_list) {
21088c2ecf20Sopenharmony_ci		if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA,
21098c2ecf20Sopenharmony_ci						&device->dev_state) ||
21108c2ecf20Sopenharmony_ci		    !device->bdev ||
21118c2ecf20Sopenharmony_ci		    test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state))
21128c2ecf20Sopenharmony_ci			continue;
21138c2ecf20Sopenharmony_ci
21148c2ecf20Sopenharmony_ci		if (i >= nr_devices)
21158c2ecf20Sopenharmony_ci			break;
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci		avail_space = device->total_bytes - device->bytes_used;
21188c2ecf20Sopenharmony_ci
21198c2ecf20Sopenharmony_ci		/* align with stripe_len */
21208c2ecf20Sopenharmony_ci		avail_space = rounddown(avail_space, BTRFS_STRIPE_LEN);
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci		/*
21238c2ecf20Sopenharmony_ci		 * In order to avoid overwriting the superblock on the drive,
21248c2ecf20Sopenharmony_ci		 * btrfs starts at an offset of at least 1MB when doing chunk
21258c2ecf20Sopenharmony_ci		 * allocation.
21268c2ecf20Sopenharmony_ci		 *
21278c2ecf20Sopenharmony_ci		 * This ensures we have at least min_stripe_size free space
21288c2ecf20Sopenharmony_ci		 * after excluding 1MB.
21298c2ecf20Sopenharmony_ci		 */
21308c2ecf20Sopenharmony_ci		if (avail_space <= SZ_1M + min_stripe_size)
21318c2ecf20Sopenharmony_ci			continue;
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci		avail_space -= SZ_1M;
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ci		devices_info[i].dev = device;
21368c2ecf20Sopenharmony_ci		devices_info[i].max_avail = avail_space;
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci		i++;
21398c2ecf20Sopenharmony_ci	}
21408c2ecf20Sopenharmony_ci	rcu_read_unlock();
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_ci	nr_devices = i;
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	btrfs_descending_sort_devices(devices_info, nr_devices);
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	i = nr_devices - 1;
21478c2ecf20Sopenharmony_ci	avail_space = 0;
21488c2ecf20Sopenharmony_ci	while (nr_devices >= rattr->devs_min) {
21498c2ecf20Sopenharmony_ci		num_stripes = min(num_stripes, nr_devices);
21508c2ecf20Sopenharmony_ci
21518c2ecf20Sopenharmony_ci		if (devices_info[i].max_avail >= min_stripe_size) {
21528c2ecf20Sopenharmony_ci			int j;
21538c2ecf20Sopenharmony_ci			u64 alloc_size;
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci			avail_space += devices_info[i].max_avail * num_stripes;
21568c2ecf20Sopenharmony_ci			alloc_size = devices_info[i].max_avail;
21578c2ecf20Sopenharmony_ci			for (j = i + 1 - num_stripes; j <= i; j++)
21588c2ecf20Sopenharmony_ci				devices_info[j].max_avail -= alloc_size;
21598c2ecf20Sopenharmony_ci		}
21608c2ecf20Sopenharmony_ci		i--;
21618c2ecf20Sopenharmony_ci		nr_devices--;
21628c2ecf20Sopenharmony_ci	}
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_ci	kfree(devices_info);
21658c2ecf20Sopenharmony_ci	*free_bytes = avail_space;
21668c2ecf20Sopenharmony_ci	return 0;
21678c2ecf20Sopenharmony_ci}
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci/*
21708c2ecf20Sopenharmony_ci * Calculate numbers for 'df', pessimistic in case of mixed raid profiles.
21718c2ecf20Sopenharmony_ci *
21728c2ecf20Sopenharmony_ci * If there's a redundant raid level at DATA block groups, use the respective
21738c2ecf20Sopenharmony_ci * multiplier to scale the sizes.
21748c2ecf20Sopenharmony_ci *
21758c2ecf20Sopenharmony_ci * Unused device space usage is based on simulating the chunk allocator
21768c2ecf20Sopenharmony_ci * algorithm that respects the device sizes and order of allocations.  This is
21778c2ecf20Sopenharmony_ci * a close approximation of the actual use but there are other factors that may
21788c2ecf20Sopenharmony_ci * change the result (like a new metadata chunk).
21798c2ecf20Sopenharmony_ci *
21808c2ecf20Sopenharmony_ci * If metadata is exhausted, f_bavail will be 0.
21818c2ecf20Sopenharmony_ci */
21828c2ecf20Sopenharmony_cistatic int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
21838c2ecf20Sopenharmony_ci{
21848c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb);
21858c2ecf20Sopenharmony_ci	struct btrfs_super_block *disk_super = fs_info->super_copy;
21868c2ecf20Sopenharmony_ci	struct btrfs_space_info *found;
21878c2ecf20Sopenharmony_ci	u64 total_used = 0;
21888c2ecf20Sopenharmony_ci	u64 total_free_data = 0;
21898c2ecf20Sopenharmony_ci	u64 total_free_meta = 0;
21908c2ecf20Sopenharmony_ci	int bits = dentry->d_sb->s_blocksize_bits;
21918c2ecf20Sopenharmony_ci	__be32 *fsid = (__be32 *)fs_info->fs_devices->fsid;
21928c2ecf20Sopenharmony_ci	unsigned factor = 1;
21938c2ecf20Sopenharmony_ci	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
21948c2ecf20Sopenharmony_ci	int ret;
21958c2ecf20Sopenharmony_ci	u64 thresh = 0;
21968c2ecf20Sopenharmony_ci	int mixed = 0;
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci	list_for_each_entry(found, &fs_info->space_info, list) {
21998c2ecf20Sopenharmony_ci		if (found->flags & BTRFS_BLOCK_GROUP_DATA) {
22008c2ecf20Sopenharmony_ci			int i;
22018c2ecf20Sopenharmony_ci
22028c2ecf20Sopenharmony_ci			total_free_data += found->disk_total - found->disk_used;
22038c2ecf20Sopenharmony_ci			total_free_data -=
22048c2ecf20Sopenharmony_ci				btrfs_account_ro_block_groups_free_space(found);
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ci			for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
22078c2ecf20Sopenharmony_ci				if (!list_empty(&found->block_groups[i]))
22088c2ecf20Sopenharmony_ci					factor = btrfs_bg_type_to_factor(
22098c2ecf20Sopenharmony_ci						btrfs_raid_array[i].bg_flag);
22108c2ecf20Sopenharmony_ci			}
22118c2ecf20Sopenharmony_ci		}
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci		/*
22148c2ecf20Sopenharmony_ci		 * Metadata in mixed block goup profiles are accounted in data
22158c2ecf20Sopenharmony_ci		 */
22168c2ecf20Sopenharmony_ci		if (!mixed && found->flags & BTRFS_BLOCK_GROUP_METADATA) {
22178c2ecf20Sopenharmony_ci			if (found->flags & BTRFS_BLOCK_GROUP_DATA)
22188c2ecf20Sopenharmony_ci				mixed = 1;
22198c2ecf20Sopenharmony_ci			else
22208c2ecf20Sopenharmony_ci				total_free_meta += found->disk_total -
22218c2ecf20Sopenharmony_ci					found->disk_used;
22228c2ecf20Sopenharmony_ci		}
22238c2ecf20Sopenharmony_ci
22248c2ecf20Sopenharmony_ci		total_used += found->disk_used;
22258c2ecf20Sopenharmony_ci	}
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci	buf->f_blocks = div_u64(btrfs_super_total_bytes(disk_super), factor);
22288c2ecf20Sopenharmony_ci	buf->f_blocks >>= bits;
22298c2ecf20Sopenharmony_ci	buf->f_bfree = buf->f_blocks - (div_u64(total_used, factor) >> bits);
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_ci	/* Account global block reserve as used, it's in logical size already */
22328c2ecf20Sopenharmony_ci	spin_lock(&block_rsv->lock);
22338c2ecf20Sopenharmony_ci	/* Mixed block groups accounting is not byte-accurate, avoid overflow */
22348c2ecf20Sopenharmony_ci	if (buf->f_bfree >= block_rsv->size >> bits)
22358c2ecf20Sopenharmony_ci		buf->f_bfree -= block_rsv->size >> bits;
22368c2ecf20Sopenharmony_ci	else
22378c2ecf20Sopenharmony_ci		buf->f_bfree = 0;
22388c2ecf20Sopenharmony_ci	spin_unlock(&block_rsv->lock);
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci	buf->f_bavail = div_u64(total_free_data, factor);
22418c2ecf20Sopenharmony_ci	ret = btrfs_calc_avail_data_space(fs_info, &total_free_data);
22428c2ecf20Sopenharmony_ci	if (ret)
22438c2ecf20Sopenharmony_ci		return ret;
22448c2ecf20Sopenharmony_ci	buf->f_bavail += div_u64(total_free_data, factor);
22458c2ecf20Sopenharmony_ci	buf->f_bavail = buf->f_bavail >> bits;
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	/*
22488c2ecf20Sopenharmony_ci	 * We calculate the remaining metadata space minus global reserve. If
22498c2ecf20Sopenharmony_ci	 * this is (supposedly) smaller than zero, there's no space. But this
22508c2ecf20Sopenharmony_ci	 * does not hold in practice, the exhausted state happens where's still
22518c2ecf20Sopenharmony_ci	 * some positive delta. So we apply some guesswork and compare the
22528c2ecf20Sopenharmony_ci	 * delta to a 4M threshold.  (Practically observed delta was ~2M.)
22538c2ecf20Sopenharmony_ci	 *
22548c2ecf20Sopenharmony_ci	 * We probably cannot calculate the exact threshold value because this
22558c2ecf20Sopenharmony_ci	 * depends on the internal reservations requested by various
22568c2ecf20Sopenharmony_ci	 * operations, so some operations that consume a few metadata will
22578c2ecf20Sopenharmony_ci	 * succeed even if the Avail is zero. But this is better than the other
22588c2ecf20Sopenharmony_ci	 * way around.
22598c2ecf20Sopenharmony_ci	 */
22608c2ecf20Sopenharmony_ci	thresh = SZ_4M;
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci	/*
22638c2ecf20Sopenharmony_ci	 * We only want to claim there's no available space if we can no longer
22648c2ecf20Sopenharmony_ci	 * allocate chunks for our metadata profile and our global reserve will
22658c2ecf20Sopenharmony_ci	 * not fit in the free metadata space.  If we aren't ->full then we
22668c2ecf20Sopenharmony_ci	 * still can allocate chunks and thus are fine using the currently
22678c2ecf20Sopenharmony_ci	 * calculated f_bavail.
22688c2ecf20Sopenharmony_ci	 */
22698c2ecf20Sopenharmony_ci	if (!mixed && block_rsv->space_info->full &&
22708c2ecf20Sopenharmony_ci	    (total_free_meta < thresh || total_free_meta - thresh < block_rsv->size))
22718c2ecf20Sopenharmony_ci		buf->f_bavail = 0;
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	buf->f_type = BTRFS_SUPER_MAGIC;
22748c2ecf20Sopenharmony_ci	buf->f_bsize = dentry->d_sb->s_blocksize;
22758c2ecf20Sopenharmony_ci	buf->f_namelen = BTRFS_NAME_LEN;
22768c2ecf20Sopenharmony_ci
22778c2ecf20Sopenharmony_ci	/* We treat it as constant endianness (it doesn't matter _which_)
22788c2ecf20Sopenharmony_ci	   because we want the fsid to come out the same whether mounted
22798c2ecf20Sopenharmony_ci	   on a big-endian or little-endian host */
22808c2ecf20Sopenharmony_ci	buf->f_fsid.val[0] = be32_to_cpu(fsid[0]) ^ be32_to_cpu(fsid[2]);
22818c2ecf20Sopenharmony_ci	buf->f_fsid.val[1] = be32_to_cpu(fsid[1]) ^ be32_to_cpu(fsid[3]);
22828c2ecf20Sopenharmony_ci	/* Mask in the root object ID too, to disambiguate subvols */
22838c2ecf20Sopenharmony_ci	buf->f_fsid.val[0] ^=
22848c2ecf20Sopenharmony_ci		BTRFS_I(d_inode(dentry))->root->root_key.objectid >> 32;
22858c2ecf20Sopenharmony_ci	buf->f_fsid.val[1] ^=
22868c2ecf20Sopenharmony_ci		BTRFS_I(d_inode(dentry))->root->root_key.objectid;
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_ci	return 0;
22898c2ecf20Sopenharmony_ci}
22908c2ecf20Sopenharmony_ci
22918c2ecf20Sopenharmony_cistatic void btrfs_kill_super(struct super_block *sb)
22928c2ecf20Sopenharmony_ci{
22938c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
22948c2ecf20Sopenharmony_ci	kill_anon_super(sb);
22958c2ecf20Sopenharmony_ci	btrfs_free_fs_info(fs_info);
22968c2ecf20Sopenharmony_ci}
22978c2ecf20Sopenharmony_ci
22988c2ecf20Sopenharmony_cistatic struct file_system_type btrfs_fs_type = {
22998c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
23008c2ecf20Sopenharmony_ci	.name		= "btrfs",
23018c2ecf20Sopenharmony_ci	.mount		= btrfs_mount,
23028c2ecf20Sopenharmony_ci	.kill_sb	= btrfs_kill_super,
23038c2ecf20Sopenharmony_ci	.fs_flags	= FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
23048c2ecf20Sopenharmony_ci};
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_cistatic struct file_system_type btrfs_root_fs_type = {
23078c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
23088c2ecf20Sopenharmony_ci	.name		= "btrfs",
23098c2ecf20Sopenharmony_ci	.mount		= btrfs_mount_root,
23108c2ecf20Sopenharmony_ci	.kill_sb	= btrfs_kill_super,
23118c2ecf20Sopenharmony_ci	.fs_flags	= FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
23128c2ecf20Sopenharmony_ci};
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ciMODULE_ALIAS_FS("btrfs");
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_cistatic int btrfs_control_open(struct inode *inode, struct file *file)
23178c2ecf20Sopenharmony_ci{
23188c2ecf20Sopenharmony_ci	/*
23198c2ecf20Sopenharmony_ci	 * The control file's private_data is used to hold the
23208c2ecf20Sopenharmony_ci	 * transaction when it is started and is used to keep
23218c2ecf20Sopenharmony_ci	 * track of whether a transaction is already in progress.
23228c2ecf20Sopenharmony_ci	 */
23238c2ecf20Sopenharmony_ci	file->private_data = NULL;
23248c2ecf20Sopenharmony_ci	return 0;
23258c2ecf20Sopenharmony_ci}
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci/*
23288c2ecf20Sopenharmony_ci * Used by /dev/btrfs-control for devices ioctls.
23298c2ecf20Sopenharmony_ci */
23308c2ecf20Sopenharmony_cistatic long btrfs_control_ioctl(struct file *file, unsigned int cmd,
23318c2ecf20Sopenharmony_ci				unsigned long arg)
23328c2ecf20Sopenharmony_ci{
23338c2ecf20Sopenharmony_ci	struct btrfs_ioctl_vol_args *vol;
23348c2ecf20Sopenharmony_ci	struct btrfs_device *device = NULL;
23358c2ecf20Sopenharmony_ci	int ret = -ENOTTY;
23368c2ecf20Sopenharmony_ci
23378c2ecf20Sopenharmony_ci	if (!capable(CAP_SYS_ADMIN))
23388c2ecf20Sopenharmony_ci		return -EPERM;
23398c2ecf20Sopenharmony_ci
23408c2ecf20Sopenharmony_ci	vol = memdup_user((void __user *)arg, sizeof(*vol));
23418c2ecf20Sopenharmony_ci	if (IS_ERR(vol))
23428c2ecf20Sopenharmony_ci		return PTR_ERR(vol);
23438c2ecf20Sopenharmony_ci	vol->name[BTRFS_PATH_NAME_MAX] = '\0';
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci	switch (cmd) {
23468c2ecf20Sopenharmony_ci	case BTRFS_IOC_SCAN_DEV:
23478c2ecf20Sopenharmony_ci		mutex_lock(&uuid_mutex);
23488c2ecf20Sopenharmony_ci		device = btrfs_scan_one_device(vol->name, FMODE_READ,
23498c2ecf20Sopenharmony_ci					       &btrfs_root_fs_type);
23508c2ecf20Sopenharmony_ci		ret = PTR_ERR_OR_ZERO(device);
23518c2ecf20Sopenharmony_ci		mutex_unlock(&uuid_mutex);
23528c2ecf20Sopenharmony_ci		break;
23538c2ecf20Sopenharmony_ci	case BTRFS_IOC_FORGET_DEV:
23548c2ecf20Sopenharmony_ci		ret = btrfs_forget_devices(vol->name);
23558c2ecf20Sopenharmony_ci		break;
23568c2ecf20Sopenharmony_ci	case BTRFS_IOC_DEVICES_READY:
23578c2ecf20Sopenharmony_ci		mutex_lock(&uuid_mutex);
23588c2ecf20Sopenharmony_ci		device = btrfs_scan_one_device(vol->name, FMODE_READ,
23598c2ecf20Sopenharmony_ci					       &btrfs_root_fs_type);
23608c2ecf20Sopenharmony_ci		if (IS_ERR(device)) {
23618c2ecf20Sopenharmony_ci			mutex_unlock(&uuid_mutex);
23628c2ecf20Sopenharmony_ci			ret = PTR_ERR(device);
23638c2ecf20Sopenharmony_ci			break;
23648c2ecf20Sopenharmony_ci		}
23658c2ecf20Sopenharmony_ci		ret = !(device->fs_devices->num_devices ==
23668c2ecf20Sopenharmony_ci			device->fs_devices->total_devices);
23678c2ecf20Sopenharmony_ci		mutex_unlock(&uuid_mutex);
23688c2ecf20Sopenharmony_ci		break;
23698c2ecf20Sopenharmony_ci	case BTRFS_IOC_GET_SUPPORTED_FEATURES:
23708c2ecf20Sopenharmony_ci		ret = btrfs_ioctl_get_supported_features((void __user*)arg);
23718c2ecf20Sopenharmony_ci		break;
23728c2ecf20Sopenharmony_ci	}
23738c2ecf20Sopenharmony_ci
23748c2ecf20Sopenharmony_ci	kfree(vol);
23758c2ecf20Sopenharmony_ci	return ret;
23768c2ecf20Sopenharmony_ci}
23778c2ecf20Sopenharmony_ci
23788c2ecf20Sopenharmony_cistatic int btrfs_freeze(struct super_block *sb)
23798c2ecf20Sopenharmony_ci{
23808c2ecf20Sopenharmony_ci	struct btrfs_trans_handle *trans;
23818c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
23828c2ecf20Sopenharmony_ci	struct btrfs_root *root = fs_info->tree_root;
23838c2ecf20Sopenharmony_ci
23848c2ecf20Sopenharmony_ci	set_bit(BTRFS_FS_FROZEN, &fs_info->flags);
23858c2ecf20Sopenharmony_ci	/*
23868c2ecf20Sopenharmony_ci	 * We don't need a barrier here, we'll wait for any transaction that
23878c2ecf20Sopenharmony_ci	 * could be in progress on other threads (and do delayed iputs that
23888c2ecf20Sopenharmony_ci	 * we want to avoid on a frozen filesystem), or do the commit
23898c2ecf20Sopenharmony_ci	 * ourselves.
23908c2ecf20Sopenharmony_ci	 */
23918c2ecf20Sopenharmony_ci	trans = btrfs_attach_transaction_barrier(root);
23928c2ecf20Sopenharmony_ci	if (IS_ERR(trans)) {
23938c2ecf20Sopenharmony_ci		/* no transaction, don't bother */
23948c2ecf20Sopenharmony_ci		if (PTR_ERR(trans) == -ENOENT)
23958c2ecf20Sopenharmony_ci			return 0;
23968c2ecf20Sopenharmony_ci		return PTR_ERR(trans);
23978c2ecf20Sopenharmony_ci	}
23988c2ecf20Sopenharmony_ci	return btrfs_commit_transaction(trans);
23998c2ecf20Sopenharmony_ci}
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_cistatic int btrfs_unfreeze(struct super_block *sb)
24028c2ecf20Sopenharmony_ci{
24038c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	clear_bit(BTRFS_FS_FROZEN, &fs_info->flags);
24068c2ecf20Sopenharmony_ci	return 0;
24078c2ecf20Sopenharmony_ci}
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_cistatic int btrfs_show_devname(struct seq_file *m, struct dentry *root)
24108c2ecf20Sopenharmony_ci{
24118c2ecf20Sopenharmony_ci	struct btrfs_fs_info *fs_info = btrfs_sb(root->d_sb);
24128c2ecf20Sopenharmony_ci	struct btrfs_device *dev, *first_dev = NULL;
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci	/*
24158c2ecf20Sopenharmony_ci	 * Lightweight locking of the devices. We should not need
24168c2ecf20Sopenharmony_ci	 * device_list_mutex here as we only read the device data and the list
24178c2ecf20Sopenharmony_ci	 * is protected by RCU.  Even if a device is deleted during the list
24188c2ecf20Sopenharmony_ci	 * traversals, we'll get valid data, the freeing callback will wait at
24198c2ecf20Sopenharmony_ci	 * least until the rcu_read_unlock.
24208c2ecf20Sopenharmony_ci	 */
24218c2ecf20Sopenharmony_ci	rcu_read_lock();
24228c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(dev, &fs_info->fs_devices->devices, dev_list) {
24238c2ecf20Sopenharmony_ci		if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state))
24248c2ecf20Sopenharmony_ci			continue;
24258c2ecf20Sopenharmony_ci		if (!dev->name)
24268c2ecf20Sopenharmony_ci			continue;
24278c2ecf20Sopenharmony_ci		if (!first_dev || dev->devid < first_dev->devid)
24288c2ecf20Sopenharmony_ci			first_dev = dev;
24298c2ecf20Sopenharmony_ci	}
24308c2ecf20Sopenharmony_ci
24318c2ecf20Sopenharmony_ci	if (first_dev)
24328c2ecf20Sopenharmony_ci		seq_escape(m, rcu_str_deref(first_dev->name), " \t\n\\");
24338c2ecf20Sopenharmony_ci	else
24348c2ecf20Sopenharmony_ci		WARN_ON(1);
24358c2ecf20Sopenharmony_ci	rcu_read_unlock();
24368c2ecf20Sopenharmony_ci	return 0;
24378c2ecf20Sopenharmony_ci}
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_cistatic const struct super_operations btrfs_super_ops = {
24408c2ecf20Sopenharmony_ci	.drop_inode	= btrfs_drop_inode,
24418c2ecf20Sopenharmony_ci	.evict_inode	= btrfs_evict_inode,
24428c2ecf20Sopenharmony_ci	.put_super	= btrfs_put_super,
24438c2ecf20Sopenharmony_ci	.sync_fs	= btrfs_sync_fs,
24448c2ecf20Sopenharmony_ci	.show_options	= btrfs_show_options,
24458c2ecf20Sopenharmony_ci	.show_devname	= btrfs_show_devname,
24468c2ecf20Sopenharmony_ci	.alloc_inode	= btrfs_alloc_inode,
24478c2ecf20Sopenharmony_ci	.destroy_inode	= btrfs_destroy_inode,
24488c2ecf20Sopenharmony_ci	.free_inode	= btrfs_free_inode,
24498c2ecf20Sopenharmony_ci	.statfs		= btrfs_statfs,
24508c2ecf20Sopenharmony_ci	.remount_fs	= btrfs_remount,
24518c2ecf20Sopenharmony_ci	.freeze_fs	= btrfs_freeze,
24528c2ecf20Sopenharmony_ci	.unfreeze_fs	= btrfs_unfreeze,
24538c2ecf20Sopenharmony_ci};
24548c2ecf20Sopenharmony_ci
24558c2ecf20Sopenharmony_cistatic const struct file_operations btrfs_ctl_fops = {
24568c2ecf20Sopenharmony_ci	.open = btrfs_control_open,
24578c2ecf20Sopenharmony_ci	.unlocked_ioctl	 = btrfs_control_ioctl,
24588c2ecf20Sopenharmony_ci	.compat_ioctl = compat_ptr_ioctl,
24598c2ecf20Sopenharmony_ci	.owner	 = THIS_MODULE,
24608c2ecf20Sopenharmony_ci	.llseek = noop_llseek,
24618c2ecf20Sopenharmony_ci};
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_cistatic struct miscdevice btrfs_misc = {
24648c2ecf20Sopenharmony_ci	.minor		= BTRFS_MINOR,
24658c2ecf20Sopenharmony_ci	.name		= "btrfs-control",
24668c2ecf20Sopenharmony_ci	.fops		= &btrfs_ctl_fops
24678c2ecf20Sopenharmony_ci};
24688c2ecf20Sopenharmony_ci
24698c2ecf20Sopenharmony_ciMODULE_ALIAS_MISCDEV(BTRFS_MINOR);
24708c2ecf20Sopenharmony_ciMODULE_ALIAS("devname:btrfs-control");
24718c2ecf20Sopenharmony_ci
24728c2ecf20Sopenharmony_cistatic int __init btrfs_interface_init(void)
24738c2ecf20Sopenharmony_ci{
24748c2ecf20Sopenharmony_ci	return misc_register(&btrfs_misc);
24758c2ecf20Sopenharmony_ci}
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_cistatic __cold void btrfs_interface_exit(void)
24788c2ecf20Sopenharmony_ci{
24798c2ecf20Sopenharmony_ci	misc_deregister(&btrfs_misc);
24808c2ecf20Sopenharmony_ci}
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_cistatic void __init btrfs_print_mod_info(void)
24838c2ecf20Sopenharmony_ci{
24848c2ecf20Sopenharmony_ci	static const char options[] = ""
24858c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG
24868c2ecf20Sopenharmony_ci			", debug=on"
24878c2ecf20Sopenharmony_ci#endif
24888c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_ASSERT
24898c2ecf20Sopenharmony_ci			", assert=on"
24908c2ecf20Sopenharmony_ci#endif
24918c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
24928c2ecf20Sopenharmony_ci			", integrity-checker=on"
24938c2ecf20Sopenharmony_ci#endif
24948c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_FS_REF_VERIFY
24958c2ecf20Sopenharmony_ci			", ref-verify=on"
24968c2ecf20Sopenharmony_ci#endif
24978c2ecf20Sopenharmony_ci			;
24988c2ecf20Sopenharmony_ci	pr_info("Btrfs loaded, crc32c=%s%s\n", crc32c_impl(), options);
24998c2ecf20Sopenharmony_ci}
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_cistatic int __init init_btrfs_fs(void)
25028c2ecf20Sopenharmony_ci{
25038c2ecf20Sopenharmony_ci	int err;
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci	btrfs_props_init();
25068c2ecf20Sopenharmony_ci
25078c2ecf20Sopenharmony_ci	err = btrfs_init_sysfs();
25088c2ecf20Sopenharmony_ci	if (err)
25098c2ecf20Sopenharmony_ci		return err;
25108c2ecf20Sopenharmony_ci
25118c2ecf20Sopenharmony_ci	btrfs_init_compress();
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci	err = btrfs_init_cachep();
25148c2ecf20Sopenharmony_ci	if (err)
25158c2ecf20Sopenharmony_ci		goto free_compress;
25168c2ecf20Sopenharmony_ci
25178c2ecf20Sopenharmony_ci	err = extent_io_init();
25188c2ecf20Sopenharmony_ci	if (err)
25198c2ecf20Sopenharmony_ci		goto free_cachep;
25208c2ecf20Sopenharmony_ci
25218c2ecf20Sopenharmony_ci	err = extent_state_cache_init();
25228c2ecf20Sopenharmony_ci	if (err)
25238c2ecf20Sopenharmony_ci		goto free_extent_io;
25248c2ecf20Sopenharmony_ci
25258c2ecf20Sopenharmony_ci	err = extent_map_init();
25268c2ecf20Sopenharmony_ci	if (err)
25278c2ecf20Sopenharmony_ci		goto free_extent_state_cache;
25288c2ecf20Sopenharmony_ci
25298c2ecf20Sopenharmony_ci	err = ordered_data_init();
25308c2ecf20Sopenharmony_ci	if (err)
25318c2ecf20Sopenharmony_ci		goto free_extent_map;
25328c2ecf20Sopenharmony_ci
25338c2ecf20Sopenharmony_ci	err = btrfs_delayed_inode_init();
25348c2ecf20Sopenharmony_ci	if (err)
25358c2ecf20Sopenharmony_ci		goto free_ordered_data;
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci	err = btrfs_auto_defrag_init();
25388c2ecf20Sopenharmony_ci	if (err)
25398c2ecf20Sopenharmony_ci		goto free_delayed_inode;
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci	err = btrfs_delayed_ref_init();
25428c2ecf20Sopenharmony_ci	if (err)
25438c2ecf20Sopenharmony_ci		goto free_auto_defrag;
25448c2ecf20Sopenharmony_ci
25458c2ecf20Sopenharmony_ci	err = btrfs_prelim_ref_init();
25468c2ecf20Sopenharmony_ci	if (err)
25478c2ecf20Sopenharmony_ci		goto free_delayed_ref;
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	err = btrfs_end_io_wq_init();
25508c2ecf20Sopenharmony_ci	if (err)
25518c2ecf20Sopenharmony_ci		goto free_prelim_ref;
25528c2ecf20Sopenharmony_ci
25538c2ecf20Sopenharmony_ci	err = btrfs_interface_init();
25548c2ecf20Sopenharmony_ci	if (err)
25558c2ecf20Sopenharmony_ci		goto free_end_io_wq;
25568c2ecf20Sopenharmony_ci
25578c2ecf20Sopenharmony_ci	btrfs_init_lockdep();
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	btrfs_print_mod_info();
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_ci	err = btrfs_run_sanity_tests();
25628c2ecf20Sopenharmony_ci	if (err)
25638c2ecf20Sopenharmony_ci		goto unregister_ioctl;
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci	err = register_filesystem(&btrfs_fs_type);
25668c2ecf20Sopenharmony_ci	if (err)
25678c2ecf20Sopenharmony_ci		goto unregister_ioctl;
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci	return 0;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ciunregister_ioctl:
25728c2ecf20Sopenharmony_ci	btrfs_interface_exit();
25738c2ecf20Sopenharmony_cifree_end_io_wq:
25748c2ecf20Sopenharmony_ci	btrfs_end_io_wq_exit();
25758c2ecf20Sopenharmony_cifree_prelim_ref:
25768c2ecf20Sopenharmony_ci	btrfs_prelim_ref_exit();
25778c2ecf20Sopenharmony_cifree_delayed_ref:
25788c2ecf20Sopenharmony_ci	btrfs_delayed_ref_exit();
25798c2ecf20Sopenharmony_cifree_auto_defrag:
25808c2ecf20Sopenharmony_ci	btrfs_auto_defrag_exit();
25818c2ecf20Sopenharmony_cifree_delayed_inode:
25828c2ecf20Sopenharmony_ci	btrfs_delayed_inode_exit();
25838c2ecf20Sopenharmony_cifree_ordered_data:
25848c2ecf20Sopenharmony_ci	ordered_data_exit();
25858c2ecf20Sopenharmony_cifree_extent_map:
25868c2ecf20Sopenharmony_ci	extent_map_exit();
25878c2ecf20Sopenharmony_cifree_extent_state_cache:
25888c2ecf20Sopenharmony_ci	extent_state_cache_exit();
25898c2ecf20Sopenharmony_cifree_extent_io:
25908c2ecf20Sopenharmony_ci	extent_io_exit();
25918c2ecf20Sopenharmony_cifree_cachep:
25928c2ecf20Sopenharmony_ci	btrfs_destroy_cachep();
25938c2ecf20Sopenharmony_cifree_compress:
25948c2ecf20Sopenharmony_ci	btrfs_exit_compress();
25958c2ecf20Sopenharmony_ci	btrfs_exit_sysfs();
25968c2ecf20Sopenharmony_ci
25978c2ecf20Sopenharmony_ci	return err;
25988c2ecf20Sopenharmony_ci}
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_cistatic void __exit exit_btrfs_fs(void)
26018c2ecf20Sopenharmony_ci{
26028c2ecf20Sopenharmony_ci	btrfs_destroy_cachep();
26038c2ecf20Sopenharmony_ci	btrfs_delayed_ref_exit();
26048c2ecf20Sopenharmony_ci	btrfs_auto_defrag_exit();
26058c2ecf20Sopenharmony_ci	btrfs_delayed_inode_exit();
26068c2ecf20Sopenharmony_ci	btrfs_prelim_ref_exit();
26078c2ecf20Sopenharmony_ci	ordered_data_exit();
26088c2ecf20Sopenharmony_ci	extent_map_exit();
26098c2ecf20Sopenharmony_ci	extent_state_cache_exit();
26108c2ecf20Sopenharmony_ci	extent_io_exit();
26118c2ecf20Sopenharmony_ci	btrfs_interface_exit();
26128c2ecf20Sopenharmony_ci	btrfs_end_io_wq_exit();
26138c2ecf20Sopenharmony_ci	unregister_filesystem(&btrfs_fs_type);
26148c2ecf20Sopenharmony_ci	btrfs_exit_sysfs();
26158c2ecf20Sopenharmony_ci	btrfs_cleanup_fs_uuids();
26168c2ecf20Sopenharmony_ci	btrfs_exit_compress();
26178c2ecf20Sopenharmony_ci}
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_cilate_initcall(init_btrfs_fs);
26208c2ecf20Sopenharmony_cimodule_exit(exit_btrfs_fs)
26218c2ecf20Sopenharmony_ci
26228c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
26238c2ecf20Sopenharmony_ciMODULE_SOFTDEP("pre: crc32c");
26248c2ecf20Sopenharmony_ciMODULE_SOFTDEP("pre: xxhash64");
26258c2ecf20Sopenharmony_ciMODULE_SOFTDEP("pre: sha256");
26268c2ecf20Sopenharmony_ciMODULE_SOFTDEP("pre: blake2b-256");
2627