From patchwork Mon Mar 16 12:37:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 6017941 X-Patchwork-Delegate: christophe.varoqui@free.fr Return-Path: X-Original-To: patchwork-dm-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 84DED9F399 for ; Mon, 16 Mar 2015 12:42:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 94458204D1 for ; Mon, 16 Mar 2015 12:42:15 +0000 (UTC) Received: from mx5-phx2.redhat.com (mx5-phx2.redhat.com [209.132.183.37]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 856AB200F4 for ; Mon, 16 Mar 2015 12:42:14 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx5-phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t2GCcetf055298; Mon, 16 Mar 2015 08:38:40 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id t2GCbMX8029004 for ; Mon, 16 Mar 2015 08:37:22 -0400 Received: from mx1.redhat.com (ext-mx12.extmail.prod.ext.phx2.redhat.com [10.5.110.17]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t2GCbMvi004245; Mon, 16 Mar 2015 08:37:22 -0400 Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t2GCbKFi019218 (version=TLSv1/SSLv3 cipher=DHE-RSA-CAMELLIA256-SHA bits=256 verify=FAIL); Mon, 16 Mar 2015 08:37:21 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 9EB41AE02; Mon, 16 Mar 2015 12:37:11 +0000 (UTC) From: Hannes Reinecke To: Christophe Varoqui Date: Mon, 16 Mar 2015 13:37:05 +0100 Message-Id: <1426509425-15978-79-git-send-email-hare@suse.de> In-Reply-To: <1426509425-15978-1-git-send-email-hare@suse.de> References: <1426509425-15978-1-git-send-email-hare@suse.de> X-RedHat-Spam-Score: -7.309 (BAYES_00, DCC_REPUT_00_12, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, URIBL_BLOCKED) 195.135.220.15 cantor2.suse.de 195.135.220.15 cantor2.suse.de X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Scanned-By: MIMEDefang 2.68 on 10.5.110.17 X-loop: dm-devel@redhat.com Cc: dm-devel@redhat.com Subject: [dm-devel] [PATCH 78/78] multipathd: trigger all devices on startup X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP During startup multipathd might race with udev and device discovery. During that time any information from libudev might not be fully available, leading to spurious multipathd failures during startup. So instead of scanning all devices on our own we should just re-trigger the existing devices; with that we'll read _all_ devices via uevents during startup and avoid the race condition. Signed-off-by: Hannes Reinecke --- libmultipath/discovery.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ libmultipath/discovery.h | 1 + multipathd/main.c | 36 +++++++++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 4582a20..8762819 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -134,6 +134,58 @@ path_discover (vector pathvec, struct config * conf, } int +path_trigger (struct config * conf, int flag) +{ + struct udev_enumerate *udev_iter; + struct udev_list_entry *entry; + int num_paths = 0; + + udev_iter = udev_enumerate_new(conf->udev); + if (!udev_iter) + return -ENOMEM; + + udev_enumerate_add_match_subsystem(udev_iter, "block"); + udev_enumerate_scan_devices(udev_iter); + + udev_list_entry_foreach(entry, + udev_enumerate_get_list_entry(udev_iter)) { + const char *devpath; + char *devname; + char filename[PATH_MAX]; + int fd; + + devpath = udev_list_entry_get_name(entry); + condlog(3, "Trigger device %s", devpath); + devname = strrchr(devpath, '/'); + if (!devname) { + condlog(3, "%s: invalid devpath", devpath); + continue; + } + devname++; + if (filter_devnode(conf->blist_devnode, + conf->elist_devnode, devname) > 0) { + condlog(3, "%s: blacklisted", devname); + continue; + } + strncpy(filename, devpath, strlen(devpath) + 1); + strncat(filename, "/uevent", 8); + fd = open(filename, O_WRONLY | O_CLOEXEC); + if (fd < 0) + continue; + if (write(fd, "add", 3) < 0) { + condlog(3, "%s: Failed to trigger 'add' uevent: %m", + devpath); + } else { + num_paths++; + } + close(fd); + } + udev_enumerate_unref(udev_iter); + condlog(4, "Triggered %d paths", num_paths); + return num_paths; +} + +int path_discovery (vector pathvec, struct config * conf, int flag) { struct udev_enumerate *udev_iter; diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h index da7652c..9ae3d23 100644 --- a/libmultipath/discovery.h +++ b/libmultipath/discovery.h @@ -31,6 +31,7 @@ struct config; int path_discovery (vector pathvec, struct config * conf, int flag); +int path_trigger (struct config * conf, int flag); int do_tur (char *); int path_offline (struct path *); diff --git a/multipathd/main.c b/multipathd/main.c index d9f2435..480b10d 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -1581,6 +1581,24 @@ configure (struct vectors * vecs, int start_waiters) } int +trigger_devices (struct vectors * vecs) +{ + + if (!vecs->pathvec && !(vecs->pathvec = vector_alloc())) + return 1; + + if (!vecs->mpvec && !(vecs->mpvec = vector_alloc())) + return 1; + + /* + * Trigger all non-blacklisted block devices + */ + path_trigger(conf, DI_ALL); + + return 0; +} + +int reconfigure (struct vectors * vecs) { struct config * old = conf; @@ -1902,15 +1920,21 @@ child (void * param) condlog(0, "failed to create cli listener: %d", rc); goto failed; } - /* - * fetch and configure both paths and multipaths - */ #ifdef USE_SYSTEMD sd_notify(0, "STATUS=configure"); #endif post_config_state(DAEMON_CONFIGURE); /* + * Trigger all paths to force reconfiguration + */ + pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(vecs->lock); + pthread_testcancel(); + trigger_devices(vecs); + lock_cleanup_pop(vecs->lock); + + /* * start threads */ if ((rc = pthread_create(&check_thr, &misc_attr, checkerloop, vecs))) { @@ -1927,6 +1951,8 @@ child (void * param) pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid); /* Ignore errors, we can live without */ + post_config_state(DAEMON_RUNNING); + #ifdef USE_SYSTEMD sd_notify(0, "READY=1\nSTATUS=running"); #endif @@ -2129,7 +2155,9 @@ main (int argc, char *argv[]) conf->bindings_read_only = 1; break; default: - ; + fprintf(stderr, "Invalid argument '-%c'\n", + optopt); + exit(1); } } if (optind < argc) {