linux/fs/ext4/resize.c

// SPDX-License-Identifier: GPL-2.0
/*
 *  linux/fs/ext4/resize.c
 *
 * Support for resizing an ext4 filesystem while it is mounted.
 *
 * Copyright (C) 2001, 2002 Andreas Dilger <[email protected]>
 *
 * This could probably be made into a module, because it is not often in use.
 */


#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/jiffies.h>

#include "ext4_jbd2.h"

struct ext4_rcu_ptr {};

static void ext4_rcu_ptr_callback(struct rcu_head *head)
{}

void ext4_kvfree_array_rcu(void *to_free)
{}

int ext4_resize_begin(struct super_block *sb)
{}

int ext4_resize_end(struct super_block *sb, bool update_backups)
{}

static ext4_grpblk_t ext4_group_overhead_blocks(struct super_block *sb,
						ext4_group_t group) {}

#define outside(b, first, last)
#define inside(b, first, last)

static int verify_group_input(struct super_block *sb,
			      struct ext4_new_group_data *input)
{}

/*
 * ext4_new_flex_group_data is used by 64bit-resize interface to add a flex
 * group each time.
 */
struct ext4_new_flex_group_data {};

/*
 * Avoiding memory allocation failures due to too many groups added each time.
 */
#define MAX_RESIZE_BG

/*
 * alloc_flex_gd() allocates a ext4_new_flex_group_data with size of
 * @flexbg_size.
 *
 * Returns NULL on failure otherwise address of the allocated structure.
 */
static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned int flexbg_size,
				ext4_group_t o_group, ext4_group_t n_group)
{}

static void free_flex_gd(struct ext4_new_flex_group_data *flex_gd)
{}

/*
 * ext4_alloc_group_tables() allocates block bitmaps, inode bitmaps
 * and inode tables for a flex group.
 *
 * This function is used by 64bit-resize.  Note that this function allocates
 * group tables from the 1st group of groups contained by @flexgd, which may
 * be a partial of a flex group.
 *
 * @sb: super block of fs to which the groups belongs
 *
 * Returns 0 on a successful allocation of the metadata blocks in the
 * block group.
 */
static int ext4_alloc_group_tables(struct super_block *sb,
				struct ext4_new_flex_group_data *flex_gd,
				unsigned int flexbg_size)
{}

static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
				  ext4_fsblk_t blk)
{}

static int ext4_resize_ensure_credits_batch(handle_t *handle, int credits)
{}

/*
 * set_flexbg_block_bitmap() mark clusters [@first_cluster, @last_cluster] used.
 *
 * Helper function for ext4_setup_new_group_blocks() which set .
 *
 * @sb: super block
 * @handle: journal handle
 * @flex_gd: flex group data
 */
static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
			struct ext4_new_flex_group_data *flex_gd,
			ext4_fsblk_t first_cluster, ext4_fsblk_t last_cluster)
{}

/*
 * Set up the block and inode bitmaps, and the inode table for the new groups.
 * This doesn't need to be part of the main transaction, since we are only
 * changing blocks outside the actual filesystem.  We still do journaling to
 * ensure the recovery is correct in case of a failure just after resize.
 * If any part of this fails, we simply abort the resize.
 *
 * setup_new_flex_group_blocks handles a flex group as follow:
 *  1. copy super block and GDT, and initialize group tables if necessary.
 *     In this step, we only set bits in blocks bitmaps for blocks taken by
 *     super block and GDT.
 *  2. allocate group tables in block bitmaps, that is, set bits in block
 *     bitmap for blocks taken by group tables.
 */
static int setup_new_flex_group_blocks(struct super_block *sb,
				struct ext4_new_flex_group_data *flex_gd)
{}

/*
 * Iterate through the groups which hold BACKUP superblock/GDT copies in an
 * ext4 filesystem.  The counters should be initialized to 1, 5, and 7 before
 * calling this for the first time.  In a sparse filesystem it will be the
 * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
 * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
 */
unsigned int ext4_list_backups(struct super_block *sb, unsigned int *three,
			       unsigned int *five, unsigned int *seven)
{}

/*
 * Check that all of the backup GDT blocks are held in the primary GDT block.
 * It is assumed that they are stored in group order.  Returns the number of
 * groups in current filesystem that have BACKUPS, or -ve error code.
 */
static int verify_reserved_gdb(struct super_block *sb,
			       ext4_group_t end,
			       struct buffer_head *primary)
{}

/*
 * Called when we need to bring a reserved group descriptor table block into
 * use from the resize inode.  The primary copy of the new GDT block currently
 * is an indirect block (under the double indirect block in the resize inode).
 * The new backup GDT blocks will be stored as leaf blocks in this indirect
 * block, in group order.  Even though we know all the block numbers we need,
 * we check to ensure that the resize inode has actually reserved these blocks.
 *
 * Don't need to update the block bitmaps because the blocks are still in use.
 *
 * We get all of the error cases out of the way, so that we are sure to not
 * fail once we start modifying the data on disk, because JBD has no rollback.
 */
static int add_new_gdb(handle_t *handle, struct inode *inode,
		       ext4_group_t group)
{}

/*
 * If there is no available space in the existing block group descriptors for
 * the new block group and there are no reserved block group descriptors, then
 * the meta_bg feature will get enabled, and es->s_first_meta_bg will get set
 * to the first block group that is managed using meta_bg and s_first_meta_bg
 * must be a multiple of EXT4_DESC_PER_BLOCK(sb).
 * This function will be called when first group of meta_bg is added to bring
 * new group descriptors block of new added meta_bg.
 */
static int add_new_gdb_meta_bg(struct super_block *sb,
			       handle_t *handle, ext4_group_t group) {}

/*
 * Called when we are adding a new group which has a backup copy of each of
 * the GDT blocks (i.e. sparse group) and there are reserved GDT blocks.
 * We need to add these reserved backup GDT blocks to the resize inode, so
 * that they are kept for future resizing and not allocated to files.
 *
 * Each reserved backup GDT block will go into a different indirect block.
 * The indirect blocks are actually the primary reserved GDT blocks,
 * so we know in advance what their block numbers are.  We only get the
 * double-indirect block to verify it is pointing to the primary reserved
 * GDT blocks so we don't overwrite a data block by accident.  The reserved
 * backup GDT blocks are stored in their reserved primary GDT block.
 */
static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
			      ext4_group_t group)
{}

static inline void ext4_set_block_group_nr(struct super_block *sb, char *data,
					   ext4_group_t group)
{}

/*
 * Update the backup copies of the ext4 metadata.  These don't need to be part
 * of the main resize transaction, because e2fsck will re-write them if there
 * is a problem (basically only OOM will cause a problem).  However, we
 * _should_ update the backups if possible, in case the primary gets trashed
 * for some reason and we need to run e2fsck from a backup superblock.  The
 * important part is that the new block and inode counts are in the backup
 * superblocks, and the location of the new group metadata in the GDT backups.
 *
 * We do not need take the s_resize_lock for this, because these
 * blocks are not otherwise touched by the filesystem code when it is
 * mounted.  We don't need to worry about last changing from
 * sbi->s_groups_count, because the worst that can happen is that we
 * do not copy the full number of backups at this time.  The resize
 * which changed s_groups_count will backup again.
 */
static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
			   int size, int meta_bg)
{}

/*
 * ext4_add_new_descs() adds @count group descriptor of groups
 * starting at @group
 *
 * @handle: journal handle
 * @sb: super block
 * @group: the group no. of the first group desc to be added
 * @resize_inode: the resize inode
 * @count: number of group descriptors to be added
 */
static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
			      ext4_group_t group, struct inode *resize_inode,
			      ext4_group_t count)
{}

static struct buffer_head *ext4_get_bitmap(struct super_block *sb, __u64 block)
{}

static int ext4_set_bitmap_checksums(struct super_block *sb,
				     struct ext4_group_desc *gdp,
				     struct ext4_new_group_data *group_data)
{}

/*
 * ext4_setup_new_descs() will set up the group descriptor descriptors of a flex bg
 */
static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,
				struct ext4_new_flex_group_data *flex_gd)
{}

static void ext4_add_overhead(struct super_block *sb,
                              const ext4_fsblk_t overhead)
{}

/*
 * ext4_update_super() updates the super block so that the newly added
 * groups can be seen by the filesystem.
 *
 * @sb: super block
 * @flex_gd: new added groups
 */
static void ext4_update_super(struct super_block *sb,
			     struct ext4_new_flex_group_data *flex_gd)
{}

/* Add a flex group to an fs. Ensure we handle all possible error conditions
 * _before_ we start modifying the filesystem, because we cannot abort the
 * transaction and not have it write the data to disk.
 */
static int ext4_flex_group_add(struct super_block *sb,
			       struct inode *resize_inode,
			       struct ext4_new_flex_group_data *flex_gd)
{}

static int ext4_setup_next_flex_gd(struct super_block *sb,
				    struct ext4_new_flex_group_data *flex_gd,
				    ext4_fsblk_t n_blocks_count)
{}

/* Add group descriptor data to an existing or new group descriptor block.
 * Ensure we handle all possible error conditions _before_ we start modifying
 * the filesystem, because we cannot abort the transaction and not have it
 * write the data to disk.
 *
 * If we are on a GDT block boundary, we need to get the reserved GDT block.
 * Otherwise, we may need to add backup GDT blocks for a sparse group.
 *
 * We only need to hold the superblock lock while we are actually adding
 * in the new group's counts to the superblock.  Prior to that we have
 * not really "added" the group at all.  We re-check that we are still
 * adding in the last group in case things have changed since verifying.
 */
int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
{} /* ext4_group_add */

/*
 * extend a group without checking assuming that checking has been done.
 */
static int ext4_group_extend_no_check(struct super_block *sb,
				      ext4_fsblk_t o_blocks_count, ext4_grpblk_t add)
{}

/*
 * Extend the filesystem to the new number of blocks specified.  This entry
 * point is only used to extend the current filesystem to the end of the last
 * existing group.  It can be accessed via ioctl, or by "remount,resize=<size>"
 * for emergencies (because it has no dependencies on reserved blocks).
 *
 * If we _really_ wanted, we could use default values to call ext4_group_add()
 * allow the "remount" trick to work for arbitrary resizing, assuming enough
 * GDT blocks are reserved to grow to the desired size.
 */
int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
		      ext4_fsblk_t n_blocks_count)
{} /* ext4_group_extend */


static int num_desc_blocks(struct super_block *sb, ext4_group_t groups)
{}

/*
 * Release the resize inode and drop the resize_inode feature if there
 * are no more reserved gdt blocks, and then convert the file system
 * to enable meta_bg
 */
static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
{}

/*
 * ext4_resize_fs() resizes a fs to new size specified by @n_blocks_count
 *
 * @sb: super block of the fs to be resized
 * @n_blocks_count: the number of blocks resides in the resized fs
 */
int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
{}