⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dm-mpath.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return 0;}struct arg_set {	unsigned argc;	char **argv;};static char *shift(struct arg_set *as){	char *r;	if (as->argc) {		as->argc--;		r = *as->argv;		as->argv++;		return r;	}	return NULL;}static void consume(struct arg_set *as, unsigned n){	BUG_ON (as->argc < n);	as->argc -= n;	as->argv += n;}static int parse_path_selector(struct arg_set *as, struct priority_group *pg,			       struct dm_target *ti){	int r;	struct path_selector_type *pst;	unsigned ps_argc;	static struct param _params[] = {		{0, 1024, "invalid number of path selector args"},	};	pst = dm_get_path_selector(shift(as));	if (!pst) {		ti->error = "unknown path selector type";		return -EINVAL;	}	r = read_param(_params, shift(as), &ps_argc, &ti->error);	if (r)		return -EINVAL;	r = pst->create(&pg->ps, ps_argc, as->argv);	if (r) {		dm_put_path_selector(pst);		ti->error = "path selector constructor failed";		return r;	}	pg->ps.type = pst;	consume(as, ps_argc);	return 0;}static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,			       struct dm_target *ti){	int r;	struct pgpath *p;	/* we need at least a path arg */	if (as->argc < 1) {		ti->error = "no device given";		return NULL;	}	p = alloc_pgpath();	if (!p)		return NULL;	r = dm_get_device(ti, shift(as), ti->begin, ti->len,			  dm_table_get_mode(ti->table), &p->path.dev);	if (r) {		ti->error = "error getting device";		goto bad;	}	r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error);	if (r) {		dm_put_device(ti, p->path.dev);		goto bad;	}	return p; bad:	free_pgpath(p);	return NULL;}static struct priority_group *parse_priority_group(struct arg_set *as,						   struct multipath *m){	static struct param _params[] = {		{1, 1024, "invalid number of paths"},		{0, 1024, "invalid number of selector args"}	};	int r;	unsigned i, nr_selector_args, nr_params;	struct priority_group *pg;	struct dm_target *ti = m->ti;	if (as->argc < 2) {		as->argc = 0;		ti->error = "not enough priority group aruments";		return NULL;	}	pg = alloc_priority_group();	if (!pg) {		ti->error = "couldn't allocate priority group";		return NULL;	}	pg->m = m;	r = parse_path_selector(as, pg, ti);	if (r)		goto bad;	/*	 * read the paths	 */	r = read_param(_params, shift(as), &pg->nr_pgpaths, &ti->error);	if (r)		goto bad;	r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error);	if (r)		goto bad;	nr_params = 1 + nr_selector_args;	for (i = 0; i < pg->nr_pgpaths; i++) {		struct pgpath *pgpath;		struct arg_set path_args;		if (as->argc < nr_params)			goto bad;		path_args.argc = nr_params;		path_args.argv = as->argv;		pgpath = parse_path(&path_args, &pg->ps, ti);		if (!pgpath)			goto bad;		pgpath->pg = pg;		list_add_tail(&pgpath->list, &pg->pgpaths);		consume(as, nr_params);	}	return pg; bad:	free_priority_group(pg, ti);	return NULL;}static int parse_hw_handler(struct arg_set *as, struct multipath *m){	int r;	struct hw_handler_type *hwht;	unsigned hw_argc;	struct dm_target *ti = m->ti;	static struct param _params[] = {		{0, 1024, "invalid number of hardware handler args"},	};	r = read_param(_params, shift(as), &hw_argc, &ti->error);	if (r)		return -EINVAL;	if (!hw_argc)		return 0;	hwht = dm_get_hw_handler(shift(as));	if (!hwht) {		ti->error = "unknown hardware handler type";		return -EINVAL;	}	m->hw_handler.md = dm_table_get_md(ti->table);	dm_put(m->hw_handler.md);	r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv);	if (r) {		dm_put_hw_handler(hwht);		ti->error = "hardware handler constructor failed";		return r;	}	m->hw_handler.type = hwht;	consume(as, hw_argc - 1);	return 0;}static int parse_features(struct arg_set *as, struct multipath *m){	int r;	unsigned argc;	struct dm_target *ti = m->ti;	const char *param_name;	static struct param _params[] = {		{0, 3, "invalid number of feature args"},		{1, 50, "pg_init_retries must be between 1 and 50"},	};	r = read_param(_params, shift(as), &argc, &ti->error);	if (r)		return -EINVAL;	if (!argc)		return 0;	do {		param_name = shift(as);		argc--;		if (!strnicmp(param_name, MESG_STR("queue_if_no_path"))) {			r = queue_if_no_path(m, 1, 0);			continue;		}		if (!strnicmp(param_name, MESG_STR("pg_init_retries")) &&		    (argc >= 1)) {			r = read_param(_params + 1, shift(as),				       &m->pg_init_retries, &ti->error);			argc--;			continue;		}		ti->error = "Unrecognised multipath feature request";		r = -EINVAL;	} while (argc && !r);	return r;}static int multipath_ctr(struct dm_target *ti, unsigned int argc,			 char **argv){	/* target parameters */	static struct param _params[] = {		{1, 1024, "invalid number of priority groups"},		{1, 1024, "invalid initial priority group number"},	};	int r;	struct multipath *m;	struct arg_set as;	unsigned pg_count = 0;	unsigned next_pg_num;	as.argc = argc;	as.argv = argv;	m = alloc_multipath(ti);	if (!m) {		ti->error = "can't allocate multipath";		return -EINVAL;	}	r = parse_features(&as, m);	if (r)		goto bad;	r = parse_hw_handler(&as, m);	if (r)		goto bad;	r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error);	if (r)		goto bad;	r = read_param(_params + 1, shift(&as), &next_pg_num, &ti->error);	if (r)		goto bad;	/* parse the priority groups */	while (as.argc) {		struct priority_group *pg;		pg = parse_priority_group(&as, m);		if (!pg) {			r = -EINVAL;			goto bad;		}		m->nr_valid_paths += pg->nr_pgpaths;		list_add_tail(&pg->list, &m->priority_groups);		pg_count++;		pg->pg_num = pg_count;		if (!--next_pg_num)			m->next_pg = pg;	}	if (pg_count != m->nr_priority_groups) {		ti->error = "priority group count mismatch";		r = -EINVAL;		goto bad;	}	return 0; bad:	free_multipath(m);	return r;}static void multipath_dtr(struct dm_target *ti){	struct multipath *m = (struct multipath *) ti->private;	flush_workqueue(kmultipathd);	free_multipath(m);}/* * Map bios, recording original fields for later in case we have to resubmit */static int multipath_map(struct dm_target *ti, struct bio *bio,			 union map_info *map_context){	int r;	struct dm_mpath_io *mpio;	struct multipath *m = (struct multipath *) ti->private;	mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);	dm_bio_record(&mpio->details, bio);	map_context->ptr = mpio;	bio->bi_rw |= (1 << BIO_RW_FAILFAST);	r = map_io(m, bio, mpio, 0);	if (r < 0 || r == DM_MAPIO_REQUEUE)		mempool_free(mpio, m->mpio_pool);	return r;}/* * Take a path out of use. */static int fail_path(struct pgpath *pgpath){	unsigned long flags;	struct multipath *m = pgpath->pg->m;	spin_lock_irqsave(&m->lock, flags);	if (!pgpath->path.is_active)		goto out;	DMWARN("Failing path %s.", pgpath->path.dev->name);	pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path);	pgpath->path.is_active = 0;	pgpath->fail_count++;	m->nr_valid_paths--;	if (pgpath == m->current_pgpath)		m->current_pgpath = NULL;	dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,		      pgpath->path.dev->name, m->nr_valid_paths);	queue_work(kmultipathd, &m->trigger_event);out:	spin_unlock_irqrestore(&m->lock, flags);	return 0;}/* * Reinstate a previously-failed path */static int reinstate_path(struct pgpath *pgpath){	int r = 0;	unsigned long flags;	struct multipath *m = pgpath->pg->m;	spin_lock_irqsave(&m->lock, flags);	if (pgpath->path.is_active)		goto out;	if (!pgpath->pg->ps.type) {		DMWARN("Reinstate path not supported by path selector %s",		       pgpath->pg->ps.type->name);		r = -EINVAL;		goto out;	}	r = pgpath->pg->ps.type->reinstate_path(&pgpath->pg->ps, &pgpath->path);	if (r)		goto out;	pgpath->path.is_active = 1;	m->current_pgpath = NULL;	if (!m->nr_valid_paths++ && m->queue_size)		queue_work(kmultipathd, &m->process_queued_ios);	dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,		      pgpath->path.dev->name, m->nr_valid_paths);	queue_work(kmultipathd, &m->trigger_event);out:	spin_unlock_irqrestore(&m->lock, flags);	return r;}/* * Fail or reinstate all paths that match the provided struct dm_dev. */static int action_dev(struct multipath *m, struct dm_dev *dev,		      action_fn action){	int r = 0;	struct pgpath *pgpath;	struct priority_group *pg;	list_for_each_entry(pg, &m->priority_groups, list) {		list_for_each_entry(pgpath, &pg->pgpaths, list) {			if (pgpath->path.dev == dev)				r = action(pgpath);		}	}	return r;}/* * Temporarily try to avoid having to use the specified PG */static void bypass_pg(struct multipath *m, struct priority_group *pg,		      int bypassed){	unsigned long flags;	spin_lock_irqsave(&m->lock, flags);	pg->bypassed = bypassed;	m->current_pgpath = NULL;	m->current_pg = NULL;	spin_unlock_irqrestore(&m->lock, flags);	queue_work(kmultipathd, &m->trigger_event);}/* * Switch to using the specified PG from the next I/O that gets mapped */static int switch_pg_num(struct multipath *m, const char *pgstr){	struct priority_group *pg;	unsigned pgnum;	unsigned long flags;	if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||	    (pgnum > m->nr_priority_groups)) {		DMWARN("invalid PG number supplied to switch_pg_num");		return -EINVAL;	}	spin_lock_irqsave(&m->lock, flags);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -