Received: by 10.223.185.116 with SMTP id b49csp5852653wrg; Tue, 27 Feb 2018 23:07:11 -0800 (PST) X-Google-Smtp-Source: AH8x224JFs6o56QWBppgwNNca3oxpBVMqeDD514guLDEFgvxBjQA0cELwM6BYHV7Y2c+bg6HgNz5 X-Received: by 10.99.98.5 with SMTP id w5mr13698959pgb.307.1519801631209; Tue, 27 Feb 2018 23:07:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519801631; cv=none; d=google.com; s=arc-20160816; b=UVcge2LzQ/jnOnjch4KbMlTdLpo7oROMix2ICw5Rscf6GBXUJKOdZilDBX+ULheKou ZhtK7OG55TuMaIijypmHdhAoJqiXidzh5Dg6HPPxrndBPapuLGt3bbQCoR3NfmLl8xxZ jqZZ/+11NceeZCDYG/xw/1tzgsaeqgDHmfU6yt1PASXSCoPYmz6uORSTNPBlhD/Uknd2 smVeax21lFkEqfSDsiLo73ri4ijVHgsnALsq1W0FgdwQXRvcYbW2Af1JA8/dT9+68L8y pDxW4A/1PN4Iku4Ep0pjuFT7ef1G301IRw7nVoCyvAbId2xL6q/52p/iY8XPZCy7YtEA VCrQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=YNpObus/ee/lXDywBIf7mIwYBJYqodeeNSXhEd7G6Ow=; b=POeaKqNGenc3b37PS4R4C3o04EoYvdaqazwitzXBQ6soIdi1MTIESxk1Hsp9IsetSr 8HeejHQSav0BXO6PQYct19NT9+H5c5/3EfOCMxvq8R54D4MqzwnJ1IOCz7LheqA6+E1K AjNwsTRbfSG7tAeR4HoBctKhB0SyHzb5K1sdISN10bbRJrcXsKzN5/AmDnFUd3nD8Rs0 2A7zHn05C2ana9AzudCVQDUu5VRzVNXvbBLiKBMIAvegxj9BB7uCK7cn5mRRxDXkrLYN PiJiWFSdpQ++uYwBUwci7GUhOxR9yYgzA+aeYFlsGKYfiKTGRN7U0HqaCAFTdeyFR6vA NJww== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Nqt1Kn57; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j91-v6si798663pld.485.2018.02.27.23.06.55; Tue, 27 Feb 2018 23:07:11 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Nqt1Kn57; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751985AbeB1HGR (ORCPT + 99 others); Wed, 28 Feb 2018 02:06:17 -0500 Received: from mail-pl0-f65.google.com ([209.85.160.65]:43969 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751631AbeB1HGP (ORCPT ); Wed, 28 Feb 2018 02:06:15 -0500 Received: by mail-pl0-f65.google.com with SMTP id f23-v6so997596plr.10 for ; Tue, 27 Feb 2018 23:06:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=YNpObus/ee/lXDywBIf7mIwYBJYqodeeNSXhEd7G6Ow=; b=Nqt1Kn57X8va21SgKSlUTStDPJ0tfXWuCJgEPvxFt884sH8tEWl602evi86dCHdzZe wbvMwSIhyHs8Kje0paYDsEYSZ1Xscb6L0y2vI++mcTteDMw4xOFe/ato6mvaPOjH+E/K beeNBLkja4/K+IJz32PFDtJ41XTh+r/a6DRVLswsfaDVUQ+wx/EZkQRWi15p9shfBdMI SX2kJKOSqsF9vyKzFXnbbdAhh26cMgXZ6TYT6KGDVwCR1mdrZYG+Jo4YSPMMY2wQ69KU A21PpOzPwot6VWbCnN8ufgOzFHQJcGYv0R3dWfBaBgpid246/BZJVdVHsL0rFrWoYBI3 EKTQ== 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; bh=YNpObus/ee/lXDywBIf7mIwYBJYqodeeNSXhEd7G6Ow=; b=IOTOQklAAlNbmTuvF/CTBb41MYNDVQm1a7NueiFaFaYfA02RH7yBLfqtFetT9kqTH1 v1/AN8GiCVGj387fL9+/YliQWu35IsKjNQfOZl1d6bGxSimN7HdRMzKjNkZcjd9Ua8Nd akeiR6L7b/r25ix6hwSwhyzuhEGXTK9WEI9/tCwT0WUKEG6YIxmRx/wKDXAHcriGc29x gO9UVMU4abTpuHtCNjdnpvJSPJ8l1oKK3nelmdw8BinLFvaA6qNkqMdsOblnjcTbRm0N CrP+HChSbv/5cyIZe+ZcM0yrKDmyUp1MSXrw3z/NOmO1/5g+Kp67Dzq/9Oiak3wFSD06 d8Fg== X-Gm-Message-State: APf1xPCd1P2QUls4ZEWUycytHqeeyzUdfE1jUF3GYAJfvU+WmgYtEoJS ZKeeE4UcZz9Nq90oEDYPveM= X-Received: by 2002:a17:902:7717:: with SMTP id n23-v6mr16686383pll.388.1519801575035; Tue, 27 Feb 2018 23:06:15 -0800 (PST) Received: from localhost.localdomain ([203.236.8.208]) by smtp.gmail.com with ESMTPSA id l26sm2006304pfj.112.2018.02.27.23.06.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 27 Feb 2018 23:06:14 -0800 (PST) From: Baegjae Sung To: keith.busch@intel.com, axboe@fb.com, hch@lst.de, sagi@grimberg.me, baegjae@gmail.com Cc: linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] nvme-multipath: fix sysfs dangerously created links Date: Wed, 28 Feb 2018 16:06:04 +0900 Message-Id: <20180228070604.25868-1-baegjae@gmail.com> X-Mailer: git-send-email 2.8.3.windows.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If multipathing is enabled, each NVMe subsystem creates a head namespace (e.g., nvme0n1) and multiple private namespaces (e.g., nvme0c0n1 and nvme0c1n1) in sysfs. When creating links for private namespaces, links of head namespace are used, so the namespace creation order must be followed (e.g., nvme0n1 -> nvme0c1n1). If the order is not followed, links of sysfs will be incomplete or kernel panic will occur. The kernel panic was: kernel BUG at fs/sysfs/symlink.c:27! Call Trace: nvme_mpath_add_disk_links+0x5d/0x80 [nvme_core] nvme_validate_ns+0x5c2/0x850 [nvme_core] nvme_scan_work+0x1af/0x2d0 [nvme_core] Correct order Context A Context B nvme0n1 nvme0c0n1 nvme0c1n1 Incorrect order Context A Context B nvme0c1n1 nvme0n1 nvme0c0n1 The nvme_mpath_add_disk (for creating head namespace) is called just before the nvme_mpath_add_disk_links (for creating private namespaces). In nvme_mpath_add_disk, the first context acquires the lock of subsystem and creates a head namespace, and other contexts do nothing by checking GENHD_FL_UP of a head namespace after waiting to acquire the lock. We verified the code with or without multipathing using three vendors of dual-port NVMe SSDs. Signed-off-by: Baegjae Sung --- drivers/nvme/host/core.c | 12 +++--------- drivers/nvme/host/multipath.c | 15 ++++++++++----- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 0fe7ea35c221..817e5e2766da 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2844,7 +2844,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl, } static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid, - struct nvme_id_ns *id, bool *new) + struct nvme_id_ns *id) { struct nvme_ctrl *ctrl = ns->ctrl; bool is_shared = id->nmic & (1 << 0); @@ -2860,8 +2860,6 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid, ret = PTR_ERR(head); goto out_unlock; } - - *new = true; } else { struct nvme_ns_ids ids; @@ -2873,8 +2871,6 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid, ret = -EINVAL; goto out_unlock; } - - *new = false; } list_add_tail(&ns->siblings, &head->list); @@ -2945,7 +2941,6 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) struct nvme_id_ns *id; char disk_name[DISK_NAME_LEN]; int node = dev_to_node(ctrl->dev), flags = GENHD_FL_EXT_DEVT; - bool new = true; ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node); if (!ns) @@ -2971,7 +2966,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) if (id->ncap == 0) goto out_free_id; - if (nvme_init_ns_head(ns, nsid, id, &new)) + if (nvme_init_ns_head(ns, nsid, id)) goto out_free_id; nvme_setup_streams_ns(ctrl, ns); @@ -3037,8 +3032,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) pr_warn("%s: failed to register lightnvm sysfs group for identification\n", ns->disk->disk_name); - if (new) - nvme_mpath_add_disk(ns->head); + nvme_mpath_add_disk(ns->head); nvme_mpath_add_disk_links(ns); return; out_unlink_ns: diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 3b211d9e58b8..b7e5c6db4d92 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -198,11 +198,16 @@ void nvme_mpath_add_disk(struct nvme_ns_head *head) { if (!head->disk) return; - device_add_disk(&head->subsys->dev, head->disk); - if (sysfs_create_group(&disk_to_dev(head->disk)->kobj, - &nvme_ns_id_attr_group)) - pr_warn("%s: failed to create sysfs group for identification\n", - head->disk->disk_name); + + mutex_lock(&head->subsys->lock); + if (!(head->disk->flags & GENHD_FL_UP)) { + device_add_disk(&head->subsys->dev, head->disk); + if (sysfs_create_group(&disk_to_dev(head->disk)->kobj, + &nvme_ns_id_attr_group)) + pr_warn("%s: failed to create sysfs group for identification\n", + head->disk->disk_name); + } + mutex_unlock(&head->subsys->lock); } void nvme_mpath_add_disk_links(struct nvme_ns *ns) -- 2.16.2