#include <linux/device-mapper.h>
#include "dm-rq.h"
#include "dm-bio-record.h"
#include "dm-path-selector.h"
#include "dm-uevent.h"
#include <linux/blkdev.h>
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <scsi/scsi_dh.h>
#include <linux/atomic.h>
#include <linux/blk-mq.h>
static struct workqueue_struct *dm_mpath_wq;
#define DM_MSG_PREFIX …
#define DM_PG_INIT_DELAY_MSECS …
#define DM_PG_INIT_DELAY_DEFAULT …
#define QUEUE_IF_NO_PATH_TIMEOUT_DEFAULT …
static unsigned long queue_if_no_path_timeout_secs = …;
struct pgpath { … };
#define path_to_pgpath(__pgp) …
struct priority_group { … };
struct multipath { … };
struct dm_mpath_io { … };
action_fn;
static struct workqueue_struct *kmultipathd, *kmpath_handlerd;
static void trigger_event(struct work_struct *work);
static void activate_or_offline_path(struct pgpath *pgpath);
static void activate_path_work(struct work_struct *work);
static void process_queued_bios(struct work_struct *work);
static void queue_if_no_path_timeout_work(struct timer_list *t);
#define MPATHF_QUEUE_IO …
#define MPATHF_QUEUE_IF_NO_PATH …
#define MPATHF_SAVED_QUEUE_IF_NO_PATH …
#define MPATHF_RETAIN_ATTACHED_HW_HANDLER …
#define MPATHF_PG_INIT_DISABLED …
#define MPATHF_PG_INIT_REQUIRED …
#define MPATHF_PG_INIT_DELAY_RETRY …
static bool mpath_double_check_test_bit(int MPATHF_bit, struct multipath *m)
{ … }
static struct pgpath *alloc_pgpath(void)
{ … }
static void free_pgpath(struct pgpath *pgpath)
{ … }
static struct priority_group *alloc_priority_group(void)
{ … }
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
{ … }
static void free_priority_group(struct priority_group *pg,
struct dm_target *ti)
{ … }
static struct multipath *alloc_multipath(struct dm_target *ti)
{ … }
static int alloc_multipath_stage2(struct dm_target *ti, struct multipath *m)
{ … }
static void free_multipath(struct multipath *m)
{ … }
static struct dm_mpath_io *get_mpio(union map_info *info)
{ … }
static size_t multipath_per_bio_data_size(void)
{ … }
static struct dm_mpath_io *get_mpio_from_bio(struct bio *bio)
{ … }
static struct dm_bio_details *get_bio_details_from_mpio(struct dm_mpath_io *mpio)
{ … }
static void multipath_init_per_bio_data(struct bio *bio, struct dm_mpath_io **mpio_p)
{ … }
static int __pg_init_all_paths(struct multipath *m)
{ … }
static int pg_init_all_paths(struct multipath *m)
{ … }
static void __switch_pg(struct multipath *m, struct priority_group *pg)
{ … }
static struct pgpath *choose_path_in_pg(struct multipath *m,
struct priority_group *pg,
size_t nr_bytes)
{ … }
static struct pgpath *choose_pgpath(struct multipath *m, size_t nr_bytes)
{ … }
#define dm_report_EIO(m) …
static bool __must_push_back(struct multipath *m)
{ … }
static bool must_push_back_rq(struct multipath *m)
{ … }
static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
union map_info *map_context,
struct request **__clone)
{ … }
static void multipath_release_clone(struct request *clone,
union map_info *map_context)
{ … }
static void __multipath_queue_bio(struct multipath *m, struct bio *bio)
{ … }
static void multipath_queue_bio(struct multipath *m, struct bio *bio)
{ … }
static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
{ … }
static int __multipath_map_bio(struct multipath *m, struct bio *bio,
struct dm_mpath_io *mpio)
{ … }
static int multipath_map_bio(struct dm_target *ti, struct bio *bio)
{ … }
static void process_queued_io_list(struct multipath *m)
{ … }
static void process_queued_bios(struct work_struct *work)
{ … }
static int queue_if_no_path(struct multipath *m, bool f_queue_if_no_path,
bool save_old_value, const char *caller)
{ … }
static void queue_if_no_path_timeout_work(struct timer_list *t)
{ … }
static void enable_nopath_timeout(struct multipath *m)
{ … }
static void disable_nopath_timeout(struct multipath *m)
{ … }
static void trigger_event(struct work_struct *work)
{ … }
static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg,
struct dm_target *ti)
{ … }
static int setup_scsi_dh(struct block_device *bdev, struct multipath *m,
const char **attached_handler_name, char **error)
{ … }
static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps,
struct dm_target *ti)
{ … }
static struct priority_group *parse_priority_group(struct dm_arg_set *as,
struct multipath *m)
{ … }
static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m)
{ … }
static int parse_features(struct dm_arg_set *as, struct multipath *m)
{ … }
static int multipath_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{ … }
static void multipath_wait_for_pg_init_completion(struct multipath *m)
{ … }
static void flush_multipath_work(struct multipath *m)
{ … }
static void multipath_dtr(struct dm_target *ti)
{ … }
static int fail_path(struct pgpath *pgpath)
{ … }
static int reinstate_path(struct pgpath *pgpath)
{ … }
static int action_dev(struct multipath *m, dev_t dev, action_fn action)
{ … }
static void bypass_pg(struct multipath *m, struct priority_group *pg,
bool bypassed)
{ … }
static int switch_pg_num(struct multipath *m, const char *pgstr)
{ … }
static int bypass_pg_num(struct multipath *m, const char *pgstr, bool bypassed)
{ … }
static bool pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath)
{ … }
static void pg_init_done(void *data, int errors)
{ … }
static void activate_or_offline_path(struct pgpath *pgpath)
{ … }
static void activate_path_work(struct work_struct *work)
{ … }
static int multipath_end_io(struct dm_target *ti, struct request *clone,
blk_status_t error, union map_info *map_context)
{ … }
static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone,
blk_status_t *error)
{ … }
static void multipath_presuspend(struct dm_target *ti)
{ … }
static void multipath_postsuspend(struct dm_target *ti)
{ … }
static void multipath_resume(struct dm_target *ti)
{ … }
static void multipath_status(struct dm_target *ti, status_type_t type,
unsigned int status_flags, char *result, unsigned int maxlen)
{ … }
static int multipath_message(struct dm_target *ti, unsigned int argc, char **argv,
char *result, unsigned int maxlen)
{ … }
static int multipath_prepare_ioctl(struct dm_target *ti,
struct block_device **bdev)
{ … }
static int multipath_iterate_devices(struct dm_target *ti,
iterate_devices_callout_fn fn, void *data)
{ … }
static int pgpath_busy(struct pgpath *pgpath)
{ … }
static int multipath_busy(struct dm_target *ti)
{ … }
static struct target_type multipath_target = …;
static int __init dm_multipath_init(void)
{ … }
static void __exit dm_multipath_exit(void)
{ … }
module_init(…) …;
module_exit(dm_multipath_exit);
module_param_named(queue_if_no_path_timeout_secs, queue_if_no_path_timeout_secs, ulong, 0644);
MODULE_PARM_DESC(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;