linux/fs/ocfs2/localalloc.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * localalloc.c
 *
 * Node local data allocation
 *
 * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
 */

#include <linux/fs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/bitops.h>

#include <cluster/masklog.h>

#include "ocfs2.h"

#include "alloc.h"
#include "blockcheck.h"
#include "dlmglue.h"
#include "inode.h"
#include "journal.h"
#include "localalloc.h"
#include "suballoc.h"
#include "super.h"
#include "sysfile.h"
#include "ocfs2_trace.h"

#include "buffer_head_io.h"

#define OCFS2_LOCAL_ALLOC(dinode)

static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc);

static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
					     struct ocfs2_dinode *alloc,
					     u32 *numbits,
					     struct ocfs2_alloc_reservation *resv);

static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc);

static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
				    handle_t *handle,
				    struct ocfs2_dinode *alloc,
				    struct inode *main_bm_inode,
				    struct buffer_head *main_bm_bh);

static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
						struct ocfs2_alloc_context **ac,
						struct inode **bitmap_inode,
						struct buffer_head **bitmap_bh);

static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
					handle_t *handle,
					struct ocfs2_alloc_context *ac);

static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
					  struct inode *local_alloc_inode);

/*
 * ocfs2_la_default_mb() - determine a default size, in megabytes of
 * the local alloc.
 *
 * Generally, we'd like to pick as large a local alloc as
 * possible. Performance on large workloads tends to scale
 * proportionally to la size. In addition to that, the reservations
 * code functions more efficiently as it can reserve more windows for
 * write.
 *
 * Some things work against us when trying to choose a large local alloc:
 *
 * - We need to ensure our sizing is picked to leave enough space in
 *   group descriptors for other allocations (such as block groups,
 *   etc). Picking default sizes which are a multiple of 4 could help
 *   - block groups are allocated in 2mb and 4mb chunks.
 *
 * - Likewise, we don't want to starve other nodes of bits on small
 *   file systems. This can easily be taken care of by limiting our
 *   default to a reasonable size (256M) on larger cluster sizes.
 *
 * - Some file systems can't support very large sizes - 4k and 8k in
 *   particular are limited to less than 128 and 256 megabytes respectively.
 *
 * The following reference table shows group descriptor and local
 * alloc maximums at various cluster sizes (4k blocksize)
 *
 * csize: 4K	group: 126M	la: 121M
 * csize: 8K	group: 252M	la: 243M
 * csize: 16K	group: 504M	la: 486M
 * csize: 32K	group: 1008M	la: 972M
 * csize: 64K	group: 2016M	la: 1944M
 * csize: 128K	group: 4032M	la: 3888M
 * csize: 256K	group: 8064M	la: 7776M
 * csize: 512K	group: 16128M	la: 15552M
 * csize: 1024K	group: 32256M	la: 31104M
 */
#define OCFS2_LA_MAX_DEFAULT_MB
#define OCFS2_LA_OLD_DEFAULT
unsigned int ocfs2_la_default_mb(struct ocfs2_super *osb)
{}

void ocfs2_la_set_sizes(struct ocfs2_super *osb, int requested_mb)
{}

static inline int ocfs2_la_state_enabled(struct ocfs2_super *osb)
{}

void ocfs2_local_alloc_seen_free_bits(struct ocfs2_super *osb,
				      unsigned int num_clusters)
{}

void ocfs2_la_enable_worker(struct work_struct *work)
{}

/*
 * Tell us whether a given allocation should use the local alloc
 * file. Otherwise, it has to go to the main bitmap.
 *
 * This function does semi-dirty reads of local alloc size and state!
 * This is ok however, as the values are re-checked once under mutex.
 */
int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits)
{}

int ocfs2_load_local_alloc(struct ocfs2_super *osb)
{}

/*
 * return any unused bits to the bitmap and write out a clean
 * local_alloc.
 *
 * local_alloc_bh is optional. If not passed, we will simply use the
 * one off osb. If you do pass it however, be warned that it *will* be
 * returned brelse'd and NULL'd out.*/
void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
{}

/*
 * We want to free the bitmap bits outside of any recovery context as
 * we'll need a cluster lock to do so, but we must clear the local
 * alloc before giving up the recovered nodes journal. To solve this,
 * we kmalloc a copy of the local alloc before it's change for the
 * caller to process with ocfs2_complete_local_alloc_recovery
 */
int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
				     int slot_num,
				     struct ocfs2_dinode **alloc_copy)
{}

/*
 * Step 2: By now, we've completed the journal recovery, we've stamped
 * a clean local alloc on disk and dropped the node out of the
 * recovery map. Dlm locks will no longer stall, so lets clear out the
 * main bitmap.
 */
int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb,
					struct ocfs2_dinode *alloc)
{}

/*
 * make sure we've got at least bits_wanted contiguous bits in the
 * local alloc. You lose them when you drop i_rwsem.
 *
 * We will add ourselves to the transaction passed in, but may start
 * our own in order to shift windows.
 */
int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
				   u32 bits_wanted,
				   struct ocfs2_alloc_context *ac)
{}

int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
				 handle_t *handle,
				 struct ocfs2_alloc_context *ac,
				 u32 bits_wanted,
				 u32 *bit_off,
				 u32 *num_bits)
{}

int ocfs2_free_local_alloc_bits(struct ocfs2_super *osb,
				handle_t *handle,
				struct ocfs2_alloc_context *ac,
				u32 bit_off,
				u32 num_bits)
{}

static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc)
{}

static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
				     struct ocfs2_dinode *alloc,
				     u32 *numbits,
				     struct ocfs2_alloc_reservation *resv)
{}

static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc)
{}

#if 0
/* turn this on and uncomment below to aid debugging window shifts. */
static void ocfs2_verify_zero_bits(unsigned long *bitmap,
				   unsigned int start,
				   unsigned int count)
{
	unsigned int tmp = count;
	while(tmp--) {
		if (ocfs2_test_bit(start + tmp, bitmap)) {
			printk("ocfs2_verify_zero_bits: start = %u, count = "
			       "%u\n", start, count);
			printk("ocfs2_verify_zero_bits: bit %u is set!",
			       start + tmp);
			BUG();
		}
	}
}
#endif

/*
 * sync the local alloc to main bitmap.
 *
 * assumes you've already locked the main bitmap -- the bitmap inode
 * passed is used for caching.
 */
static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
				    handle_t *handle,
				    struct ocfs2_dinode *alloc,
				    struct inode *main_bm_inode,
				    struct buffer_head *main_bm_bh)
{}

enum ocfs2_la_event {};
#define OCFS2_LA_ENABLE_INTERVAL
/*
 * Given an event, calculate the size of our next local alloc window.
 *
 * This should always be called under i_rwsem of the local alloc inode
 * so that local alloc disabling doesn't race with processes trying to
 * use the allocator.
 *
 * Returns the state which the local alloc was left in. This value can
 * be ignored by some paths.
 */
static int ocfs2_recalc_la_window(struct ocfs2_super *osb,
				  enum ocfs2_la_event event)
{}

static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
						struct ocfs2_alloc_context **ac,
						struct inode **bitmap_inode,
						struct buffer_head **bitmap_bh)
{}

/*
 * pass it the bitmap lock in lock_bh if you have it.
 */
static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
					handle_t *handle,
					struct ocfs2_alloc_context *ac)
{}

/* Note that we do *NOT* lock the local alloc inode here as
 * it's been locked already for us. */
static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
					  struct inode *local_alloc_inode)
{}