From patchwork Thu Mar 14 14:08:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 2271391 Return-Path: X-Original-To: patchwork-dm-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from mx4-phx2.redhat.com (mx4-phx2.redhat.com [209.132.183.25]) by patchwork2.kernel.org (Postfix) with ESMTP id 0F63CDFB79 for ; Thu, 14 Mar 2013 14:12:12 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx4-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r2EE90lb008397; Thu, 14 Mar 2013 10:09:02 -0400 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r2EE8x42021396 for ; Thu, 14 Mar 2013 10:08:59 -0400 Received: from mx1.redhat.com (ext-mx13.extmail.prod.ext.phx2.redhat.com [10.5.110.18]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r2EE8x2D024432 for ; Thu, 14 Mar 2013 10:08:59 -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 r2EE8opk029317 for ; Thu, 14 Mar 2013 10:08:51 -0400 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 03299A5234; Thu, 14 Mar 2013 15:08:50 +0100 (CET) From: Hannes Reinecke To: dm-devel@redhat.com Date: Thu, 14 Mar 2013 15:08:47 +0100 Message-Id: <1363270128-20900-6-git-send-email-hare@suse.de> In-Reply-To: <1363270128-20900-1-git-send-email-hare@suse.de> References: <1363270128-20900-1-git-send-email-hare@suse.de> X-RedHat-Spam-Score: -9.302 (BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, URIBL_BLOCKED) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-Scanned-By: MIMEDefang 2.68 on 10.5.110.18 X-loop: dm-devel@redhat.com Cc: Christophe Varoqui Subject: [dm-devel] [PATCH 5/6] libmultipath: Implement sysfs_set_fc_rport_state() 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 In a faulty fabric FC HBAs might not be able to update the status of the remote ports, resulting in I/O to be stuck as the normal 'fast_io_fail' mechanism it never invoked. To handle these cases I've implemented a function sysfs_set_fc_rport_state() which allows multipath to forcibly set the rport state to 'blocked', causing the fast_io_fail mechanism to be invoked, which eventually will abort all stuck I/O. This patch relies on the patch scsi_transport_fc: Make 'port_state' writeable posted to linux-scsi. Signed-off-by: Hannes Reinecke --- libmultipath/discovery.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++ libmultipath/discovery.h | 1 + 2 files changed, 61 insertions(+) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 58ce533..3b60125 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -476,6 +476,66 @@ sysfs_set_scsi_tmo (struct multipath *mpp) } int +sysfs_set_fc_rport_state (struct path *pp, int blocked) +{ + struct udev_device *rport_dev = NULL; + char rport_id[32]; + char value[NAME_SIZE]; + int retval = 0; + + if (pp->bus != SYSFS_BUS_SCSI) { + condlog(4, "%s: no FC settings on non-SCSI device", pp->dev); + return 0; + } + + sprintf(rport_id, "rport-%d:%d-%d", + pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); + rport_dev = udev_device_new_from_subsystem_sysname(conf->udev, + "fc_remote_ports", rport_id); + if (!rport_dev) { + condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev, + rport_id); + return 0; + } + + if (sysfs_attr_get_value(rport_dev, "port_state", + value, 16) <= 0) { + condlog(1, "%s: failed to read rport state from '%s'", + pp->dev, rport_id); + retval = EBADF; + goto out; + } + condlog(3, "%s: rport state '%s'", pp->dev, value); + if (blocked) { + /* Can only transition Online -> Blocked */ + if (strncmp(value, "Online", 6)) { + retval = EAGAIN; + goto out; + } + sprintf(value, "Blocked"); + } else { + /* Can only transition Blocked -> Online */ + if (strncmp(value, "Blocked", 7)) { + retval = EAGAIN; + goto out; + } + + sprintf(value, "Online"); + } + + if (sysfs_attr_set_value(rport_dev, "port_state", + value, strlen(value)) <= 0) { + condlog(1, "%s: failed to set rport to '%s', error %d", + pp->dev, value, errno); + retval = ENXIO; + } +out: + udev_device_unref(rport_dev); + + return retval; +} + +int do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, void *resp, int mx_resp_len) { diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h index 1a614ee..38b61dc 100644 --- a/libmultipath/discovery.h +++ b/libmultipath/discovery.h @@ -38,6 +38,7 @@ int store_pathinfo (vector pathvec, vector hwtable, struct path **pp_ptr); int sysfs_set_scsi_tmo (struct multipath *mpp); int sysfs_get_timeout(struct path *pp, unsigned int *timeout); +int sysfs_set_fc_rport_state(struct path *pp, int blocked); /* * discovery bitmask