linux/drivers/md/dm-region-hash.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2003 Sistina Software Limited.
 * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
 *
 * This file is released under the GPL.
 */

#include <linux/dm-dirty-log.h>
#include <linux/dm-region-hash.h>

#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>

#include "dm.h"

#define DM_MSG_PREFIX

/*
 *------------------------------------------------------------------
 * Region hash
 *
 * The mirror splits itself up into discrete regions.  Each
 * region can be in one of three states: clean, dirty,
 * nosync.  There is no need to put clean regions in the hash.
 *
 * In addition to being present in the hash table a region _may_
 * be present on one of three lists.
 *
 *   clean_regions: Regions on this list have no io pending to
 *   them, they are in sync, we are no longer interested in them,
 *   they are dull.  dm_rh_update_states() will remove them from the
 *   hash table.
 *
 *   quiesced_regions: These regions have been spun down, ready
 *   for recovery.  rh_recovery_start() will remove regions from
 *   this list and hand them to kmirrord, which will schedule the
 *   recovery io with kcopyd.
 *
 *   recovered_regions: Regions that kcopyd has successfully
 *   recovered.  dm_rh_update_states() will now schedule any delayed
 *   io, up the recovery_count, and remove the region from the
 *   hash.
 *
 * There are 2 locks:
 *   A rw spin lock 'hash_lock' protects just the hash table,
 *   this is never held in write mode from interrupt context,
 *   which I believe means that we only have to disable irqs when
 *   doing a write lock.
 *
 *   An ordinary spin lock 'region_lock' that protects the three
 *   lists in the region_hash, with the 'state', 'list' and
 *   'delayed_bios' fields of the regions.  This is used from irq
 *   context, so all other uses will have to suspend local irqs.
 *------------------------------------------------------------------
 */
struct dm_region_hash {};

struct dm_region {};

/*
 * Conversion fns
 */
static region_t dm_rh_sector_to_region(struct dm_region_hash *rh, sector_t sector)
{}

sector_t dm_rh_region_to_sector(struct dm_region_hash *rh, region_t region)
{}
EXPORT_SYMBOL_GPL();

region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio)
{}
EXPORT_SYMBOL_GPL();

void *dm_rh_region_context(struct dm_region *reg)
{}
EXPORT_SYMBOL_GPL();

region_t dm_rh_get_region_key(struct dm_region *reg)
{}
EXPORT_SYMBOL_GPL();

sector_t dm_rh_get_region_size(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

/*
 * FIXME: shall we pass in a structure instead of all these args to
 * dm_region_hash_create()????
 */
#define RH_HASH_MULT
#define RH_HASH_SHIFT

#define MIN_REGIONS
struct dm_region_hash *dm_region_hash_create(
		void *context, void (*dispatch_bios)(void *context,
						     struct bio_list *bios),
		void (*wakeup_workers)(void *context),
		void (*wakeup_all_recovery_waiters)(void *context),
		sector_t target_begin, unsigned int max_recovery,
		struct dm_dirty_log *log, uint32_t region_size,
		region_t nr_regions)
{}
EXPORT_SYMBOL_GPL();

void dm_region_hash_destroy(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

static unsigned int rh_hash(struct dm_region_hash *rh, region_t region)
{}

static struct dm_region *__rh_lookup(struct dm_region_hash *rh, region_t region)
{}

static void __rh_insert(struct dm_region_hash *rh, struct dm_region *reg)
{}

static struct dm_region *__rh_alloc(struct dm_region_hash *rh, region_t region)
{}

static struct dm_region *__rh_find(struct dm_region_hash *rh, region_t region)
{}

int dm_rh_get_state(struct dm_region_hash *rh, region_t region, int may_block)
{}
EXPORT_SYMBOL_GPL();

static void complete_resync_work(struct dm_region *reg, int success)
{}

/* dm_rh_mark_nosync
 * @ms
 * @bio
 *
 * The bio was written on some mirror(s) but failed on other mirror(s).
 * We can successfully endio the bio but should avoid the region being
 * marked clean by setting the state DM_RH_NOSYNC.
 *
 * This function is _not_ safe in interrupt context!
 */
void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio)
{}
EXPORT_SYMBOL_GPL();

void dm_rh_update_states(struct dm_region_hash *rh, int errors_handled)
{}
EXPORT_SYMBOL_GPL();

static void rh_inc(struct dm_region_hash *rh, region_t region)
{}

void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
{}
EXPORT_SYMBOL_GPL();

void dm_rh_dec(struct dm_region_hash *rh, region_t region)
{}
EXPORT_SYMBOL_GPL();

/*
 * Starts quiescing a region in preparation for recovery.
 */
static int __rh_recovery_prepare(struct dm_region_hash *rh)
{}

void dm_rh_recovery_prepare(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

/*
 * Returns any quiesced regions.
 */
struct dm_region *dm_rh_recovery_start(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

void dm_rh_recovery_end(struct dm_region *reg, int success)
{}
EXPORT_SYMBOL_GPL();

/* Return recovery in flight count. */
int dm_rh_recovery_in_flight(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

int dm_rh_flush(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

void dm_rh_delay(struct dm_region_hash *rh, struct bio *bio)
{}
EXPORT_SYMBOL_GPL();

void dm_rh_stop_recovery(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

void dm_rh_start_recovery(struct dm_region_hash *rh)
{}
EXPORT_SYMBOL_GPL();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();