dm-multipath: ps-refcount.patch Fixes the refcounting on the path-selectors. And, exports the register/unregister functions. From: Mike Christie --- diff/drivers/md/dm-path-selector.c 2004-09-28 15:11:35.000000000 +0100 +++ source/drivers/md/dm-path-selector.c 2004-09-28 15:42:45.000000000 +0100 @@ -14,12 +14,14 @@ #include struct ps_internal { - struct path_selector_type pt; + struct path_selector_type pst; struct list_head list; long use; }; +#define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst) + static LIST_HEAD(_path_selectors); static DECLARE_MUTEX(_lock); @@ -28,8 +30,8 @@ struct ps_internal *li; list_for_each_entry (li, &_path_selectors, list) { - if (!strcmp(name, li->pt.name)) - return &li->pt; + if (!strcmp(name, li->pst.name)) + return &li->pst; } return NULL; @@ -37,32 +39,42 @@ struct path_selector_type *dm_get_path_selector(const char *name) { - struct path_selector_type *lb; + struct path_selector_type *pst; if (!name) return NULL; down(&_lock); - lb = __find_path_selector_type(name); - if (lb) { - struct ps_internal *li = (struct ps_internal *) lb; - li->use++; + pst = __find_path_selector_type(name); + if (pst) { + struct ps_internal *psi = pst_to_psi(pst); + + if (psi->use == 0 && !try_module_get(pst->module)) + psi = NULL; + else + psi->use++; } up(&_lock); - return lb; + return pst; } -void dm_put_path_selector(struct path_selector_type *l) +void dm_put_path_selector(struct path_selector_type *pst) { - struct ps_internal *li = (struct ps_internal *) l; + struct ps_internal *psi; down(&_lock); - if (--li->use < 0) + pst = __find_path_selector_type(pst->name); + if (!pst) + return; + + psi = pst_to_psi(pst); + if (--psi->use == 0) + module_put(psi->pst.module); + + if (psi->use < 0) BUG(); up(&_lock); - - return; } static struct ps_internal *_alloc_path_selector(struct path_selector_type *pt) @@ -71,7 +83,7 @@ if (psi) { memset(psi, 0, sizeof(*psi)); - memcpy(psi, pt, sizeof(*pt)); + memcpy(&psi->pst, pt, sizeof(*pt)); } return psi; @@ -97,17 +109,20 @@ return r; } +EXPORT_SYMBOL(dm_register_path_selector); + int dm_unregister_path_selector(struct path_selector_type *pst) { struct ps_internal *psi; down(&_lock); - psi = (struct ps_internal *) __find_path_selector_type(pst->name); - if (!psi) { + pst = __find_path_selector_type(pst->name); + if (!pst) { up(&_lock); return -EINVAL; } + psi = pst_to_psi(pst); if (psi->use) { up(&_lock); return -ETXTBSY; @@ -121,6 +136,8 @@ return 0; } +EXPORT_SYMBOL(dm_unregister_path_selector); + /*----------------------------------------------------------------- * Path handling code, paths are held in lists *---------------------------------------------------------------*/ @@ -274,6 +291,7 @@ static struct path_selector_type rr_ps = { .name = "round-robin", + .module = THIS_MODULE, .table_args = 0, .info_args = 0, .ctr = rr_ctr, --- diff/drivers/md/dm-path-selector.h 2004-09-28 15:11:35.000000000 +0100 +++ source/drivers/md/dm-path-selector.h 2004-09-28 15:42:45.000000000 +0100 @@ -69,6 +69,8 @@ /* Information about a path selector type */ struct path_selector_type { char *name; + struct module *module; + unsigned int table_args; unsigned int info_args; ps_ctr_fn ctr;