linux/fs/btrfs/super.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 */

#include <linux/blkdev.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/backing-dev.h>
#include <linux/mount.h>
#include <linux/writeback.h>
#include <linux/statfs.h>
#include <linux/compat.h>
#include <linux/parser.h>
#include <linux/ctype.h>
#include <linux/namei.h>
#include <linux/miscdevice.h>
#include <linux/magic.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <linux/crc32c.h>
#include <linux/btrfs.h>
#include <linux/security.h>
#include <linux/fs_parser.h>
#include "messages.h"
#include "delayed-inode.h"
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
#include "btrfs_inode.h"
#include "direct-io.h"
#include "props.h"
#include "xattr.h"
#include "bio.h"
#include "export.h"
#include "compression.h"
#include "dev-replace.h"
#include "free-space-cache.h"
#include "backref.h"
#include "space-info.h"
#include "sysfs.h"
#include "zoned.h"
#include "tests/btrfs-tests.h"
#include "block-group.h"
#include "discard.h"
#include "qgroup.h"
#include "raid56.h"
#include "fs.h"
#include "accessors.h"
#include "defrag.h"
#include "dir-item.h"
#include "ioctl.h"
#include "scrub.h"
#include "verity.h"
#include "super.h"
#include "extent-tree.h"
#define CREATE_TRACE_POINTS
#include <trace/events/btrfs.h>

static const struct super_operations btrfs_super_ops;
static struct file_system_type btrfs_fs_type;

static void btrfs_put_super(struct super_block *sb)
{}

/* Store the mount options related information. */
struct btrfs_fs_context {};

enum {};

enum {};

static const struct constant_table btrfs_parameter_fatal_errors[] =;

enum {};

static const struct constant_table btrfs_parameter_discard[] =;

enum {};

static const struct constant_table btrfs_parameter_space_cache[] =;

enum {};

static const struct constant_table btrfs_parameter_rescue[] =;

#ifdef CONFIG_BTRFS_DEBUG
enum {};

static const struct constant_table btrfs_parameter_fragment[] =;
#endif

static const struct fs_parameter_spec btrfs_fs_parameters[] =;

/* No support for restricting writes to btrfs devices yet... */
static inline blk_mode_t btrfs_open_mode(struct fs_context *fc)
{}

static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{}

/*
 * Some options only have meaning at mount time and shouldn't persist across
 * remounts, or be displayed. Clear these at the end of mount and remount code
 * paths.
 */
static void btrfs_clear_oneshot_options(struct btrfs_fs_info *fs_info)
{}

static bool check_ro_option(const struct btrfs_fs_info *fs_info,
			    unsigned long long mount_opt, unsigned long long opt,
			    const char *opt_name)
{}

bool btrfs_check_options(const struct btrfs_fs_info *info,
			 unsigned long long *mount_opt,
			 unsigned long flags)
{}

/*
 * This is subtle, we only call this during open_ctree().  We need to pre-load
 * the mount options with the on-disk settings.  Before the new mount API took
 * effect we would do this on mount and remount.  With the new mount API we'll
 * only do this on the initial mount.
 *
 * This isn't a change in behavior, because we're using the current state of the
 * file system to set the current mount options.  If you mounted with special
 * options to disable these features and then remounted we wouldn't revert the
 * settings, because mounting without these features cleared the on-disk
 * settings, so this being called on re-mount is not needed.
 */
void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info)
{}

static void set_device_specific_options(struct btrfs_fs_info *fs_info)
{}

char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info,
					  u64 subvol_objectid)
{}

static int get_default_subvol_objectid(struct btrfs_fs_info *fs_info, u64 *objectid)
{}

static int btrfs_fill_super(struct super_block *sb,
			    struct btrfs_fs_devices *fs_devices,
			    void *data)
{}

int btrfs_sync_fs(struct super_block *sb, int wait)
{}

static void print_rescue_option(struct seq_file *seq, const char *s, bool *printed)
{}

static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
{}

/*
 * subvolumes are identified by ino 256
 */
static inline int is_subvolume_inode(struct inode *inode)
{}

static struct dentry *mount_subvol(const char *subvol_name, u64 subvol_objectid,
				   struct vfsmount *mnt)
{}

static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
				     u32 new_pool_size, u32 old_pool_size)
{}

static inline void btrfs_remount_begin(struct btrfs_fs_info *fs_info,
				       unsigned long long old_opts, int flags)
{}

static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,
					 unsigned long long old_opts)
{}

static int btrfs_remount_rw(struct btrfs_fs_info *fs_info)
{}

static int btrfs_remount_ro(struct btrfs_fs_info *fs_info)
{}

static void btrfs_ctx_to_info(struct btrfs_fs_info *fs_info, struct btrfs_fs_context *ctx)
{}

static void btrfs_info_to_ctx(struct btrfs_fs_info *fs_info, struct btrfs_fs_context *ctx)
{}

#define btrfs_info_if_set(fs_info, old_ctx, opt, fmt, args...)

#define btrfs_info_if_unset(fs_info, old_ctx, opt, fmt, args...)

static void btrfs_emit_options(struct btrfs_fs_info *info,
			       struct btrfs_fs_context *old)
{}

static int btrfs_reconfigure(struct fs_context *fc)
{}

/* Used to sort the devices by max_avail(descending sort) */
static int btrfs_cmp_device_free_bytes(const void *a, const void *b)
{}

/*
 * sort the devices by max_avail, in which max free extent size of each device
 * is stored.(Descending Sort)
 */
static inline void btrfs_descending_sort_devices(
					struct btrfs_device_info *devices,
					size_t nr_devices)
{}

/*
 * The helper to calc the free space on the devices that can be used to store
 * file data.
 */
static inline int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info,
					      u64 *free_bytes)
{}

/*
 * Calculate numbers for 'df', pessimistic in case of mixed raid profiles.
 *
 * If there's a redundant raid level at DATA block groups, use the respective
 * multiplier to scale the sizes.
 *
 * Unused device space usage is based on simulating the chunk allocator
 * algorithm that respects the device sizes and order of allocations.  This is
 * a close approximation of the actual use but there are other factors that may
 * change the result (like a new metadata chunk).
 *
 * If metadata is exhausted, f_bavail will be 0.
 */
static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{}

static int btrfs_fc_test_super(struct super_block *sb, struct fs_context *fc)
{}

static int btrfs_get_tree_super(struct fs_context *fc)
{}

/*
 * Ever since commit 0723a0473fb4 ("btrfs: allow mounting btrfs subvolumes
 * with different ro/rw options") the following works:
 *
 *        (i) mount /dev/sda3 -o subvol=foo,ro /mnt/foo
 *       (ii) mount /dev/sda3 -o subvol=bar,rw /mnt/bar
 *
 * which looks nice and innocent but is actually pretty intricate and deserves
 * a long comment.
 *
 * On another filesystem a subvolume mount is close to something like:
 *
 *	(iii) # create rw superblock + initial mount
 *	      mount -t xfs /dev/sdb /opt/
 *
 *	      # create ro bind mount
 *	      mount --bind -o ro /opt/foo /mnt/foo
 *
 *	      # unmount initial mount
 *	      umount /opt
 *
 * Of course, there's some special subvolume sauce and there's the fact that the
 * sb->s_root dentry is really swapped after mount_subtree(). But conceptually
 * it's very close and will help us understand the issue.
 *
 * The old mount API didn't cleanly distinguish between a mount being made ro
 * and a superblock being made ro.  The only way to change the ro state of
 * either object was by passing ms_rdonly. If a new mount was created via
 * mount(2) such as:
 *
 *      mount("/dev/sdb", "/mnt", "xfs", ms_rdonly, null);
 *
 * the MS_RDONLY flag being specified had two effects:
 *
 * (1) MNT_READONLY was raised -> the resulting mount got
 *     @mnt->mnt_flags |= MNT_READONLY raised.
 *
 * (2) MS_RDONLY was passed to the filesystem's mount method and the filesystems
 *     made the superblock ro. Note, how SB_RDONLY has the same value as
 *     ms_rdonly and is raised whenever MS_RDONLY is passed through mount(2).
 *
 * Creating a subtree mount via (iii) ends up leaving a rw superblock with a
 * subtree mounted ro.
 *
 * But consider the effect on the old mount API on btrfs subvolume mounting
 * which combines the distinct step in (iii) into a single step.
 *
 * By issuing (i) both the mount and the superblock are turned ro. Now when (ii)
 * is issued the superblock is ro and thus even if the mount created for (ii) is
 * rw it wouldn't help. Hence, btrfs needed to transition the superblock from ro
 * to rw for (ii) which it did using an internal remount call.
 *
 * IOW, subvolume mounting was inherently complicated due to the ambiguity of
 * MS_RDONLY in mount(2). Note, this ambiguity has mount(8) always translate
 * "ro" to MS_RDONLY. IOW, in both (i) and (ii) "ro" becomes MS_RDONLY when
 * passed by mount(8) to mount(2).
 *
 * Enter the new mount API. The new mount API disambiguates making a mount ro
 * and making a superblock ro.
 *
 * (3) To turn a mount ro the MOUNT_ATTR_ONLY flag can be used with either
 *     fsmount() or mount_setattr() this is a pure VFS level change for a
 *     specific mount or mount tree that is never seen by the filesystem itself.
 *
 * (4) To turn a superblock ro the "ro" flag must be used with
 *     fsconfig(FSCONFIG_SET_FLAG, "ro"). This option is seen by the filesystem
 *     in fc->sb_flags.
 *
 * This disambiguation has rather positive consequences.  Mounting a subvolume
 * ro will not also turn the superblock ro. Only the mount for the subvolume
 * will become ro.
 *
 * So, if the superblock creation request comes from the new mount API the
 * caller must have explicitly done:
 *
 *      fsconfig(FSCONFIG_SET_FLAG, "ro")
 *      fsmount/mount_setattr(MOUNT_ATTR_RDONLY)
 *
 * IOW, at some point the caller must have explicitly turned the whole
 * superblock ro and we shouldn't just undo it like we did for the old mount
 * API. In any case, it lets us avoid the hack in the new mount API.
 *
 * Consequently, the remounting hack must only be used for requests originating
 * from the old mount API and should be marked for full deprecation so it can be
 * turned off in a couple of years.
 *
 * The new mount API has no reason to support this hack.
 */
static struct vfsmount *btrfs_reconfigure_for_mount(struct fs_context *fc)
{}

static int btrfs_get_tree_subvol(struct fs_context *fc)
{}

static int btrfs_get_tree(struct fs_context *fc)
{}

static void btrfs_kill_super(struct super_block *sb)
{}

static void btrfs_free_fs_context(struct fs_context *fc)
{}

static int btrfs_dup_fs_context(struct fs_context *fc, struct fs_context *src_fc)
{}

static const struct fs_context_operations btrfs_fs_context_ops =;

static int btrfs_init_fs_context(struct fs_context *fc)
{}

static struct file_system_type btrfs_fs_type =;

MODULE_ALIAS_FS();

static int btrfs_control_open(struct inode *inode, struct file *file)
{}

/*
 * Used by /dev/btrfs-control for devices ioctls.
 */
static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{}

static int btrfs_freeze(struct super_block *sb)
{}

static int check_dev_super(struct btrfs_device *dev)
{}

static int btrfs_unfreeze(struct super_block *sb)
{}

static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
{}

static long btrfs_nr_cached_objects(struct super_block *sb, struct shrink_control *sc)
{}

static long btrfs_free_cached_objects(struct super_block *sb, struct shrink_control *sc)
{}

static const struct super_operations btrfs_super_ops =;

static const struct file_operations btrfs_ctl_fops =;

static struct miscdevice btrfs_misc =;

MODULE_ALIAS_MISCDEV();
MODULE_ALIAS();

static int __init btrfs_interface_init(void)
{}

static __cold void btrfs_interface_exit(void)
{}

static int __init btrfs_print_mod_info(void)
{}

static int register_btrfs(void)
{}

static void unregister_btrfs(void)
{}

/* Helper structure for long init/exit functions. */
struct init_sequence {};

static const struct init_sequence mod_init_seq[] =;

static bool mod_init_result[ARRAY_SIZE(mod_init_seq)];

static __always_inline void btrfs_exit_btrfs_fs(void)
{}

static void __exit exit_btrfs_fs(void)
{}

static int __init init_btrfs_fs(void)
{}

late_initcall(init_btrfs_fs);
module_exit()

MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_SOFTDEP();
MODULE_SOFTDEP();
MODULE_SOFTDEP();
MODULE_SOFTDEP();