#include <linux/mm.h>
#include <linux/bio.h>
#include <linux/err.h>
#include <linux/hash.h>
#include <linux/list.h>
#include <linux/log2.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/dm-io.h>
#include <linux/mutex.h>
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/blkdev.h>
#include <linux/kdev_t.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/mempool.h>
#include <linux/spinlock.h>
#include <linux/blk_types.h>
#include <linux/dm-kcopyd.h>
#include <linux/workqueue.h>
#include <linux/backing-dev.h>
#include <linux/device-mapper.h>
#include "dm.h"
#include "dm-clone-metadata.h"
#define DM_MSG_PREFIX …
#define MIN_REGION_SIZE …
#define MAX_REGION_SIZE …
#define MIN_HYDRATIONS …
#define DEFAULT_HYDRATION_THRESHOLD …
#define DEFAULT_HYDRATION_BATCH_SIZE …
#define COMMIT_PERIOD …
#define HASH_TABLE_BITS …
DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(…) …;
static struct kmem_cache *_hydration_cache;
enum clone_metadata_mode { … };
struct hash_table_bucket;
struct clone { … };
#define DM_CLONE_DISCARD_PASSDOWN …
#define DM_CLONE_HYDRATION_ENABLED …
#define DM_CLONE_HYDRATION_SUSPENDED …
static enum clone_metadata_mode get_clone_mode(struct clone *clone)
{ … }
static const char *clone_device_name(struct clone *clone)
{ … }
static void __set_clone_mode(struct clone *clone, enum clone_metadata_mode new_mode)
{ … }
static void __abort_transaction(struct clone *clone)
{ … }
static void __reload_in_core_bitset(struct clone *clone)
{ … }
static void __metadata_operation_failed(struct clone *clone, const char *op, int r)
{ … }
static inline void wakeup_hydration_waiters(struct clone *clone)
{ … }
static inline void wake_worker(struct clone *clone)
{ … }
static inline void remap_to_source(struct clone *clone, struct bio *bio)
{ … }
static inline void remap_to_dest(struct clone *clone, struct bio *bio)
{ … }
static bool bio_triggers_commit(struct clone *clone, struct bio *bio)
{ … }
static inline sector_t region_to_sector(struct clone *clone, unsigned long region_nr)
{ … }
static inline unsigned long bio_to_region(struct clone *clone, struct bio *bio)
{ … }
static void bio_region_range(struct clone *clone, struct bio *bio,
unsigned long *rs, unsigned long *nr_regions)
{ … }
static inline bool is_overwrite_bio(struct clone *clone, struct bio *bio)
{ … }
static void fail_bios(struct bio_list *bios, blk_status_t status)
{ … }
static void submit_bios(struct bio_list *bios)
{ … }
static void issue_bio(struct clone *clone, struct bio *bio)
{ … }
static void remap_and_issue(struct clone *clone, struct bio *bio)
{ … }
static void issue_deferred_bios(struct clone *clone, struct bio_list *bios)
{ … }
static void complete_overwrite_bio(struct clone *clone, struct bio *bio)
{ … }
static void trim_bio(struct bio *bio, sector_t sector, unsigned int len)
{ … }
static void complete_discard_bio(struct clone *clone, struct bio *bio, bool success)
{ … }
static void process_discard_bio(struct clone *clone, struct bio *bio)
{ … }
struct dm_clone_region_hydration { … };
struct hash_table_bucket { … };
#define bucket_lock_irqsave(bucket, flags) …
#define bucket_unlock_irqrestore(bucket, flags) …
#define bucket_lock_irq(bucket) …
#define bucket_unlock_irq(bucket) …
static int hash_table_init(struct clone *clone)
{ … }
static void hash_table_exit(struct clone *clone)
{ … }
static struct hash_table_bucket *get_hash_table_bucket(struct clone *clone,
unsigned long region_nr)
{ … }
static struct dm_clone_region_hydration *__hash_find(struct hash_table_bucket *bucket,
unsigned long region_nr)
{ … }
static inline void __insert_region_hydration(struct hash_table_bucket *bucket,
struct dm_clone_region_hydration *hd)
{ … }
static struct dm_clone_region_hydration *
__find_or_insert_region_hydration(struct hash_table_bucket *bucket,
struct dm_clone_region_hydration *hd)
{ … }
static struct dm_clone_region_hydration *alloc_hydration(struct clone *clone)
{ … }
static inline void free_hydration(struct dm_clone_region_hydration *hd)
{ … }
static void hydration_init(struct dm_clone_region_hydration *hd, unsigned long region_nr)
{ … }
static int hydration_update_metadata(struct dm_clone_region_hydration *hd)
{ … }
static void hydration_complete(struct dm_clone_region_hydration *hd)
{ … }
static void hydration_kcopyd_callback(int read_err, unsigned long write_err, void *context)
{ … }
static void hydration_copy(struct dm_clone_region_hydration *hd, unsigned int nr_regions)
{ … }
static void overwrite_endio(struct bio *bio)
{ … }
static void hydration_overwrite(struct dm_clone_region_hydration *hd, struct bio *bio)
{ … }
static void hydrate_bio_region(struct clone *clone, struct bio *bio)
{ … }
struct batch_info { … };
static void __batch_hydration(struct batch_info *batch,
struct dm_clone_region_hydration *hd)
{ … }
static unsigned long __start_next_hydration(struct clone *clone,
unsigned long offset,
struct batch_info *batch)
{ … }
static void do_hydration(struct clone *clone)
{ … }
static bool need_commit_due_to_time(struct clone *clone)
{ … }
static int commit_metadata(struct clone *clone, bool *dest_dev_flushed)
{ … }
static void process_deferred_discards(struct clone *clone)
{ … }
static void process_deferred_bios(struct clone *clone)
{ … }
static void process_deferred_flush_bios(struct clone *clone)
{ … }
static void do_worker(struct work_struct *work)
{ … }
static void do_waker(struct work_struct *work)
{ … }
static int clone_map(struct dm_target *ti, struct bio *bio)
{ … }
static int clone_endio(struct dm_target *ti, struct bio *bio, blk_status_t *error)
{ … }
static void emit_flags(struct clone *clone, char *result, unsigned int maxlen,
ssize_t *sz_ptr)
{ … }
static void emit_core_args(struct clone *clone, char *result,
unsigned int maxlen, ssize_t *sz_ptr)
{ … }
static void clone_status(struct dm_target *ti, status_type_t type,
unsigned int status_flags, char *result,
unsigned int maxlen)
{ … }
static sector_t get_dev_size(struct dm_dev *dev)
{ … }
static int parse_feature_args(struct dm_arg_set *as, struct clone *clone)
{ … }
static int parse_core_args(struct dm_arg_set *as, struct clone *clone)
{ … }
static int parse_region_size(struct clone *clone, struct dm_arg_set *as, char **error)
{ … }
static int validate_nr_regions(unsigned long n, char **error)
{ … }
static int parse_metadata_dev(struct clone *clone, struct dm_arg_set *as, char **error)
{ … }
static int parse_dest_dev(struct clone *clone, struct dm_arg_set *as, char **error)
{ … }
static int parse_source_dev(struct clone *clone, struct dm_arg_set *as, char **error)
{ … }
static int copy_ctr_args(struct clone *clone, int argc, const char **argv, char **error)
{ … }
static int clone_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{ … }
static void clone_dtr(struct dm_target *ti)
{ … }
static void clone_postsuspend(struct dm_target *ti)
{ … }
static void clone_resume(struct dm_target *ti)
{ … }
static void disable_passdown_if_not_supported(struct clone *clone)
{ … }
static void set_discard_limits(struct clone *clone, struct queue_limits *limits)
{ … }
static void clone_io_hints(struct dm_target *ti, struct queue_limits *limits)
{ … }
static int clone_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{ … }
static void set_hydration_threshold(struct clone *clone, unsigned int nr_regions)
{ … }
static void set_hydration_batch_size(struct clone *clone, unsigned int nr_regions)
{ … }
static void enable_hydration(struct clone *clone)
{ … }
static void disable_hydration(struct clone *clone)
{ … }
static int clone_message(struct dm_target *ti, unsigned int argc, char **argv,
char *result, unsigned int maxlen)
{ … }
static struct target_type clone_target = …;
static int __init dm_clone_init(void)
{ … }
static void __exit dm_clone_exit(void)
{ … }
module_init(…) …;
module_exit(dm_clone_exit);
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;