[dm-devel] map removal and multipathd
christophe varoqui
christophe.varoqui at free.fr
Fri Jul 15 23:10:10 UTC 2005
Nice hunt, applied.
Glad to see this long standing issue get the attention it deserved :)
I suspect this patch will also plugs an annoying memory leak I spotted
recently. Will check.
Regards,
cvaroqui
On ven, 2005-07-15 at 11:08 -0400, goggin, edward wrote:
> I've found the removal of a multipath map (or all of them for that matter)
> to be troublesome
> for multipathd, particularly its waitevent pthreads. The dm driver in the
> kernel was not waking
> up the dm event waiters so they stayed in the kernel where each one held a
> reference on the
> mapped device and its table. This held reference prevented the multipathd
> from receiving either
> a uevent or a hotplug event for the removal of the multipath block device --
> since it is not removed
> in this case.
>
> --- drivers/md/dm-ioctl.c.orig 2005-07-14 13:33:56.000000000 -0500
> +++ drivers/md/dm-ioctl.c 2005-07-14 22:01:04.000000000 -0500
> @@ -226,10 +226,22 @@
>
> static void __hash_remove(struct hash_cell *hc)
> {
> + struct dm_table *table;
> +
> /* remove from the dev hash */
> list_del(&hc->uuid_list);
> list_del(&hc->name_list);
> unregister_with_devfs(hc);
> +
> + /*
> + * Wakeup any dm event waiters.
> + */
> + table = dm_get_table(hc->md);
> + if (table) {
> + dm_table_event(table);
> + dm_table_put(table);
> + }
> +
> dm_put(hc->md);
> if (hc->new_map)
> dm_table_put(hc->new_map);
>
> With dm-ioctl.c patched to wake up waiting dm event threads when a mapped
> device is removed,
> multipathd has issues. Fixed 3 bugs
>
> (1) update_multipath wasn't dealing with an error from
> setup_multipath. Setup_multipath
> error path involved the call chain
> update_multipath_strings->update_multipath_table->
> dm_get_map->dm_task_run->ioctl. Since the mpp structure for a block
> device could be
> deallocated in setup_multipath, the multipathd could SIGSEGV when it
> referenced the
> deallocated mpp memory in update_multipath.
>
> (2) The waitevent pthread's dm task structure memory was getting
> destroyed twice if
> it ever broke out of its waitevent loop due to the call to
> waiteventloop returning < 0. I
> set wp->dmt to null after waiteventloop called dm_task_destroy to
> prevent free_waiter
> from doing likewise.
>
> (3) setup_multipath was not removing the mpp ptr from the
> allpaths->mpvec vector if it
> deallocated the mpp structure memory due to the error occurrence
> mentioned in (1).
> This omission would cause multipathd mpvec_garbage_collector to
> SIGSEGV.
> Fixed uev_add_map since it had the same issue.
>
> diff --git a/multipathd/main.c b/multipathd/main.c
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -207,6 +207,7 @@ static int
> setup_multipath (struct paths * allpaths, struct multipath * mpp)
> {
> char * wwid;
> + int i;
>
> wwid = get_mpe_wwid(mpp->alias);
>
> @@ -227,6 +228,12 @@ setup_multipath (struct paths * allpaths
>
> return 0;
> out:
> + /*
> + * purge the multipath vector
> + */
> + if ((i = find_slot(allpaths->mpvec, (void *)mpp)) != -1)
> + vector_del_slot(allpaths->mpvec, i);
> +
> free_multipath(mpp, KEEP_PATHS);
> condlog(0, "failed to setup multipath");
> return 1;
> @@ -275,7 +282,8 @@ update_multipath (struct paths *allpaths
> free_pgvec(mpp->pg, KEEP_PATHS);
> mpp->pg = NULL;
>
> - setup_multipath(allpaths, mpp);
> + if (setup_multipath(allpaths, mpp))
> + goto out; /* mpp freed in setup_multipath */
>
> /*
> * compare checkers states with DM states
> @@ -311,7 +319,8 @@ free_waiter (void * data)
> {
> struct event_thread * wp = (struct event_thread *)data;
>
> - dm_task_destroy(wp->dmt);
> + if (wp->dmt)
> + dm_task_destroy(wp->dmt);
> FREE(wp);
> }
>
> @@ -344,6 +353,7 @@ waiteventloop (struct event_thread * wai
> dm_task_run(waiter->dmt);
> pthread_testcancel();
> dm_task_destroy(waiter->dmt);
> + waiter->dmt = NULL;
>
> waiter->event_nr++;
>
> @@ -509,7 +519,7 @@ remove_maps (struct paths * allpaths)
> int
> uev_add_map (char * devname, struct paths * allpaths)
> {
> - int major, minor;
> + int major, minor, i;
> char dev_t[BLK_DEV_SIZE];
> char * alias;
> struct multipath * mpp;
> @@ -570,6 +580,12 @@ uev_add_map (char * devname, struct path
> return 0;
> out:
> condlog(2, "add %s devmap failed", mpp->alias);
> + /*
> + * purge the multipath vector
> + */
> + if ((i = find_slot(allpaths->mpvec, (void *)mpp)) != -1)
> + vector_del_slot(allpaths->mpvec, i);
> +
> free_multipath(mpp, KEEP_PATHS);
> return 1;
> }
> @@ -874,7 +890,8 @@ get_dm_mpvec (struct paths * allpaths)
> return 1;
>
> vector_foreach_slot (allpaths->mpvec, mpp, i) {
> - setup_multipath(allpaths, mpp);
> + if (setup_multipath(allpaths, mpp))
> + return 1;
> mpp->minor = dm_get_minor(mpp->alias);
> start_waiter_thread(mpp, allpaths);
> }
>
> --
> dm-devel mailing list
> dm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
--
christophe varoqui <christophe.varoqui at free.fr>
More information about the dm-devel
mailing list