brintos

brintos / linux-shallow public Read only

0
0
Text · 2.5 KiB · 3e4cb81 Raw
141 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2003 Sistina Software.4 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.5 *6 * Module Author: Heinz Mauelshagen7 *8 * This file is released under the GPL.9 *10 * Path selector registration.11 */12 13#include <linux/device-mapper.h>14#include <linux/module.h>15 16#include "dm-path-selector.h"17 18#include <linux/slab.h>19 20struct ps_internal {21	struct path_selector_type pst;22	struct list_head list;23};24 25#define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)26 27static LIST_HEAD(_path_selectors);28static DECLARE_RWSEM(_ps_lock);29 30static struct ps_internal *__find_path_selector_type(const char *name)31{32	struct ps_internal *psi;33 34	list_for_each_entry(psi, &_path_selectors, list) {35		if (!strcmp(name, psi->pst.name))36			return psi;37	}38 39	return NULL;40}41 42static struct ps_internal *get_path_selector(const char *name)43{44	struct ps_internal *psi;45 46	down_read(&_ps_lock);47	psi = __find_path_selector_type(name);48	if (psi && !try_module_get(psi->pst.module))49		psi = NULL;50	up_read(&_ps_lock);51 52	return psi;53}54 55struct path_selector_type *dm_get_path_selector(const char *name)56{57	struct ps_internal *psi;58 59	if (!name)60		return NULL;61 62	psi = get_path_selector(name);63	if (!psi) {64		request_module("dm-%s", name);65		psi = get_path_selector(name);66	}67 68	return psi ? &psi->pst : NULL;69}70 71void dm_put_path_selector(struct path_selector_type *pst)72{73	struct ps_internal *psi;74 75	if (!pst)76		return;77 78	down_read(&_ps_lock);79	psi = __find_path_selector_type(pst->name);80	if (!psi)81		goto out;82 83	module_put(psi->pst.module);84out:85	up_read(&_ps_lock);86}87 88static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)89{90	struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL);91 92	if (psi)93		psi->pst = *pst;94 95	return psi;96}97 98int dm_register_path_selector(struct path_selector_type *pst)99{100	int r = 0;101	struct ps_internal *psi = _alloc_path_selector(pst);102 103	if (!psi)104		return -ENOMEM;105 106	down_write(&_ps_lock);107 108	if (__find_path_selector_type(pst->name)) {109		kfree(psi);110		r = -EEXIST;111	} else112		list_add(&psi->list, &_path_selectors);113 114	up_write(&_ps_lock);115 116	return r;117}118EXPORT_SYMBOL_GPL(dm_register_path_selector);119 120int dm_unregister_path_selector(struct path_selector_type *pst)121{122	struct ps_internal *psi;123 124	down_write(&_ps_lock);125 126	psi = __find_path_selector_type(pst->name);127	if (!psi) {128		up_write(&_ps_lock);129		return -EINVAL;130	}131 132	list_del(&psi->list);133 134	up_write(&_ps_lock);135 136	kfree(psi);137 138	return 0;139}140EXPORT_SYMBOL_GPL(dm_unregister_path_selector);141