From patchwork Tue Oct 23 20:56:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10653667 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A03AF14BD for ; Tue, 23 Oct 2018 20:57:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 89F0D28514 for ; Tue, 23 Oct 2018 20:57:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7E2CF2A446; Tue, 23 Oct 2018 20:57:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7659128514 for ; Tue, 23 Oct 2018 20:57:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725266AbeJXFWQ (ORCPT ); Wed, 24 Oct 2018 01:22:16 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:36499 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728530AbeJXFWQ (ORCPT ); Wed, 24 Oct 2018 01:22:16 -0400 Received: by mail-pl1-f193.google.com with SMTP id y11-v6so1195043plt.3 for ; Tue, 23 Oct 2018 13:57:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LYjiQTUP29RKb32HOIyRldHdU4T6pkq8bNCCH1pXAcQ=; b=UQPCEG8Itqrc0jF4WBBLIFjsLwovV+QLrE6cCCi1Dkz8ORgbWDS9cMhXv/j52lxRoH Ej8ZmAUUZPJzkP5xXY3XHgjR/SVs9fkvryCEQeWLIuWHB1mEJ6ZBHWIs7pY87YaF8p6p iJBeskJK23xKrvtfQaDysXykPBj+Brvhb9ATg42whS4P4pC/FCnKP7BqcXksTP2du5S7 pLhnYcDLYarnOx25nQ/29vezHGzOB9LslTHxUT5HGUNZHRanvyofFxvDR2K1LXhz3izr U3hZi3rN6XiE6KcKqXbFh7seR9UFWtnr81cskdAgKqeUqi985aWKPLNXuZPGUMwHC9vC vbOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LYjiQTUP29RKb32HOIyRldHdU4T6pkq8bNCCH1pXAcQ=; b=cu8k5Rm3m9ucMd9VjHTCHy6IwJH3DhYwNJQl6nyMfVAekNAQ4C9c4V3333Ovg3PK6S +u35BrRm52oSudUV7oOXBSPJydKYJGtLe15RQk6MMc6jG9wS3JdzBT58rHUCTBSVmlM0 OcWfY0/ibikp4hvog3HWz7ePzBtPGcAf0wGreG76hN5aY2hfNi301rR7LkBlPocogduu BaMlNfF+12PupGUlsgTn1i1NVtGI94U/a4ZyCNY/Eh2DXrtSTqNliej4QEvl+ZqqXqhv LiQHbI4WgfxGsoD51Tq6Kt1DIZevagBh7Q1alS9vgt6uqT+JarcGS2beHlGAGb9Y8fFZ dEhQ== X-Gm-Message-State: ABuFfoh5Q7Ziz1IFz5dydl8AI+fO51xVU+8gc6+bC4seyxSnVF/0UIyy ibyiV4KI5JMUpTtBK6naXOqiXGrmGBU= X-Google-Smtp-Source: ACcGV608jC8sM6eJpI/V2sT6mkkoGeIbgpH1LW3E8dBvIgCsZatoC6Bp+tGdZld2z3aRu1GPSHCapg== X-Received: by 2002:a17:902:1021:: with SMTP id b30-v6mr50855463pla.23.1540328231048; Tue, 23 Oct 2018 13:57:11 -0700 (PDT) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id u69-v6sm4772039pfk.68.2018.10.23.13.57.05 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 23 Oct 2018 13:57:06 -0700 (PDT) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gF3jc-000106-NH; Tue, 23 Oct 2018 14:57:04 -0600 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH rdma-core 1/9] verbs: Move all dynamic driver opening code to dynamic_driver.c Date: Tue, 23 Oct 2018 14:56:53 -0600 Message-Id: <20181023205701.3729-2-jgg@ziepe.ca> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181023205701.3729-1-jgg@ziepe.ca> References: <20181023205701.3729-1-jgg@ziepe.ca> MIME-Version: 1.0 Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jason Gunthorpe This is preparation for removing this code when statically linking. Signed-off-by: Jason Gunthorpe --- libibverbs/CMakeLists.txt | 1 + libibverbs/dynamic_driver.c | 239 ++++++++++++++++++++++++++++++++++++ libibverbs/ibverbs.h | 1 + libibverbs/init.c | 206 ------------------------------- 4 files changed, 241 insertions(+), 206 deletions(-) create mode 100644 libibverbs/dynamic_driver.c diff --git a/libibverbs/CMakeLists.txt b/libibverbs/CMakeLists.txt index 738e5e15aaf00e..33e86a409708b0 100644 --- a/libibverbs/CMakeLists.txt +++ b/libibverbs/CMakeLists.txt @@ -38,6 +38,7 @@ rdma_library(ibverbs "${CMAKE_CURRENT_BINARY_DIR}/libibverbs.map" compat-1_0.c device.c dummy_ops.c + dynamic_driver.c enum_strs.c init.c marshall.c diff --git a/libibverbs/dynamic_driver.c b/libibverbs/dynamic_driver.c new file mode 100644 index 00000000000000..7a8f95b9e74f32 --- /dev/null +++ b/libibverbs/dynamic_driver.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. + * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2018 Mellanox Technologies, Ltd. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include + +#include "ibverbs.h" + +struct ibv_driver_name { + struct list_node entry; + char *name; +}; + +static LIST_HEAD(driver_name_list); + +static void read_config_file(const char *path) +{ + FILE *conf; + char *line = NULL; + char *config; + char *field; + size_t buflen = 0; + ssize_t len; + + conf = fopen(path, "r" STREAM_CLOEXEC); + if (!conf) { + fprintf(stderr, PFX "Warning: couldn't read config file %s.\n", + path); + return; + } + + while ((len = getline(&line, &buflen, conf)) != -1) { + config = line + strspn(line, "\t "); + if (config[0] == '\n' || config[0] == '#') + continue; + + field = strsep(&config, "\n\t "); + + if (strcmp(field, "driver") == 0 && config != NULL) { + struct ibv_driver_name *driver_name; + + config += strspn(config, "\t "); + field = strsep(&config, "\n\t "); + + driver_name = malloc(sizeof(*driver_name)); + if (!driver_name) { + fprintf(stderr, + PFX + "Warning: couldn't allocate driver name '%s'.\n", + field); + continue; + } + + driver_name->name = strdup(field); + if (!driver_name->name) { + fprintf(stderr, + PFX + "Warning: couldn't allocate driver name '%s'.\n", + field); + free(driver_name); + continue; + } + + list_add(&driver_name_list, &driver_name->entry); + } else + fprintf(stderr, + PFX + "Warning: ignoring bad config directive '%s' in file '%s'.\n", + field, path); + } + + if (line) + free(line); + fclose(conf); +} + +static void read_config(void) +{ + DIR *conf_dir; + struct dirent *dent; + char *path; + + conf_dir = opendir(IBV_CONFIG_DIR); + if (!conf_dir) { + fprintf(stderr, + PFX "Warning: couldn't open config directory '%s'.\n", + IBV_CONFIG_DIR); + return; + } + + while ((dent = readdir(conf_dir))) { + struct stat buf; + + if (asprintf(&path, "%s/%s", IBV_CONFIG_DIR, dent->d_name) < + 0) { + fprintf(stderr, + PFX + "Warning: couldn't read config file %s/%s.\n", + IBV_CONFIG_DIR, dent->d_name); + goto out; + } + + if (stat(path, &buf)) { + fprintf(stderr, + PFX + "Warning: couldn't stat config file '%s'.\n", + path); + goto next; + } + + if (!S_ISREG(buf.st_mode)) + goto next; + + read_config_file(path); +next: + free(path); + } + +out: + closedir(conf_dir); +} + +static void load_driver(const char *name) +{ + char *so_name; + void *dlhandle; + + /* If the name is an absolute path then open that path after appending + * the trailer suffix + */ + if (name[0] == '/') { + if (asprintf(&so_name, "%s" VERBS_PROVIDER_SUFFIX, name) < 0) + goto out_asprintf; + dlhandle = dlopen(so_name, RTLD_NOW); + if (!dlhandle) + goto out_dlopen; + free(so_name); + return; + } + + /* If configured with a provider plugin path then try that next */ + if (sizeof(VERBS_PROVIDER_DIR) > 1) { + if (asprintf(&so_name, + VERBS_PROVIDER_DIR "/lib%s" VERBS_PROVIDER_SUFFIX, + name) < 0) + goto out_asprintf; + dlhandle = dlopen(so_name, RTLD_NOW); + free(so_name); + if (dlhandle) + return; + } + + /* Otherwise use the system library search path. This is the historical + * behavior of libibverbs + */ + if (asprintf(&so_name, "lib%s" VERBS_PROVIDER_SUFFIX, name) < 0) + goto out_asprintf; + dlhandle = dlopen(so_name, RTLD_NOW); + if (!dlhandle) + goto out_dlopen; + free(so_name); + return; + +out_asprintf: + fprintf(stderr, PFX "Warning: couldn't load driver '%s'.\n", name); + return; +out_dlopen: + fprintf(stderr, PFX "Warning: couldn't load driver '%s': %s\n", so_name, + dlerror()); + free(so_name); +} + +void load_drivers(void) +{ + struct ibv_driver_name *name, *next_name; + const char *env; + char *list, *env_name; + + read_config(); + + /* Only use drivers passed in through the calling user's environment + * if we're not running setuid. + */ + if (getuid() == geteuid()) { + if ((env = getenv("RDMAV_DRIVERS"))) { + list = strdupa(env); + while ((env_name = strsep(&list, ":;"))) + load_driver(env_name); + } else if ((env = getenv("IBV_DRIVERS"))) { + list = strdupa(env); + while ((env_name = strsep(&list, ":;"))) + load_driver(env_name); + } + } + + list_for_each_safe (&driver_name_list, name, next_name, entry) { + load_driver(name->name); + free(name->name); + free(name); + } +} diff --git a/libibverbs/ibverbs.h b/libibverbs/ibverbs.h index 56be3627c81bdd..4ff4dc588410e6 100644 --- a/libibverbs/ibverbs.h +++ b/libibverbs/ibverbs.h @@ -61,6 +61,7 @@ int ibverbs_get_device_list(struct list_head *list); int ibverbs_init(void); void ibverbs_device_put(struct ibv_device *dev); void ibverbs_device_hold(struct ibv_device *dev); +void load_drivers(void); struct verbs_ex_private { BITMAP_DECLARE(unsupported_ioctls, VERBS_OPS_NUM); diff --git a/libibverbs/init.c b/libibverbs/init.c index a4c5f9e6e65d40..930d91811ca978 100644 --- a/libibverbs/init.c +++ b/libibverbs/init.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -54,17 +53,11 @@ int abi_ver; -struct ibv_driver_name { - struct list_node entry; - char *name; -}; - struct ibv_driver { struct list_node entry; const struct verbs_device_ops *ops; }; -static LIST_HEAD(driver_name_list); static LIST_HEAD(driver_list); static int try_access_device(const struct verbs_sysfs_dev *sysfs_dev) @@ -192,179 +185,6 @@ void verbs_register_driver(const struct verbs_device_ops *ops) list_add_tail(&driver_list, &driver->entry); } -static void load_driver(const char *name) -{ - char *so_name; - void *dlhandle; - - /* If the name is an absolute path then open that path after appending - the trailer suffix */ - if (name[0] == '/') { - if (asprintf(&so_name, "%s" VERBS_PROVIDER_SUFFIX, name) < 0) - goto out_asprintf; - dlhandle = dlopen(so_name, RTLD_NOW); - if (!dlhandle) - goto out_dlopen; - free(so_name); - return; - } - - /* If configured with a provider plugin path then try that next */ - if (sizeof(VERBS_PROVIDER_DIR) > 1) { - if (asprintf(&so_name, - VERBS_PROVIDER_DIR "/lib%s" VERBS_PROVIDER_SUFFIX, - name) < 0) - goto out_asprintf; - dlhandle = dlopen(so_name, RTLD_NOW); - free(so_name); - if (dlhandle) - return; - } - - /* Otherwise use the system libary search path. This is the historical - behavior of libibverbs */ - if (asprintf(&so_name, "lib%s" VERBS_PROVIDER_SUFFIX, name) < 0) - goto out_asprintf; - dlhandle = dlopen(so_name, RTLD_NOW); - if (!dlhandle) - goto out_dlopen; - free(so_name); - return; - -out_asprintf: - fprintf(stderr, PFX "Warning: couldn't load driver '%s'.\n", name); - return; -out_dlopen: - fprintf(stderr, PFX "Warning: couldn't load driver '%s': %s\n", so_name, - dlerror()); - free(so_name); - return; -} - -static void load_drivers(void) -{ - struct ibv_driver_name *name, *next_name; - const char *env; - char *list, *env_name; - - /* - * Only use drivers passed in through the calling user's - * environment if we're not running setuid. - */ - if (getuid() == geteuid()) { - if ((env = getenv("RDMAV_DRIVERS"))) { - list = strdupa(env); - while ((env_name = strsep(&list, ":;"))) - load_driver(env_name); - } else if ((env = getenv("IBV_DRIVERS"))) { - list = strdupa(env); - while ((env_name = strsep(&list, ":;"))) - load_driver(env_name); - } - } - - list_for_each_safe(&driver_name_list, name, next_name, entry) { - load_driver(name->name); - free(name->name); - free(name); - } -} - -static void read_config_file(const char *path) -{ - FILE *conf; - char *line = NULL; - char *config; - char *field; - size_t buflen = 0; - ssize_t len; - - conf = fopen(path, "r" STREAM_CLOEXEC); - if (!conf) { - fprintf(stderr, PFX "Warning: couldn't read config file %s.\n", - path); - return; - } - - while ((len = getline(&line, &buflen, conf)) != -1) { - config = line + strspn(line, "\t "); - if (config[0] == '\n' || config[0] == '#') - continue; - - field = strsep(&config, "\n\t "); - - if (strcmp(field, "driver") == 0 && config != NULL) { - struct ibv_driver_name *driver_name; - - config += strspn(config, "\t "); - field = strsep(&config, "\n\t "); - - driver_name = malloc(sizeof *driver_name); - if (!driver_name) { - fprintf(stderr, PFX "Warning: couldn't allocate " - "driver name '%s'.\n", field); - continue; - } - - driver_name->name = strdup(field); - if (!driver_name->name) { - fprintf(stderr, PFX "Warning: couldn't allocate " - "driver name '%s'.\n", field); - free(driver_name); - continue; - } - - list_add(&driver_name_list, &driver_name->entry); - } else - fprintf(stderr, PFX "Warning: ignoring bad config directive " - "'%s' in file '%s'.\n", field, path); - } - - if (line) - free(line); - fclose(conf); -} - -static void read_config(void) -{ - DIR *conf_dir; - struct dirent *dent; - char *path; - - conf_dir = opendir(IBV_CONFIG_DIR); - if (!conf_dir) { - fprintf(stderr, PFX "Warning: couldn't open config directory '%s'.\n", - IBV_CONFIG_DIR); - return; - } - - while ((dent = readdir(conf_dir))) { - struct stat buf; - - if (asprintf(&path, "%s/%s", IBV_CONFIG_DIR, dent->d_name) < 0) { - fprintf(stderr, PFX "Warning: couldn't read config file %s/%s.\n", - IBV_CONFIG_DIR, dent->d_name); - goto out; - } - - if (stat(path, &buf)) { - fprintf(stderr, PFX "Warning: couldn't stat config file '%s'.\n", - path); - goto next; - } - - if (!S_ISREG(buf.st_mode)) - goto next; - - read_config_file(path); -next: - free(path); - } - -out: - closedir(conf_dir); -} - /* Match a single modalias value */ static bool match_modalias(const struct verbs_match_ent *ent, const char *value) { @@ -616,7 +436,6 @@ int ibverbs_get_device_list(struct list_head *device_list) struct verbs_device *vdev, *tmp; static int drivers_loaded; unsigned int num_devices = 0; - int statically_linked = 0; int ret; ret = find_sysfs_devs(&sysfs_list); @@ -652,26 +471,6 @@ int ibverbs_get_device_list(struct list_head *device_list) if (list_empty(&sysfs_list) || drivers_loaded) goto out; - /* - * Check if we can dlopen() ourselves. If this fails, - * libibverbs is probably statically linked into the - * executable, and we should just give up, since trying to - * dlopen() a driver module will fail spectacularly (loading a - * driver .so will bring in dynamic copies of libibverbs and - * libdl to go along with the static copies the executable - * has, which quickly leads to a crash. - */ - { - void *hand = dlopen(NULL, RTLD_NOW); - if (!hand) { - fprintf(stderr, PFX "Warning: dlopen(NULL) failed, " - "assuming static linking.\n"); - statically_linked = 1; - goto out; - } - dlclose(hand); - } - load_drivers(); drivers_loaded = 1; @@ -686,9 +485,6 @@ out: fprintf(stderr, PFX "Warning: no userspace device-specific driver found for %s\n", sysfs_dev->sysfs_path); - if (statically_linked) - fprintf(stderr, - " When linking libibverbs statically, driver must be statically linked too.\n"); } free(sysfs_dev); } @@ -725,8 +521,6 @@ int ibverbs_init(void) check_memlock_limit(); - read_config(); - return 0; }