From patchwork Wed Jul 8 11:09:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 6745021 Return-Path: X-Original-To: patchwork-linux-scsi@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 972C09F319 for ; Wed, 8 Jul 2015 11:10:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9226E2060F for ; Wed, 8 Jul 2015 11:10:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6617E2060C for ; Wed, 8 Jul 2015 11:10:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933851AbbGHLKC (ORCPT ); Wed, 8 Jul 2015 07:10:02 -0400 Received: from cantor2.suse.de ([195.135.220.15]:45660 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933800AbbGHLJw (ORCPT ); Wed, 8 Jul 2015 07:09:52 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 56450ABC9; Wed, 8 Jul 2015 11:09:50 +0000 (UTC) From: Hannes Reinecke To: James Bottomley Cc: Bart van Assche , Christoph Hellwig , linux-scsi@vger.kernel.org, Ewan Milne , Hannes Reinecke Subject: [PATCH 2/5] scsi_dh: add 'rescan' callback Date: Wed, 8 Jul 2015 13:09:45 +0200 Message-Id: <1436353788-104911-3-git-send-email-hare@suse.de> X-Mailer: git-send-email 1.8.5.2 In-Reply-To: <1436353788-104911-1-git-send-email-hare@suse.de> References: <1436353788-104911-1-git-send-email-hare@suse.de> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 If a device needs to be rescanned the device_handler might need to be rechecked, too. So add a 'rescan' callback to the device handler and call it upon scsi_rescan_device(). Signed-off-by: Hannes Reinecke --- drivers/scsi/device_handler/scsi_dh_alua.c | 53 +++++++++++++++++++++++------- drivers/scsi/scsi_lib.c | 1 + drivers/scsi/scsi_scan.c | 8 ++++- include/scsi/scsi_dh.h | 1 + 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index e4cabc8..5b52017 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -262,7 +262,8 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) int group_id = -1; char device_id_str[256], *device_id = NULL; int device_id_size, device_id_type = 0; - struct alua_port_group *tmp_pg, *pg = NULL; + struct alua_port_group *tmp_pg, *pg = NULL, *old_pg = NULL; + bool pg_found = false; rcu_read_lock(); if (!rcu_dereference(sdev->vpd_pg83)) { @@ -407,17 +408,25 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) if (memcmp(tmp_pg->device_id, device_id, device_id_size)) continue; - kref_get(&tmp_pg->kref); spin_lock(&h->pg_lock); - rcu_assign_pointer(h->pg, tmp_pg); + pg = rcu_dereference(h->pg); + if (pg) { + /* + * This can happen if the VPD information changed + */ + if (tmp_pg != pg) { + old_pg = pg; + kref_get(&tmp_pg->kref); + rcu_assign_pointer(h->pg, tmp_pg); + } + pg_found = true; + } spin_unlock(&h->pg_lock); break; } spin_unlock(&port_group_lock); - if (h->pg) { - synchronize_rcu(); - return SCSI_DH_OK; - } + if (pg_found) + goto out; pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL); if (!pg) { @@ -466,12 +475,17 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) if (memcmp(tmp_pg->device_id, pg->device_id, device_id_size)) continue; - kref_get(&tmp_pg->kref); spin_lock(&h->pg_lock); - rcu_assign_pointer(h->pg, tmp_pg); + pg = rcu_dereference(h->pg); + if (pg) { + if (tmp_pg != pg) { + old_pg = pg; + kref_get(&tmp_pg->kref); + rcu_assign_pointer(h->pg, tmp_pg); + } + pg = NULL; + } spin_unlock(&h->pg_lock); - kfree(pg); - pg = NULL; break; } if (pg) { @@ -481,6 +495,13 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h) spin_unlock(&h->pg_lock); } spin_unlock(&port_group_lock); +out: + if (old_pg) { + synchronize_rcu(); + if (old_pg->rtpg_sdev) + flush_workqueue(old_pg->work_q); + kref_put(&pg->kref, release_port_group); + } return SCSI_DH_OK; } @@ -1011,6 +1032,8 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) kref_get(&pg->kref); rcu_read_unlock(); } + } else { + WARN_ON(rcu_dereference(h->pg)); } complete(&h->init_complete); if (pg) { @@ -1195,6 +1218,13 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) } +static void alua_rescan(struct scsi_device *sdev) +{ + struct alua_dh_data *h = sdev->handler_data; + + alua_initialize(sdev, h); +} + /* * alua_bus_attach - Attach device handler * @sdev: device to be attached to @@ -1256,6 +1286,7 @@ static struct scsi_device_handler alua_dh = { .prep_fn = alua_prep_fn, .check_sense = alua_check_sense, .activate = alua_activate, + .rescan = alua_rescan, .set_params = alua_set_params, }; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 18ab4ad..991b9e1 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2704,6 +2704,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt) envp[idx++] = "SDEV_MEDIA_CHANGE=1"; break; case SDEV_EVT_INQUIRY_CHANGE_REPORTED: + scsi_rescan_device(&sdev->sdev_gendev); envp[idx++] = "SDEV_UA=INQUIRY_DATA_HAS_CHANGED"; break; case SDEV_EVT_CAPACITY_CHANGE_REPORTED: diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 190d743..5d3e2ae 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "scsi_priv.h" @@ -1516,9 +1517,14 @@ EXPORT_SYMBOL(scsi_add_device); void scsi_rescan_device(struct device *dev) { + struct scsi_device *sdev = to_scsi_device(dev); + device_lock(dev); - scsi_attach_vpd(to_scsi_device(dev)); + scsi_attach_vpd(sdev); + + if (sdev->handler && sdev->handler->rescan) + sdev->handler->rescan(sdev); if (dev->driver && try_module_get(dev->driver->owner)) { struct scsi_driver *drv = to_scsi_driver(dev->driver); diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 85d7317..5c73062 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h @@ -70,6 +70,7 @@ struct scsi_device_handler { int (*activate)(struct scsi_device *, activate_complete, void *); int (*prep_fn)(struct scsi_device *, struct request *); int (*set_params)(struct scsi_device *, const char *); + void (*rescan)(struct scsi_device *); }; #ifdef CONFIG_SCSI_DH