linux/fs/ext4/super.c

// SPDX-License-Identifier: GPL-2.0
/*
 *  linux/fs/ext4/super.c
 *
 * Copyright (C) 1992, 1993, 1994, 1995
 * Remy Card ([email protected])
 * Laboratoire MASI - Institut Blaise Pascal
 * Universite Pierre et Marie Curie (Paris VI)
 *
 *  from
 *
 *  linux/fs/minix/inode.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Big-endian to little-endian byte-swapping/bitmaps by
 *        David S. Miller ([email protected]), 1995
 */

#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
#include <linux/parser.h>
#include <linux/buffer_head.h>
#include <linux/exportfs.h>
#include <linux/vfs.h>
#include <linux/random.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/quotaops.h>
#include <linux/seq_file.h>
#include <linux/ctype.h>
#include <linux/log2.h>
#include <linux/crc16.h>
#include <linux/dax.h>
#include <linux/uaccess.h>
#include <linux/iversion.h>
#include <linux/unicode.h>
#include <linux/part_stat.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/fsnotify.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>

#include "ext4.h"
#include "ext4_extents.h"	/* Needed for trace points definition */
#include "ext4_jbd2.h"
#include "xattr.h"
#include "acl.h"
#include "mballoc.h"
#include "fsmap.h"

#define CREATE_TRACE_POINTS
#include <trace/events/ext4.h>

static struct ext4_lazy_init *ext4_li_info;
static DEFINE_MUTEX(ext4_li_mtx);
static struct ratelimit_state ext4_mount_msg_ratelimit;

static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
			     unsigned long journal_devnum);
static int ext4_show_options(struct seq_file *seq, struct dentry *root);
static void ext4_update_super(struct super_block *sb);
static int ext4_commit_super(struct super_block *sb);
static int ext4_mark_recovery_complete(struct super_block *sb,
					struct ext4_super_block *es);
static int ext4_clear_journal_err(struct super_block *sb,
				  struct ext4_super_block *es);
static int ext4_sync_fs(struct super_block *sb, int wait);
static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
static int ext4_unfreeze(struct super_block *sb);
static int ext4_freeze(struct super_block *sb);
static inline int ext2_feature_set_ok(struct super_block *sb);
static inline int ext3_feature_set_ok(struct super_block *sb);
static void ext4_destroy_lazyinit_thread(void);
static void ext4_unregister_li_request(struct super_block *sb);
static void ext4_clear_request_list(void);
static struct inode *ext4_get_journal_inode(struct super_block *sb,
					    unsigned int journal_inum);
static int ext4_validate_options(struct fs_context *fc);
static int ext4_check_opt_consistency(struct fs_context *fc,
				      struct super_block *sb);
static void ext4_apply_options(struct fs_context *fc, struct super_block *sb);
static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param);
static int ext4_get_tree(struct fs_context *fc);
static int ext4_reconfigure(struct fs_context *fc);
static void ext4_fc_free(struct fs_context *fc);
static int ext4_init_fs_context(struct fs_context *fc);
static void ext4_kill_sb(struct super_block *sb);
static const struct fs_parameter_spec ext4_param_specs[];

/*
 * Lock ordering
 *
 * page fault path:
 * mmap_lock -> sb_start_pagefault -> invalidate_lock (r) -> transaction start
 *   -> page lock -> i_data_sem (rw)
 *
 * buffered write path:
 * sb_start_write -> i_mutex -> mmap_lock
 * sb_start_write -> i_mutex -> transaction start -> page lock ->
 *   i_data_sem (rw)
 *
 * truncate:
 * sb_start_write -> i_mutex -> invalidate_lock (w) -> i_mmap_rwsem (w) ->
 *   page lock
 * sb_start_write -> i_mutex -> invalidate_lock (w) -> transaction start ->
 *   i_data_sem (rw)
 *
 * direct IO:
 * sb_start_write -> i_mutex -> mmap_lock
 * sb_start_write -> i_mutex -> transaction start -> i_data_sem (rw)
 *
 * writepages:
 * transaction start -> page lock(s) -> i_data_sem (rw)
 */

static const struct fs_context_operations ext4_context_ops =;


#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
static struct file_system_type ext2_fs_type = {
	.owner			= THIS_MODULE,
	.name			= "ext2",
	.init_fs_context	= ext4_init_fs_context,
	.parameters		= ext4_param_specs,
	.kill_sb		= ext4_kill_sb,
	.fs_flags		= FS_REQUIRES_DEV,
};
MODULE_ALIAS_FS("ext2");
MODULE_ALIAS("ext2");
#define IS_EXT2_SB
#else
#define IS_EXT2_SB(sb)
#endif


static struct file_system_type ext3_fs_type =;
MODULE_ALIAS_FS();
MODULE_ALIAS();
#define IS_EXT3_SB(sb)


static inline void __ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags,
				  bh_end_io_t *end_io)
{}

void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags,
			 bh_end_io_t *end_io)
{}

int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, bh_end_io_t *end_io)
{}

int ext4_read_bh_lock(struct buffer_head *bh, blk_opf_t op_flags, bool wait)
{}

/*
 * This works like __bread_gfp() except it uses ERR_PTR for error
 * returns.  Currently with sb_bread it's impossible to distinguish
 * between ENOMEM and EIO situations (since both result in a NULL
 * return.
 */
static struct buffer_head *__ext4_sb_bread_gfp(struct super_block *sb,
					       sector_t block,
					       blk_opf_t op_flags, gfp_t gfp)
{}

struct buffer_head *ext4_sb_bread(struct super_block *sb, sector_t block,
				   blk_opf_t op_flags)
{}

struct buffer_head *ext4_sb_bread_unmovable(struct super_block *sb,
					    sector_t block)
{}

void ext4_sb_breadahead_unmovable(struct super_block *sb, sector_t block)
{}

static int ext4_verify_csum_type(struct super_block *sb,
				 struct ext4_super_block *es)
{}

__le32 ext4_superblock_csum(struct super_block *sb,
			    struct ext4_super_block *es)
{}

static int ext4_superblock_csum_verify(struct super_block *sb,
				       struct ext4_super_block *es)
{}

void ext4_superblock_csum_set(struct super_block *sb)
{}

ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
			       struct ext4_group_desc *bg)
{}

ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
			       struct ext4_group_desc *bg)
{}

ext4_fsblk_t ext4_inode_table(struct super_block *sb,
			      struct ext4_group_desc *bg)
{}

__u32 ext4_free_group_clusters(struct super_block *sb,
			       struct ext4_group_desc *bg)
{}

__u32 ext4_free_inodes_count(struct super_block *sb,
			      struct ext4_group_desc *bg)
{}

__u32 ext4_used_dirs_count(struct super_block *sb,
			      struct ext4_group_desc *bg)
{}

__u32 ext4_itable_unused_count(struct super_block *sb,
			      struct ext4_group_desc *bg)
{}

void ext4_block_bitmap_set(struct super_block *sb,
			   struct ext4_group_desc *bg, ext4_fsblk_t blk)
{}

void ext4_inode_bitmap_set(struct super_block *sb,
			   struct ext4_group_desc *bg, ext4_fsblk_t blk)
{}

void ext4_inode_table_set(struct super_block *sb,
			  struct ext4_group_desc *bg, ext4_fsblk_t blk)
{}

void ext4_free_group_clusters_set(struct super_block *sb,
				  struct ext4_group_desc *bg, __u32 count)
{}

void ext4_free_inodes_set(struct super_block *sb,
			  struct ext4_group_desc *bg, __u32 count)
{}

void ext4_used_dirs_set(struct super_block *sb,
			  struct ext4_group_desc *bg, __u32 count)
{}

void ext4_itable_unused_set(struct super_block *sb,
			  struct ext4_group_desc *bg, __u32 count)
{}

static void __ext4_update_tstamp(__le32 *lo, __u8 *hi, time64_t now)
{}

static time64_t __ext4_get_tstamp(__le32 *lo, __u8 *hi)
{}
#define ext4_update_tstamp(es, tstamp)
#define ext4_get_tstamp(es, tstamp)

#define EXT4_SB_REFRESH_INTERVAL_SEC
#define EXT4_SB_REFRESH_INTERVAL_KB

/*
 * The ext4_maybe_update_superblock() function checks and updates the
 * superblock if needed.
 *
 * This function is designed to update the on-disk superblock only under
 * certain conditions to prevent excessive disk writes and unnecessary
 * waking of the disk from sleep. The superblock will be updated if:
 * 1. More than an hour has passed since the last superblock update, and
 * 2. More than 16MB have been written since the last superblock update.
 *
 * @sb: The superblock
 */
static void ext4_maybe_update_superblock(struct super_block *sb)
{}

static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
{}

/*
 * This writepage callback for write_cache_pages()
 * takes care of a few cases after page cleaning.
 *
 * write_cache_pages() already checks for dirty pages
 * and calls clear_page_dirty_for_io(), which we want,
 * to write protect the pages.
 *
 * However, we may have to redirty a page (see below.)
 */
static int ext4_journalled_writepage_callback(struct folio *folio,
					      struct writeback_control *wbc,
					      void *data)
{}

static int ext4_journalled_submit_inode_data_buffers(struct jbd2_inode *jinode)
{}

static int ext4_journal_submit_inode_data_buffers(struct jbd2_inode *jinode)
{}

static int ext4_journal_finish_inode_data_buffers(struct jbd2_inode *jinode)
{}

static bool system_going_down(void)
{}

struct ext4_err_translation {};

#define EXT4_ERR_TRANSLATE(err)

static struct ext4_err_translation err_translation[] =;

static int ext4_errno_to_code(int errno)
{}

static void save_error_info(struct super_block *sb, int error,
			    __u32 ino, __u64 block,
			    const char *func, unsigned int line)
{}

/* Deal with the reporting of failure conditions on a filesystem such as
 * inconsistencies detected or read IO failures.
 *
 * On ext2, we can store the error state of the filesystem in the
 * superblock.  That is not possible on ext4, because we may have other
 * write ordering constraints on the superblock which prevent us from
 * writing it out straight away; and given that the journal is about to
 * be aborted, we can't rely on the current, or future, transactions to
 * write out the superblock safely.
 *
 * We'll just use the jbd2_journal_abort() error code to record an error in
 * the journal instead.  On recovery, the journal will complain about
 * that error until we've noted it down and cleared it.
 *
 * If force_ro is set, we unconditionally force the filesystem into an
 * ABORT|READONLY state, unless the error response on the fs has been set to
 * panic in which case we take the easy way out and panic immediately. This is
 * used to deal with unrecoverable failures such as journal IO errors or ENOMEM
 * at a critical moment in log management.
 */
static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
			      __u32 ino, __u64 block,
			      const char *func, unsigned int line)
{}

static void update_super_work(struct work_struct *work)
{}

#define ext4_error_ratelimit(sb)

void __ext4_error(struct super_block *sb, const char *function,
		  unsigned int line, bool force_ro, int error, __u64 block,
		  const char *fmt, ...)
{}

void __ext4_error_inode(struct inode *inode, const char *function,
			unsigned int line, ext4_fsblk_t block, int error,
			const char *fmt, ...)
{}

void __ext4_error_file(struct file *file, const char *function,
		       unsigned int line, ext4_fsblk_t block,
		       const char *fmt, ...)
{}

const char *ext4_decode_error(struct super_block *sb, int errno,
			      char nbuf[16])
{}

/* __ext4_std_error decodes expected errors from journaling functions
 * automatically and invokes the appropriate error response.  */

void __ext4_std_error(struct super_block *sb, const char *function,
		      unsigned int line, int errno)
{}

void __ext4_msg(struct super_block *sb,
		const char *prefix, const char *fmt, ...)
{}

static int ext4_warning_ratelimit(struct super_block *sb)
{}

void __ext4_warning(struct super_block *sb, const char *function,
		    unsigned int line, const char *fmt, ...)
{}

void __ext4_warning_inode(const struct inode *inode, const char *function,
			  unsigned int line, const char *fmt, ...)
{}

void __ext4_grp_locked_error(const char *function, unsigned int line,
			     struct super_block *sb, ext4_group_t grp,
			     unsigned long ino, ext4_fsblk_t block,
			     const char *fmt, ...)
__releases(bitlock)
__acquires(bitlock)
{}

void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
				     ext4_group_t group,
				     unsigned int flags)
{}

void ext4_update_dynamic_rev(struct super_block *sb)
{}

static inline struct inode *orphan_list_entry(struct list_head *l)
{}

static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi)
{}

#ifdef CONFIG_QUOTA
static int ext4_quota_off(struct super_block *sb, int type);

static inline void ext4_quotas_off(struct super_block *sb, int type)
{}

/*
 * This is a helper function which is used in the mount/remount
 * codepaths (which holds s_umount) to fetch the quota file name.
 */
static inline char *get_qf_name(struct super_block *sb,
				struct ext4_sb_info *sbi,
				int type)
{}
#else
static inline void ext4_quotas_off(struct super_block *sb, int type)
{
}
#endif

static int ext4_percpu_param_init(struct ext4_sb_info *sbi)
{}

static void ext4_percpu_param_destroy(struct ext4_sb_info *sbi)
{}

static void ext4_group_desc_free(struct ext4_sb_info *sbi)
{}

static void ext4_flex_groups_free(struct ext4_sb_info *sbi)
{}

static void ext4_put_super(struct super_block *sb)
{}

static struct kmem_cache *ext4_inode_cachep;

/*
 * Called inside transaction, so use GFP_NOFS
 */
static struct inode *ext4_alloc_inode(struct super_block *sb)
{}

static int ext4_drop_inode(struct inode *inode)
{}

static void ext4_free_in_core_inode(struct inode *inode)
{}

static void ext4_destroy_inode(struct inode *inode)
{}

static void ext4_shutdown(struct super_block *sb)
{}

static void init_once(void *foo)
{}

static int __init init_inodecache(void)
{}

static void destroy_inodecache(void)
{}

void ext4_clear_inode(struct inode *inode)
{}

static struct inode *ext4_nfs_get_inode(struct super_block *sb,
					u64 ino, u32 generation)
{}

static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid,
					int fh_len, int fh_type)
{}

static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
					int fh_len, int fh_type)
{}

static int ext4_nfs_commit_metadata(struct inode *inode)
{}

#ifdef CONFIG_QUOTA
static const char * const quotatypes[] = INITQFNAMES;
#define QTYPE2NAME(t)

static int ext4_write_dquot(struct dquot *dquot);
static int ext4_acquire_dquot(struct dquot *dquot);
static int ext4_release_dquot(struct dquot *dquot);
static int ext4_mark_dquot_dirty(struct dquot *dquot);
static int ext4_write_info(struct super_block *sb, int type);
static int ext4_quota_on(struct super_block *sb, int type, int format_id,
			 const struct path *path);
static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
			       size_t len, loff_t off);
static ssize_t ext4_quota_write(struct super_block *sb, int type,
				const char *data, size_t len, loff_t off);
static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
			     unsigned int flags);

static struct dquot __rcu **ext4_get_dquots(struct inode *inode)
{}

static const struct dquot_operations ext4_quota_operations =;

static const struct quotactl_ops ext4_qctl_operations =;
#endif

static const struct super_operations ext4_sops =;

static const struct export_operations ext4_export_ops =;

enum {};

static const struct constant_table ext4_param_errors[] =;

static const struct constant_table ext4_param_data[] =;

static const struct constant_table ext4_param_data_err[] =;

static const struct constant_table ext4_param_jqfmt[] =;

static const struct constant_table ext4_param_dax[] =;

/*
 * Mount option specification
 * We don't use fsparam_flag_no because of the way we set the
 * options and the way we show them in _ext4_show_options(). To
 * keep the changes to a minimum, let's keep the negative options
 * separate for now.
 */
static const struct fs_parameter_spec ext4_param_specs[] =;

#define DEFAULT_JOURNAL_IOPRIO

#define MOPT_SET
#define MOPT_CLEAR
#define MOPT_NOSUPPORT
#define MOPT_EXPLICIT
#ifdef CONFIG_QUOTA
#define MOPT_Q
#define MOPT_QFMT
#else
#define MOPT_Q
#define MOPT_QFMT
#endif
#define MOPT_NO_EXT2
#define MOPT_NO_EXT3
#define MOPT_EXT4_ONLY
#define MOPT_SKIP
#define MOPT_2

static const struct mount_opts {} ext4_mount_opts[] =;

#if IS_ENABLED(CONFIG_UNICODE)
static const struct ext4_sb_encodings {} ext4_sb_encoding_map[] =;

static const struct ext4_sb_encodings *
ext4_sb_read_encoding(const struct ext4_super_block *es)
{}
#endif

#define EXT4_SPEC_JQUOTA
#define EXT4_SPEC_JQFMT
#define EXT4_SPEC_DATAJ
#define EXT4_SPEC_SB_BLOCK
#define EXT4_SPEC_JOURNAL_DEV
#define EXT4_SPEC_JOURNAL_IOPRIO
#define EXT4_SPEC_s_want_extra_isize
#define EXT4_SPEC_s_max_batch_time
#define EXT4_SPEC_s_min_batch_time
#define EXT4_SPEC_s_inode_readahead_blks
#define EXT4_SPEC_s_li_wait_mult
#define EXT4_SPEC_s_max_dir_size_kb
#define EXT4_SPEC_s_stripe
#define EXT4_SPEC_s_resuid
#define EXT4_SPEC_s_resgid
#define EXT4_SPEC_s_commit_interval
#define EXT4_SPEC_s_fc_debug_max_replay
#define EXT4_SPEC_s_sb_block
#define EXT4_SPEC_mb_optimize_scan

struct ext4_fs_context {};

static void ext4_fc_free(struct fs_context *fc)
{}

int ext4_init_fs_context(struct fs_context *fc)
{}

#ifdef CONFIG_QUOTA
/*
 * Note the name of the specified quota file.
 */
static int note_qf_name(struct fs_context *fc, int qtype,
		       struct fs_parameter *param)
{}

/*
 * Clear the name of the specified quota file.
 */
static int unnote_qf_name(struct fs_context *fc, int qtype)
{}
#endif

static int ext4_parse_test_dummy_encryption(const struct fs_parameter *param,
					    struct ext4_fs_context *ctx)
{}

#define EXT4_SET_CTX(name)

#define EXT4_CLEAR_CTX(name)

#define EXT4_TEST_CTX(name)

EXT4_SET_CTX(flags); /* set only */
EXT4_SET_CTX(mount_opt);
EXT4_CLEAR_CTX(mount_opt);
EXT4_TEST_CTX(mount_opt);
EXT4_SET_CTX(mount_opt2);
EXT4_CLEAR_CTX(mount_opt2);
EXT4_TEST_CTX(mount_opt2);

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

static int parse_options(struct fs_context *fc, char *options)
{}

static int parse_apply_sb_mount_options(struct super_block *sb,
					struct ext4_fs_context *m_ctx)
{}

static void ext4_apply_quota_options(struct fs_context *fc,
				     struct super_block *sb)
{}

/*
 * Check quota settings consistency.
 */
static int ext4_check_quota_consistency(struct fs_context *fc,
					struct super_block *sb)
{}

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

static void ext4_apply_test_dummy_encryption(struct ext4_fs_context *ctx,
					     struct super_block *sb)
{}

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

static void ext4_apply_options(struct fs_context *fc, struct super_block *sb)
{}


static int ext4_validate_options(struct fs_context *fc)
{}

static inline void ext4_show_quota_options(struct seq_file *seq,
					   struct super_block *sb)
{}

static const char *token2str(int token)
{}

/*
 * Show an option if
 *  - it's set to a non-default value OR
 *  - if the per-sb default is different from the global default
 */
static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
			      int nodefs)
{}

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

int ext4_seq_options_show(struct seq_file *seq, void *offset)
{}

static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
			    int read_only)
{}

int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
{}

static int ext4_fill_flex_info(struct super_block *sb)
{}

static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group,
				   struct ext4_group_desc *gdp)
{}

int ext4_group_desc_csum_verify(struct super_block *sb, __u32 block_group,
				struct ext4_group_desc *gdp)
{}

void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
			      struct ext4_group_desc *gdp)
{}

/* Called at mount-time, super-block is locked */
static int ext4_check_descriptors(struct super_block *sb,
				  ext4_fsblk_t sb_block,
				  ext4_group_t *first_not_zeroed)
{}

/*
 * Maximal extent format file size.
 * Resulting logical blkno at s_maxbytes must fit in our on-disk
 * extent format containers, within a sector_t, and within i_blocks
 * in the vfs.  ext4 inode has 48 bits of i_block in fsblock units,
 * so that won't be a limiting factor.
 *
 * However there is other limiting factor. We do store extents in the form
 * of starting block and length, hence the resulting length of the extent
 * covering maximum file size must fit into on-disk format containers as
 * well. Given that length is always by 1 unit bigger than max unit (because
 * we count 0 as well) we have to lower the s_maxbytes by one fs block.
 *
 * Note, this does *not* consider any metadata overhead for vfs i_blocks.
 */
static loff_t ext4_max_size(int blkbits, int has_huge_files)
{}

/*
 * Maximal bitmap file size.  There is a direct, and {,double-,triple-}indirect
 * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
 * We need to be 1 filesystem block less than the 2^48 sector limit.
 */
static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
{}

static ext4_fsblk_t descriptor_loc(struct super_block *sb,
				   ext4_fsblk_t logical_sb_block, int nr)
{}

/**
 * ext4_get_stripe_size: Get the stripe size.
 * @sbi: In memory super block info
 *
 * If we have specified it via mount option, then
 * use the mount option value. If the value specified at mount time is
 * greater than the blocks per group use the super block value.
 * If the super block value is greater than blocks per group return 0.
 * Allocator needs it be less than blocks per group.
 *
 */
static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
{}

/*
 * Check whether this filesystem can be mounted based on
 * the features present and the RDONLY/RDWR mount requested.
 * Returns 1 if this filesystem can be mounted as requested,
 * 0 if it cannot be.
 */
int ext4_feature_set_ok(struct super_block *sb, int readonly)
{}

/*
 * This function is called once a day if we have errors logged
 * on the file system
 */
static void print_daily_error_info(struct timer_list *t)
{}

/* Find next suitable group and run ext4_init_inode_table */
static int ext4_run_li_request(struct ext4_li_request *elr)
{}

/*
 * Remove lr_request from the list_request and free the
 * request structure. Should be called with li_list_mtx held
 */
static void ext4_remove_li_request(struct ext4_li_request *elr)
{}

static void ext4_unregister_li_request(struct super_block *sb)
{}

static struct task_struct *ext4_lazyinit_task;

/*
 * This is the function where ext4lazyinit thread lives. It walks
 * through the request list searching for next scheduled filesystem.
 * When such a fs is found, run the lazy initialization request
 * (ext4_rn_li_request) and keep track of the time spend in this
 * function. Based on that time we compute next schedule time of
 * the request. When walking through the list is complete, compute
 * next waking time and put itself into sleep.
 */
static int ext4_lazyinit_thread(void *arg)
{}

static void ext4_clear_request_list(void)
{}

static int ext4_run_lazyinit_thread(void)
{}

/*
 * Check whether it make sense to run itable init. thread or not.
 * If there is at least one uninitialized inode table, return
 * corresponding group number, else the loop goes through all
 * groups and return total number of groups.
 */
static ext4_group_t ext4_has_uninit_itable(struct super_block *sb)
{}

static int ext4_li_info_new(void)
{}

static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
					    ext4_group_t start)
{}

int ext4_register_li_request(struct super_block *sb,
			     ext4_group_t first_not_zeroed)
{}

/*
 * We do not need to lock anything since this is called on
 * module unload.
 */
static void ext4_destroy_lazyinit_thread(void)
{}

static int set_journal_csum_feature_set(struct super_block *sb)
{}

/*
 * Note: calculating the overhead so we can be compatible with
 * historical BSD practice is quite difficult in the face of
 * clusters/bigalloc.  This is because multiple metadata blocks from
 * different block group can end up in the same allocation cluster.
 * Calculating the exact overhead in the face of clustered allocation
 * requires either O(all block bitmaps) in memory or O(number of block
 * groups**2) in time.  We will still calculate the superblock for
 * older file systems --- and if we come across with a bigalloc file
 * system with zero in s_overhead_clusters the estimate will be close to
 * correct especially for very large cluster sizes --- but for newer
 * file systems, it's better to calculate this figure once at mkfs
 * time, and store it in the superblock.  If the superblock value is
 * present (even for non-bigalloc file systems), we will use it.
 */
static int count_overhead(struct super_block *sb, ext4_group_t grp,
			  char *buf)
{}

/*
 * Compute the overhead and stash it in sbi->s_overhead
 */
int ext4_calculate_overhead(struct super_block *sb)
{}

static void ext4_set_resv_clusters(struct super_block *sb)
{}

static const char *ext4_quota_mode(struct super_block *sb)
{}

static void ext4_setup_csum_trigger(struct super_block *sb,
				    enum ext4_journal_trigger_type type,
				    void (*trigger)(
					struct jbd2_buffer_trigger_type *type,
					struct buffer_head *bh,
					void *mapped_data,
					size_t size))
{}

static void ext4_free_sbi(struct ext4_sb_info *sbi)
{}

static struct ext4_sb_info *ext4_alloc_sbi(struct super_block *sb)
{}

static void ext4_set_def_opts(struct super_block *sb,
			      struct ext4_super_block *es)
{}

static int ext4_handle_clustersize(struct super_block *sb)
{}

static void ext4_fast_commit_init(struct super_block *sb)
{}

static int ext4_inode_info_init(struct super_block *sb,
				struct ext4_super_block *es)
{}

#if IS_ENABLED(CONFIG_UNICODE)
static int ext4_encoding_init(struct super_block *sb, struct ext4_super_block *es)
{}
#else
static inline int ext4_encoding_init(struct super_block *sb, struct ext4_super_block *es)
{
	return 0;
}
#endif

static int ext4_init_metadata_csum(struct super_block *sb, struct ext4_super_block *es)
{}

static int ext4_check_feature_compatibility(struct super_block *sb,
					    struct ext4_super_block *es,
					    int silent)
{}

static int ext4_check_geometry(struct super_block *sb,
			       struct ext4_super_block *es)
{}

static int ext4_group_desc_init(struct super_block *sb,
				struct ext4_super_block *es,
				ext4_fsblk_t logical_sb_block,
				ext4_group_t *first_not_zeroed)
{}

static int ext4_load_and_init_journal(struct super_block *sb,
				      struct ext4_super_block *es,
				      struct ext4_fs_context *ctx)
{}

static int ext4_check_journal_data_mode(struct super_block *sb)
{}

static int ext4_load_super(struct super_block *sb, ext4_fsblk_t *lsb,
			   int silent)
{}

static void ext4_hash_info_init(struct super_block *sb)
{}

static int ext4_block_group_meta_init(struct super_block *sb, int silent)
{}

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

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

static int ext4_get_tree(struct fs_context *fc)
{}

/*
 * Setup any per-fs journal parameters now.  We'll do this both on
 * initial mount, once the journal has been initialised but before we've
 * done any recovery; and again on any subsequent remount.
 */
static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
{}

static struct inode *ext4_get_journal_inode(struct super_block *sb,
					     unsigned int journal_inum)
{}

static int ext4_journal_bmap(journal_t *journal, sector_t *block)
{}

static journal_t *ext4_open_inode_journal(struct super_block *sb,
					  unsigned int journal_inum)
{}

static struct file *ext4_get_journal_blkdev(struct super_block *sb,
					dev_t j_dev, ext4_fsblk_t *j_start,
					ext4_fsblk_t *j_len)
{}

static journal_t *ext4_open_dev_journal(struct super_block *sb,
					dev_t j_dev)
{}

static int ext4_load_journal(struct super_block *sb,
			     struct ext4_super_block *es,
			     unsigned long journal_devnum)
{}

/* Copy state of EXT4_SB(sb) into buffer for on-disk superblock */
static void ext4_update_super(struct super_block *sb)
{}

static int ext4_commit_super(struct super_block *sb)
{}

/*
 * Have we just finished recovery?  If so, and if we are mounting (or
 * remounting) the filesystem readonly, then we will end up with a
 * consistent fs on disk.  Record that fact.
 */
static int ext4_mark_recovery_complete(struct super_block *sb,
				       struct ext4_super_block *es)
{}

/*
 * If we are mounting (or read-write remounting) a filesystem whose journal
 * has recorded an error from a previous lifetime, move that error to the
 * main filesystem now.
 */
static int ext4_clear_journal_err(struct super_block *sb,
				   struct ext4_super_block *es)
{}

/*
 * Force the running and committing transactions to commit,
 * and wait on the commit.
 */
int ext4_force_commit(struct super_block *sb)
{}

static int ext4_sync_fs(struct super_block *sb, int wait)
{}

/*
 * LVM calls this function before a (read-only) snapshot is created.  This
 * gives us a chance to flush the journal completely and mark the fs clean.
 *
 * Note that only this function cannot bring a filesystem to be in a clean
 * state independently. It relies on upper layer to stop all data & metadata
 * modifications.
 */
static int ext4_freeze(struct super_block *sb)
{}

/*
 * Called by LVM after the snapshot is done.  We need to reset the RECOVER
 * flag here, even though the filesystem is not technically dirty yet.
 */
static int ext4_unfreeze(struct super_block *sb)
{}

/*
 * Structure to save mount options for ext4_remount's benefit
 */
struct ext4_mount_options {};

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

static int ext4_reconfigure(struct fs_context *fc)
{}

#ifdef CONFIG_QUOTA
static int ext4_statfs_project(struct super_block *sb,
			       kprojid_t projid, struct kstatfs *buf)
{}
#endif

static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
{}


#ifdef CONFIG_QUOTA

/*
 * Helper functions so that transaction is started before we acquire dqio_sem
 * to keep correct lock ordering of transaction > dqio_sem
 */
static inline struct inode *dquot_to_inode(struct dquot *dquot)
{}

static int ext4_write_dquot(struct dquot *dquot)
{}

static int ext4_acquire_dquot(struct dquot *dquot)
{}

static int ext4_release_dquot(struct dquot *dquot)
{}

static int ext4_mark_dquot_dirty(struct dquot *dquot)
{}

static int ext4_write_info(struct super_block *sb, int type)
{}

static void lockdep_set_quota_inode(struct inode *inode, int subclass)
{}

/*
 * Standard function to be called on quota_on
 */
static int ext4_quota_on(struct super_block *sb, int type, int format_id,
			 const struct path *path)
{}

static inline bool ext4_check_quota_inum(int type, unsigned long qf_inum)
{}

static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
			     unsigned int flags)
{}

/* Enable usage tracking for all quota types. */
int ext4_enable_quotas(struct super_block *sb)
{}

static int ext4_quota_off(struct super_block *sb, int type)
{}

/* Read data from quotafile - avoid pagecache and such because we cannot afford
 * acquiring the locks... As quota files are never truncated and quota code
 * itself serializes the operations (and no one else should touch the files)
 * we don't have to be afraid of races */
static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
			       size_t len, loff_t off)
{}

/* Write to quotafile (we know the transaction is already started and has
 * enough credits) */
static ssize_t ext4_quota_write(struct super_block *sb, int type,
				const char *data, size_t len, loff_t off)
{}
#endif

#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
static inline void register_as_ext2(void)
{
	int err = register_filesystem(&ext2_fs_type);
	if (err)
		printk(KERN_WARNING
		       "EXT4-fs: Unable to register as ext2 (%d)\n", err);
}

static inline void unregister_as_ext2(void)
{
	unregister_filesystem(&ext2_fs_type);
}

static inline int ext2_feature_set_ok(struct super_block *sb)
{
	if (ext4_has_unknown_ext2_incompat_features(sb))
		return 0;
	if (sb_rdonly(sb))
		return 1;
	if (ext4_has_unknown_ext2_ro_compat_features(sb))
		return 0;
	return 1;
}
#else
static inline void register_as_ext2(void) {}
static inline void unregister_as_ext2(void) {}
static inline int ext2_feature_set_ok(struct super_block *sb) {}
#endif

static inline void register_as_ext3(void)
{}

static inline void unregister_as_ext3(void)
{}

static inline int ext3_feature_set_ok(struct super_block *sb)
{}

static void ext4_kill_sb(struct super_block *sb)
{}

static struct file_system_type ext4_fs_type =;
MODULE_ALIAS_FS();

/* Shared across all ext4 file systems */
wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];

static int __init ext4_init_fs(void)
{}

static void __exit ext4_exit_fs(void)
{}

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_SOFTDEP();
module_init()
module_exit()