/*
* Copyright (C) 2003 Sistina Software Limited.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This file is released under the GPL.
*/
#include "dm.h"
#include "dm-path-selector.h"
#include "dm-hw-handler.h"
#include "dm-bio-list.h"
#include "dm-bio-record.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/workqueue.h>
#include <asm/atomic.h>
#define MESG_STR(x) x, sizeof(x)
/* Path properties */
struct pgpath {
struct list_head list;
struct priority_group *pg; /* Owning PG */
unsigned fail_count; /* Cumulative failure count */
struct path path;
};
#define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
/*
* Paths are grouped into Priority Groups and numbered from 1 upwards.
* Each has a path selector which controls which path gets used.
*/
struct priority_group {
struct list_head list;
struct multipath *m; /* Owning multipath instance */
struct path_selector ps;
unsigned pg_num; /* Reference number */
unsigned bypassed; /* Temporarily bypass this PG? */
unsigned nr_pgpaths; /* Number of paths in PG */
struct list_head pgpaths;
};
/* Multipath context */
struct multipath {
struct list_head list;
struct dm_target *ti;
spinlock_t lock;
struct hw_handler hw_handler;
unsigned nr_priority_groups;
struct list_head priority_groups;
unsigned pg_init_required; /* pg_init needs calling? */
unsigned pg_init_in_progress; /* Only one pg_init allowed at once */
unsigned nr_valid_paths; /* Total number of usable paths */
struct pgpath *current_pgpath;
struct priority_group *current_pg;
struct priority_group *next_pg; /* Switch to this PG if set */
unsigned repeat_count; /* I/Os left before calling PS again */
unsigned queue_io; /* Must we queue all I/O? */
unsigned queue_if_no_path; /* Queue I/O if last path fails? */
unsigned saved_queue_if_no_path;/* Saved state during suspension */
struct work_struct process_queued_ios;
struct bio_list queued_ios;
unsigned queue_size;
struct work_struct trigger_event;
/*
* We must use a mempool of mpath_io structs so that we
* can resubmit bios on error.
*/
mempool_t *mpio_pool;
};
/*
* Context information attached to each bio we process.
*/
struct mpath_io {
struct pgpath *pgpath;
struct dm_bio_details details;
};
typedef int (*action_fn) (struct pgpath *pgpath);
#define MIN_IOS 256 /* Mempool size */
static kmem_cache_t *_mpio_cache;
struct workqueue_struct *kmultipathd;
static void process_queued_ios(void *data);
static void trigger_event(void *data);
/*-----------------------------------------------
* Allocation routines
*-----------------------------------------------*/
static struct pgpath *alloc_pgpath(void)
{
struct pgpath *pgpath = kmalloc(sizeof(*pgpath), GFP_KERNEL);
if (pgpath) {
memset(pgpath, 0, sizeof