From owner-freebsd-scsi@FreeBSD.ORG Mon May 10 04:20:04 2010 Return-Path: Delivered-To: freebsd-scsi@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 1AC77106566B; Mon, 10 May 2010 04:20:04 +0000 (UTC) (envelope-from linimon@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id E5C688FC0C; Mon, 10 May 2010 04:20:03 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id o4A4K3ES091896; Mon, 10 May 2010 04:20:03 GMT (envelope-from linimon@freefall.freebsd.org) Received: (from linimon@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id o4A4K3n3091892; Mon, 10 May 2010 04:20:03 GMT (envelope-from linimon) Date: Mon, 10 May 2010 04:20:03 GMT Message-Id: <201005100420.o4A4K3n3091892@freefall.freebsd.org> To: linimon@FreeBSD.org, freebsd-amd64@FreeBSD.org, freebsd-scsi@FreeBSD.org From: linimon@FreeBSD.org Cc: Subject: Re: kern/145768: [mpt] can't perform I/O on SAS based SAN disk in freebsd 7 and 8 X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 May 2010 04:20:04 -0000 Old Synopsis: can't perform I/O on SAS based SAN disk in freebsd 7 and 8 New Synopsis: [mpt] can't perform I/O on SAS based SAN disk in freebsd 7 and 8 Responsible-Changed-From-To: freebsd-amd64->freebsd-scsi Responsible-Changed-By: linimon Responsible-Changed-When: Mon May 10 04:18:32 UTC 2010 Responsible-Changed-Why: Over to maintainer(s). http://www.freebsd.org/cgi/query-pr.cgi?pr=145768 From owner-freebsd-scsi@FreeBSD.ORG Mon May 10 06:30:06 2010 Return-Path: Delivered-To: freebsd-scsi@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id A7F711065672 for ; Mon, 10 May 2010 06:30:06 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id 7D0FD8FC1C for ; Mon, 10 May 2010 06:30:06 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id o4A6U67i010307 for ; Mon, 10 May 2010 06:30:06 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id o4A6U6bG010302; Mon, 10 May 2010 06:30:06 GMT (envelope-from gnats) Date: Mon, 10 May 2010 06:30:06 GMT Message-Id: <201005100630.o4A6U6bG010302@freefall.freebsd.org> To: freebsd-scsi@FreeBSD.org From: Matthew Jacob Cc: Subject: Re: kern/145768: [mpt] can't perform I/O on SAS based SAN disk in freebsd 7 and 8 X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Matthew Jacob List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 May 2010 06:30:06 -0000 The following reply was made to PR kern/145768; it has been noted by GNATS. From: Matthew Jacob To: bug-followup@FreeBSD.org, tracproject@gmail.com Cc: Subject: Re: kern/145768: [mpt] can't perform I/O on SAS based SAN disk in freebsd 7 and 8 Date: Sun, 09 May 2010 23:24:53 -0700 More information is needed. The URL does not resolve, so getting technical details about the attached hardware seems not possible. The messages reported via g_vfs are just simply EIO. Surely there must be other relevant messages you can share. From owner-freebsd-scsi@FreeBSD.ORG Mon May 10 11:07:06 2010 Return-Path: Delivered-To: freebsd-scsi@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 5E77F1065673 for ; Mon, 10 May 2010 11:07:06 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id 4CF908FC1D for ; Mon, 10 May 2010 11:07:06 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id o4AB76WC082207 for ; Mon, 10 May 2010 11:07:06 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id o4AB75VV082205 for freebsd-scsi@FreeBSD.org; Mon, 10 May 2010 11:07:05 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 10 May 2010 11:07:05 GMT Message-Id: <201005101107.o4AB75VV082205@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-scsi@FreeBSD.org Cc: Subject: Current problem reports assigned to freebsd-scsi@FreeBSD.org X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 May 2010 11:07:06 -0000 Note: to view an individual PR, use: http://www.freebsd.org/cgi/query-pr.cgi?pr=(number). The following is a listing of current problems submitted by FreeBSD users. These represent problem reports covering all versions including experimental development code and obsolete releases. S Tracker Resp. Description -------------------------------------------------------------------------------- o kern/146287 scsi [ciss] ciss(4) cannot see more than one SmartArray con o kern/145768 scsi [mpt] can't perform I/O on SAS based SAN disk in freeb o kern/144648 scsi [aac] Strange values of speed and bus width in dmesg o kern/144301 scsi [ciss] [hang] HP proliant server locks when using ciss o kern/142351 scsi [mpt] LSILogic driver performance problems o kern/141934 scsi [cam] [patch] add support for SEAGATE DAT Scopion 130 o kern/134488 scsi [mpt] MPT SCSI driver probes max. 8 LUNs per device o kern/132250 scsi [ciss] ciss driver does not support more then 15 drive o kern/132206 scsi [mpt] system panics on boot when mirroring and 2nd dri p kern/130735 scsi [cam] [patch] pass M_NOWAIT to the malloc() call insid o kern/130621 scsi [mpt] tranfer rate is inscrutable slow when use lsi213 o kern/129602 scsi [ahd] ahd(4) gets confused and wedges SCSI bus o kern/128452 scsi [sa] [panic] Accessing SCSI tape drive randomly crashe o kern/128245 scsi [scsi] "inquiry data fails comparison at DV1 step" [re o kern/127927 scsi [isp] isp(4) target driver crashes kernel when set up o kern/124667 scsi [amd] [panic] FreeBSD-7 kernel page faults at amd-scsi o kern/123674 scsi [ahc] ahc driver dumping f kern/123666 scsi [aac] attach fails with Adaptec SAS RAID 3805 controll o sparc/121676 scsi [iscsi] iscontrol do not connect iscsi-target on sparc o kern/120487 scsi [sg] scsi_sg incompatible with scanners o kern/120247 scsi [mpt] FreeBSD 6.3 and LSI Logic 1030 = only 3.300MB/s o kern/119668 scsi [cam] [patch] certain errors are too verbose comparing o kern/114597 scsi [sym] System hangs at SCSI bus reset with dual HBAs o kern/110847 scsi [ahd] Tyan U320 onboard problem with more than 3 disks o kern/99954 scsi [ahc] reading from DVD failes on 6.x [regression] o kern/94838 scsi Kernel panic while mounting SD card with lock switch o o kern/92798 scsi [ahc] SCSI problem with timeouts o kern/90282 scsi [sym] SCSI bus resets cause loss of ch device o kern/76178 scsi [ahd] Problem with ahd and large SCSI Raid system o kern/74627 scsi [ahc] [hang] Adaptec 2940U2W Can't boot 5.3 s kern/61165 scsi [panic] kernel page fault after calling cam_send_ccb o kern/60641 scsi [sym] Sporadic SCSI bus resets with 53C810 under load o kern/60598 scsi wire down of scsi devices conflicts with config s kern/57398 scsi [mly] Current fails to install on mly(4) based RAID di o kern/52638 scsi [panic] SCSI U320 on SMP server won't run faster than o kern/44587 scsi dev/dpt/dpt.h is missing defines required for DPT_HAND o kern/40895 scsi wierd kernel / device driver bug o kern/39388 scsi ncr/sym drivers fail with 53c810 and more than 256MB m o kern/35234 scsi World access to /dev/pass? (for scanner) requires acce 39 problems total. From owner-freebsd-scsi@FreeBSD.ORG Thu May 13 05:01:45 2010 Return-Path: Delivered-To: freebsd-scsi@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9492D1065670 for ; Thu, 13 May 2010 05:01:45 +0000 (UTC) (envelope-from mj@feral.com) Received: from ns1.feral.com (ns1.feral.com [192.67.166.1]) by mx1.freebsd.org (Postfix) with ESMTP id 1B4138FC1C for ; Thu, 13 May 2010 05:01:44 +0000 (UTC) Received: from [172.16.135.100] (lportal.in1.lcl [172.16.1.9]) by ns1.feral.com (8.14.3/8.14.3) with ESMTP id o4D51ihN091326 for ; Wed, 12 May 2010 22:01:44 -0700 (PDT) (envelope-from mj@feral.com) Message-ID: <4BEB87B8.1070104@feral.com> Date: Wed, 12 May 2010 22:01:44 -0700 From: Matthew Jacob Organization: Feral Software User-Agent: Thunderbird 2.0.0.24 (Windows/20100228) MIME-Version: 1.0 To: freebsd-scsi@freebsd.org Content-Type: multipart/mixed; boundary="------------010007070401000608000906" X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.2.3 (ns1.feral.com [192.168.221.1]); Wed, 12 May 2010 22:01:44 -0700 (PDT) Subject: patches for CAM SCSI probing, etc. X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 May 2010 05:01:45 -0000 This is a multi-part message in MIME format. --------------010007070401000608000906 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit [ prefatory note: these patches incorporate the work done by Alexander Motin for protecting the periph driver list. I am pretty eager for comments on this. This ended up being a tougher nut to crack than I thought. ] This is a set of patches that attempts to address the generalized problem of dealing with SCSI devices that are being unconfigured at the same time that they are being configured. There are essentially 3 problems that these pataches address. The first problem with race conditions with configuring and deconfiguring SCSI devices is that the periph_drivers list was not lock protected. The changes to address this are in cam_periph.c and the top of cam_xpt.c. and mostly come from Alexander Motin at FreeBSD.org. I found and fixed a potential problem for a periph refcount going negative and rearranged Alexander's patch slightly to get a bit more cohesion. The general idea here is to protect the periph driver list with the cam XPT topology lock. I also added an assert that we can never look up a periph without the SIM mutex being owned. This (barely) covers us in case where a periph might want to go away in between cam_periph_find and cam_periph_acquire. The second problem has to do with making sure that the probe sequence for finding new devices correctly stops when it detects an error, and furthermore, leaves the device queues correctly unfrozen when this occurs. This is contained in the large number of changes in scsi/scsi_xpt.c:probedone. The gist of these changes is to stop trying to probe a device that has been found to have an uncorrectable error during probe and might in fact be deallocated already. I also more closely followed what Alexander did with ata/ata_xpt.c in that by the time you break out of the switch statement at the bottom of probedone, you're going to be tearing down the probe periph so it seemed to me to be dead code to call back to probestart. The third problem has to do with making sure that different subsystems that do things in an uncoordinated fashion don't get surprised by unexpected dealloaction of devices. The da driver (scsi_da.c) interacts both with the GEOM and SYSCTL subsystems when a device arrives. Unfortunately there is no shared locking that coordinate actions between callbacks from the GEOM and SYSCTL subsystems in an entirely safe way. For SYSCTL, increasing the refcount on the CAM periph structure is allowed because we know da will be called back later to create the SYSCTL tree for this da instance. This keeps the periph from going away unexpectedly. At that point of time in a callback, the validity of the periph structure can be rechecked safely. For GEOM, I haven't specifically done anything, but there is a race condition where if you have specified a ioctl entry point in the disk structure, GEOM will call back on it during device tasting. There is just no existing good way to protect yourself from blowing up without adding some extra one-off barrier locking. This is not present in this patch set because the default FreeBSD disk driver does not, in fact, have an ioctl entry point (but the one at Panasas does). In order to really test this stuff, a "Fake HBA" and "Fake Disk" that I've come up with was used. Using the 'faulty' subclass for it, this fake HBA and fake DISK creates 512 fake disks (64 targets with 8 luns) but every 255 operations received 'fails' that operation with a SELECT TIMEOUT error. Running repeated and simulataneous 'camcontrol rescans' over this bus exercises repeated probe/fail/probe/fail scenarios. I've had overnight runs with this testing now, whereas previously I would die within minutes. --------------010007070401000608000906 Content-Type: text/plain; name="BIG_CAM_PATCH" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="BIG_CAM_PATCH" diff -ru sys/cam/cam_periph.c /space/FreeBSD/work/sys/cam/cam_periph.c --- sys/cam/cam_periph.c 2010-04-04 09:35:26.000000000 -0700 +++ /space/FreeBSD/work/sys/cam/cam_periph.c 2010-05-12 21:28:18.000000000 -0700 @@ -185,17 +185,6 @@ init_level++; - xpt_lock_buses(); - for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { - if (strcmp((*p_drv)->driver_name, name) == 0) - break; - } - xpt_unlock_buses(); - if (*p_drv == NULL) { - printf("cam_periph_alloc: invalid periph name '%s'\n", name); - free(periph, M_CAMPERIPH); - return (CAM_REQ_INVALID); - } sim = xpt_path_sim(path); path_id = xpt_path_path_id(path); @@ -208,7 +197,6 @@ periph->periph_oninval = periph_oninvalidate; periph->type = type; periph->periph_name = name; - periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id); periph->immediate_priority = CAM_PRIORITY_NONE; periph->refcount = 0; periph->sim = sim; @@ -216,26 +204,39 @@ status = xpt_create_path(&path, periph, path_id, target_id, lun_id); if (status != CAM_REQ_CMP) goto failure; - periph->path = path; - init_level++; - - status = xpt_add_periph(periph); - - if (status != CAM_REQ_CMP) - goto failure; + xpt_lock_buses(); + for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { + if (strcmp((*p_drv)->driver_name, name) == 0) + break; + } + if (*p_drv == NULL) { + printf("cam_periph_alloc: invalid periph name '%s'\n", name); + xpt_free_path(periph->path); + free(periph, M_CAMPERIPH); + xpt_unlock_buses(); + return (CAM_REQ_INVALID); + } + periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id); cur_periph = TAILQ_FIRST(&(*p_drv)->units); while (cur_periph != NULL && cur_periph->unit_number < periph->unit_number) cur_periph = TAILQ_NEXT(cur_periph, unit_links); - - if (cur_periph != NULL) + if (cur_periph != NULL) { + KASSERT(cur_periph->unit_number != periph->unit_number, ("duplicate units on periph list")); TAILQ_INSERT_BEFORE(cur_periph, periph, unit_links); - else { + } else { TAILQ_INSERT_TAIL(&(*p_drv)->units, periph, unit_links); (*p_drv)->generation++; } + xpt_unlock_buses(); + + init_level++; + + status = xpt_add_periph(periph); + if (status != CAM_REQ_CMP) + goto failure; init_level++; @@ -250,10 +251,12 @@ /* Initialized successfully */ break; case 3: - TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links); xpt_remove_periph(periph); /* FALLTHROUGH */ case 2: + xpt_lock_buses(); + TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links); + xpt_unlock_buses(); xpt_free_path(periph->path); /* FALLTHROUGH */ case 1: @@ -288,6 +291,7 @@ TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) { if (xpt_path_comp(periph->path, path) == 0) { xpt_unlock_buses(); + mtx_assert(periph->sim->mtx, MA_OWNED); return(periph); } } @@ -322,8 +326,13 @@ return; xpt_lock_buses(); - if ((--periph->refcount == 0) - && (periph->flags & CAM_PERIPH_INVALID)) { + if (periph->refcount != 0) { + periph->refcount--; + } else { + xpt_print(periph->path, "%s: release %p when refcount is zero\n ", __func__, periph); + } + if (periph->refcount == 0 + && (periph->flags & CAM_PERIPH_INVALID)) { camperiphfree(periph); } xpt_unlock_buses(); diff -ru sys/cam/cam_xpt.c /space/FreeBSD/work/sys/cam/cam_xpt.c --- sys/cam/cam_xpt.c 2010-05-02 04:16:42.000000000 -0700 +++ /space/FreeBSD/work/sys/cam/cam_xpt.c 2010-05-12 21:34:02.000000000 -0700 @@ -2115,6 +2115,7 @@ retval = 1; + xpt_lock_buses(); for (periph = (start_periph ? start_periph : TAILQ_FIRST(&(*pdrv)->units)); periph != NULL; periph = next_periph) { @@ -2122,9 +2123,12 @@ next_periph = TAILQ_NEXT(periph, unit_links); retval = tr_func(periph, arg); - if (retval == 0) + if (retval == 0) { + xpt_unlock_buses(); return(retval); + } } + xpt_unlock_buses(); return(retval); } @@ -2300,7 +2304,6 @@ CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_action_default\n")); - switch (start_ccb->ccb_h.func_code) { case XPT_SCSI_IO: { @@ -2647,7 +2650,9 @@ xptedtmatch(cdm); break; case CAM_DEV_POS_PDRV: + xpt_lock_buses(); xptperiphlistmatch(cdm); + xpt_unlock_buses(); break; default: cdm->status = CAM_DEV_MATCH_ERROR; diff -ru sys/cam/scsi/scsi_da.c /space/FreeBSD/work/sys/cam/scsi/scsi_da.c --- sys/cam/scsi/scsi_da.c 2010-04-02 12:08:45.000000000 -0800 +++ /space/FreeBSD/work/sys/cam/scsi/scsi_da.c 2010-05-12 21:28:18.000000000 -0700 @@ -997,11 +997,6 @@ xpt_print(periph->path, "can't remove sysctl context\n"); } - /* - * Nullify our periph pointer here to try and catch - * race conditions in callbacks/downcalls. - */ - softc->disk->d_drv1 = NULL; disk_destroy(softc->disk); callout_drain(&softc->sendordered_c); free(softc, M_DEVBUF); @@ -1080,8 +1075,13 @@ char tmpstr[80], tmpstr2[80]; periph = (struct cam_periph *)context; - if (cam_periph_acquire(periph) != CAM_REQ_CMP) + /* + * periph was held for us when this task was enqueued + */ + if (periph->flags & CAM_PERIPH_INVALID) { + cam_periph_release(periph); return; + } softc = (struct da_softc *)periph->softc; snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number); @@ -1237,29 +1237,6 @@ * Register this media as a disk */ - mtx_unlock(periph->sim->mtx); - softc->disk = disk_alloc(); - softc->disk->d_open = daopen; - softc->disk->d_close = daclose; - softc->disk->d_strategy = dastrategy; - softc->disk->d_dump = dadump; - softc->disk->d_name = "da"; - softc->disk->d_drv1 = periph; - if (cpi.maxio == 0) - softc->disk->d_maxsize = DFLTPHYS; /* traditional default */ - else if (cpi.maxio > MAXPHYS) - softc->disk->d_maxsize = MAXPHYS; /* for safety */ - else - softc->disk->d_maxsize = cpi.maxio; - softc->disk->d_unit = periph->unit_number; - softc->disk->d_flags = 0; - if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) - softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; - strlcpy(softc->disk->d_ident, cgd->serial_num, - MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1)); - disk_create(softc->disk, DISK_VERSION); - mtx_lock(periph->sim->mtx); - /* * Add async callbacks for bus reset and * bus device reset calls. I don't bother @@ -1277,7 +1254,6 @@ * the end of probe. */ (void)cam_periph_hold(periph, PRIBIO); - xpt_schedule(periph, CAM_PRIORITY_DEV); /* * Schedule a periodic event to occasionally send an @@ -1288,6 +1264,31 @@ (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL, dasendorderedtag, softc); + mtx_unlock(periph->sim->mtx); + softc->disk = disk_alloc(); + softc->disk->d_open = daopen; + softc->disk->d_close = daclose; + softc->disk->d_strategy = dastrategy; + softc->disk->d_dump = dadump; + softc->disk->d_name = "da"; + softc->disk->d_drv1 = periph; + if (cpi.maxio == 0) + softc->disk->d_maxsize = DFLTPHYS; /* traditional default */ + else if (cpi.maxio > MAXPHYS) + softc->disk->d_maxsize = MAXPHYS; /* for safety */ + else + softc->disk->d_maxsize = cpi.maxio; + softc->disk->d_unit = periph->unit_number; + softc->disk->d_flags = 0; + if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) + softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; + strlcpy(softc->disk->d_ident, cgd->serial_num, + MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1)); + disk_create(softc->disk, DISK_VERSION); + mtx_lock(periph->sim->mtx); + + xpt_schedule(periph, CAM_PRIORITY_DEV); + return(CAM_REQ_CMP); } @@ -1747,6 +1748,7 @@ * Create our sysctl variables, now that we know * we have successfully attached. */ + (void) cam_periph_acquire(periph); /* increase the refcount */ taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task); } softc->state = DA_STATE_NORMAL; diff -ru sys/cam/scsi/scsi_xpt.c /space/FreeBSD/work/sys/cam/scsi/scsi_xpt.c --- sys/cam/scsi/scsi_xpt.c 2010-02-26 18:20:06.000000000 -0800 +++ /space/FreeBSD/work/sys/cam/scsi/scsi_xpt.c 2010-05-12 21:28:18.000000000 -0700 @@ -1005,53 +1005,49 @@ return (1); } +#define PCHK(d, f) cam_periph_error((d), 0, (f), NULL) == ERESTART +#define PCHK_S(d, f, s) \ + cam_periph_error((d), 0, (f), &(s)->saved_ccb) == ERESTART + static void probedone(struct cam_periph *periph, union ccb *done_ccb) { probe_softc *softc; struct cam_path *path; - u_int32_t priority; + cam_status status; + int frozen; + u_int32_t priority; CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); softc = (probe_softc *)periph->softc; path = done_ccb->ccb_h.path; priority = done_ccb->ccb_h.pinfo.priority; + status = done_ccb->ccb_h.status & CAM_STATUS_MASK; + frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0; switch (softc->action) { case PROBE_TUR: - { - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - - if (cam_periph_error(done_ccb, 0, - SF_NO_PRINT, NULL) == ERESTART) - return; - else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, - /*count*/1, - /*run_queue*/TRUE); - } - PROBE_SET_ACTION(softc, PROBE_INQUIRY); - xpt_release_ccb(done_ccb); - xpt_schedule(periph, priority); - return; - } + if (status == CAM_REQ_CMP) { + PROBE_SET_ACTION(softc, PROBE_INQUIRY); + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + if (PCHK(done_ccb, SF_NO_PRINT)) + return; + status = CAM_REQ_CMP_ERR; + break; case PROBE_INQUIRY: case PROBE_FULL_INQUIRY: { - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + if (status == CAM_REQ_CMP) { struct scsi_inquiry_data *inq_buf; - u_int8_t periph_qual; path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID; inq_buf = &path->device->inq_data; - periph_qual = SID_QUAL(inq_buf); - - switch(periph_qual) { - case SID_QUAL_LU_CONNECTED: - { + if (SID_QUAL(inq_buf) == SID_QUAL_LU_CONNECTED) { u_int8_t len; /* @@ -1069,7 +1065,8 @@ additional_length) + 1; if (softc->action == PROBE_INQUIRY && len > SHORT_INQUIRY_LENGTH) { - PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); + PROBE_SET_ACTION(softc, + PROBE_FULL_INQUIRY); xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); return; @@ -1079,31 +1076,29 @@ scsi_devise_transport(path); if (INQ_DATA_TQ_ENABLED(inq_buf)) - PROBE_SET_ACTION(softc, PROBE_MODE_SENSE); + PROBE_SET_ACTION(softc, + PROBE_MODE_SENSE); else - PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0); + PROBE_SET_ACTION(softc, + PROBE_SERIAL_NUM_0); - if (path->device->flags & CAM_DEV_UNCONFIGURED) { - path->device->flags &= ~CAM_DEV_UNCONFIGURED; + if (path->device->flags & + CAM_DEV_UNCONFIGURED) { + path->device->flags &= + ~CAM_DEV_UNCONFIGURED; xpt_acquire_device(path->device); } xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); return; } - default: - break; + } else { + int flags = SF_RETRY_UA; + if (done_ccb->ccb_h.target_lun > 0) + flags |= SF_QUIET_IR; + if (PCHK_S(done_ccb, flags, softc)) { + return; } - } else if (cam_periph_error(done_ccb, 0, - done_ccb->ccb_h.target_lun > 0 - ? SF_RETRY_UA|SF_QUIET_IR - : SF_RETRY_UA, - &softc->saved_ccb) == ERESTART) { - return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); } /* * If we get to this point, we got an error status back @@ -1119,7 +1114,7 @@ /* Send the async notification. */ xpt_async(AC_LOST_DEVICE, path, NULL); - xpt_release_ccb(done_ccb); + status = CAM_REQ_CMP_ERR; break; } case PROBE_MODE_SENSE: @@ -1129,7 +1124,7 @@ csio = &done_ccb->csio; mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr; - if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + if (status == CAM_REQ_CMP) { struct scsi_control_page *page; u_int8_t *offset; @@ -1137,20 +1132,18 @@ + mode_hdr->blk_desc_len; page = (struct scsi_control_page *)offset; path->device->queue_flags = page->queue_flags; - } else if (cam_periph_error(done_ccb, 0, - SF_RETRY_UA|SF_NO_PRINT, - &softc->saved_ccb) == ERESTART) { + } else if (PCHK_S(done_ccb, SF_RETRY_UA|SF_NO_PRINT, softc)) { return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, - /*count*/1, /*run_queue*/TRUE); } - xpt_release_ccb(done_ccb); free(mode_hdr, M_CAMXPT); - PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0); - xpt_schedule(periph, priority); - return; + if (status == CAM_REQ_CMP) { + PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_0); + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + status = CAM_REQ_CMP_ERR; + break; } case PROBE_SERIAL_NUM_0: { @@ -1167,8 +1160,7 @@ /* * Don't process the command as it was never sent */ - } else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP - && (page_list->length > 0)) { + } else if (status == CAM_REQ_CMP && page_list->length > 0) { length = min(page_list->length, SVPD_SUPPORTED_PAGES_SIZE); for (i = 0; i < length; i++) { @@ -1178,22 +1170,16 @@ break; } } - } else if (cam_periph_error(done_ccb, 0, - SF_RETRY_UA|SF_NO_PRINT, - &softc->saved_ccb) == ERESTART) { + } else if (PCHK_S(done_ccb, SF_RETRY_UA|SF_NO_PRINT, softc)) { return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); } if (page_list != NULL) free(page_list, M_CAMXPT); if (serialnum_supported) { - xpt_release_ccb(done_ccb); PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM_1); + xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); return; } @@ -1201,7 +1187,6 @@ csio->data_ptr = NULL; /* FALLTHROUGH */ } - case PROBE_SERIAL_NUM_1: { struct ccb_scsiio *csio; @@ -1210,7 +1195,11 @@ int changed; int have_serialnum; - changed = 1; + if (status == CAM_REQ_CMP) + changed = 1; + else { + changed = 0; + } have_serialnum = 0; csio = &done_ccb->csio; priority = done_ccb->ccb_h.pinfo.priority; @@ -1228,9 +1217,7 @@ /* * Don't process the command as it was never sent */ - } else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP - && (serial_buf->length > 0)) { - + } else if (status == CAM_REQ_CMP && serial_buf->length > 0) { have_serialnum = 1; path->device->serial_num = (u_int8_t *)malloc((serial_buf->length + 1), @@ -1244,20 +1231,14 @@ path->device->serial_num[serial_buf->length] = '\0'; } - } else if (cam_periph_error(done_ccb, 0, - SF_RETRY_UA|SF_NO_PRINT, - &softc->saved_ccb) == ERESTART) { + } else if (PCHK_S(done_ccb, SF_RETRY_UA|SF_NO_PRINT, softc)) { return; - } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); } /* * Let's see if we have seen this device before. */ - if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) { + if (changed && (softc->flags & PROBE_INQUIRY_CKSUM) != 0) { MD5_CTX context; u_int8_t digest[16]; @@ -1298,33 +1279,33 @@ * settings to set the device up. */ proberequestdefaultnegotiation(periph); - xpt_release_ccb(done_ccb); /* * Perform a TUR to allow the controller to * perform any necessary transfer negotiation. */ PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); + xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); return; } - xpt_release_ccb(done_ccb); + status = CAM_REQ_CMP_ERR; break; } case PROBE_TUR_FOR_NEGOTIATION: - if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (status != CAM_REQ_CMP) { DELAY(500000); - if (cam_periph_error(done_ccb, 0, SF_RETRY_UA, - NULL) == ERESTART) + if (PCHK(done_ccb, SF_RETRY_UA)) return; } - /* FALLTHROUGH */ + /* FALLTHROUGH */ case PROBE_DV_EXIT: - if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); + + if (status != CAM_REQ_CMP) { + status = CAM_REQ_CMP_ERR; + break; } + /* * Do Domain Validation for lun 0 on devices that claim * to support Synchronous Transfer modes. @@ -1336,8 +1317,8 @@ CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Begin Domain Validation\n")); path->device->flags |= CAM_DEV_IN_DV; - xpt_release_ccb(done_ccb); PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1); + xpt_release_ccb(done_ccb); xpt_schedule(periph, priority); return; } @@ -1358,7 +1339,6 @@ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); } - xpt_release_ccb(done_ccb); break; case PROBE_INQUIRY_BASIC_DV1: case PROBE_INQUIRY_BASIC_DV2: @@ -1366,20 +1346,21 @@ struct scsi_inquiry_data *nbuf; struct ccb_scsiio *csio; - if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { - /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, - /*run_queue*/TRUE); - } csio = &done_ccb->csio; nbuf = (struct scsi_inquiry_data *)csio->data_ptr; + if (status != CAM_REQ_CMP) { + status = CAM_REQ_CMP_ERR; + free(nbuf, M_CAMXPT); + break; + } if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) { xpt_print(path, "inquiry data fails comparison at DV%d step\n", softc->action == PROBE_INQUIRY_BASIC_DV1 ? 1 : 2); if (proberequestbackoff(periph, path->device)) { path->device->flags &= ~CAM_DEV_IN_DV; - PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); + PROBE_SET_ACTION(softc, + PROBE_TUR_FOR_NEGOTIATION); } else { /* give up */ PROBE_SET_ACTION(softc, PROBE_DV_EXIT); @@ -1413,27 +1394,35 @@ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); } - xpt_release_ccb(done_ccb); break; } case PROBE_INVALID: - CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO, - ("probedone: invalid action state\n")); + status = CAM_REQ_CMP_ERR; + xpt_print(done_ccb->ccb_h.path, "%s: invalid action state\n", + __func__); + break; default: + status = CAM_REQ_CMP_ERR; + xpt_print(done_ccb->ccb_h.path, "%s: unknown action state %x\n", + __func__, softc->action); break; } - done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); - TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe); - done_ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(done_ccb); - if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { - cam_release_devq(periph->path, - RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); - cam_periph_invalidate(periph); - cam_periph_release_locked(periph); - } else { - probeschedule(periph); - } + if (frozen) { + xpt_release_devq_rl(done_ccb->ccb_h.path, + CAM_PRIORITY_TO_RL(done_ccb->ccb_h.pinfo.priority), + 1, TRUE); + } + xpt_release_ccb(done_ccb); + while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) { + TAILQ_REMOVE(&softc->request_ccbs, + &done_ccb->ccb_h, periph_links.tqe); + done_ccb->ccb_h.status = status; + xpt_done(done_ccb); + } + cam_release_devq(periph->path, + RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); + cam_periph_invalidate(periph); + cam_periph_release_locked(periph); } static void --------------010007070401000608000906-- From owner-freebsd-scsi@FreeBSD.ORG Sat May 15 01:15:36 2010 Return-Path: Delivered-To: freebsd-scsi@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1295B106566C for ; Sat, 15 May 2010 01:15:36 +0000 (UTC) (envelope-from mj@feral.com) Received: from ns1.feral.com (ns1.feral.com [192.67.166.1]) by mx1.freebsd.org (Postfix) with ESMTP id C9B598FC0C for ; Sat, 15 May 2010 01:15:35 +0000 (UTC) Received: from [192.168.0.102] (m206-63.dsl.tsoft.com [198.144.206.63]) by ns1.feral.com (8.14.3/8.14.3) with ESMTP id o4F1FZnS068863 for ; Fri, 14 May 2010 18:15:35 -0700 (PDT) (envelope-from mj@feral.com) Message-ID: <4BEDF5BD.9040502@feral.com> Date: Fri, 14 May 2010 18:15:41 -0700 From: Matthew Jacob User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 MIME-Version: 1.0 To: freebsd-scsi@freebsd.org Content-Type: multipart/mixed; boundary="------------040302060404000402050808" X-Greylist: Default is to whitelist mail, not delayed by milter-greylist-4.2.3 (ns1.feral.com [192.67.166.1]); Fri, 14 May 2010 18:15:35 -0700 (PDT) Subject: addition of an XPT_SCAN_TGT code X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 15 May 2010 01:15:36 -0000 This is a multi-part message in MIME format. --------------040302060404000402050808 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Sometimes, particularly in relation to a hotplug event, you just want to scan a target id, not the whole bus. It's lighter weight. The attached patch adds this with a relatively light touch. I'm not super happy with it, but it does make rescanning on a target basis doable. Comments? --------------040302060404000402050808 Content-Type: text/plain; name="TGT_SCAN.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="TGT_SCAN.diff" diff -r 85c0fa25a2fc sys/cam/ata/ata_xpt.c --- a/sys/cam/ata/ata_xpt.c Fri May 14 15:55:34 2010 -0700 +++ b/sys/cam/ata/ata_xpt.c Fri May 14 18:14:46 2010 -0700 @@ -1189,6 +1189,7 @@ ("xpt_scan_bus\n")); switch (request_ccb->ccb_h.func_code) { case XPT_SCAN_BUS: + case XPT_SCAN_TGT: /* Find out the characteristics of the bus */ work_ccb = xpt_alloc_ccb_nowait(); if (work_ccb == NULL) { @@ -1530,6 +1531,7 @@ break; } case XPT_SCAN_BUS: + case XPT_SCAN_TGT: ata_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); break; case XPT_SCAN_LUN: diff -r 85c0fa25a2fc sys/cam/cam_ccb.h --- a/sys/cam/cam_ccb.h Fri May 14 15:55:34 2010 -0700 +++ b/sys/cam/cam_ccb.h Fri May 14 18:14:46 2010 -0700 @@ -207,6 +207,10 @@ /* Notify Host Target driver of event */ XPT_NOTIFY_ACKNOWLEDGE = 0x37 | XPT_FC_QUEUED | XPT_FC_USER_CCB, /* Acknowledgement of event */ +/* overflow commands: 0x40 ->0x4F */ + XPT_SCAN_TGT = 0x40 | XPT_FC_QUEUED | XPT_FC_USER_CCB + | XPT_FC_XPT_ONLY, + /* (Re)Scan the SCSI Bus */ /* Vendor Unique codes: 0x80->0x8F */ XPT_VUNIQUE = 0x80 diff -r 85c0fa25a2fc sys/cam/cam_xpt.c --- a/sys/cam/cam_xpt.c Fri May 14 15:55:34 2010 -0700 +++ b/sys/cam/cam_xpt.c Fri May 14 18:14:46 2010 -0700 @@ -463,6 +463,13 @@ case XPT_PATH_INQ: case XPT_ENG_INQ: case XPT_SCAN_LUN: + case XPT_SCAN_TGT: + if (inccb->ccb_h.func_code == XPT_SCAN_TGT && + (inccb->ccb_h.target_id == CAM_TARGET_WILDCARD || + (inccb->ccb_h.target_lun != CAM_LUN_WILDCARD))) { + error = EINVAL; + break; + } ccb = xpt_alloc_ccb(); @@ -839,11 +846,21 @@ struct ccb_hdr *hdr; /* Prepare request */ - if (ccb->ccb_h.path->target->target_id == CAM_TARGET_WILDCARD || + if (ccb->ccb_h.path->target->target_id == CAM_TARGET_WILDCARD && ccb->ccb_h.path->device->lun_id == CAM_LUN_WILDCARD) ccb->ccb_h.func_code = XPT_SCAN_BUS; - else + else if (ccb->ccb_h.path->target->target_id != CAM_TARGET_WILDCARD && + ccb->ccb_h.path->device->lun_id == CAM_LUN_WILDCARD) + ccb->ccb_h.func_code = XPT_SCAN_TGT; + else if (ccb->ccb_h.path->target->target_id != CAM_TARGET_WILDCARD && + ccb->ccb_h.path->device->lun_id != CAM_LUN_WILDCARD) ccb->ccb_h.func_code = XPT_SCAN_LUN; + else { + xpt_print(ccb->ccb_h.path, "illegal scan path\n"); + xpt_free_path(ccb->ccb_h.path); + xpt_free_ccb(ccb); + return; + } ccb->ccb_h.ppriv_ptr1 = ccb->ccb_h.cbfcnp; ccb->ccb_h.cbfcnp = xpt_rescan_done; xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, CAM_PRIORITY_XPT); diff -r 85c0fa25a2fc sys/cam/scsi/scsi_xpt.c --- a/sys/cam/scsi/scsi_xpt.c Fri May 14 15:55:34 2010 -0700 +++ b/sys/cam/scsi/scsi_xpt.c Fri May 14 18:14:46 2010 -0700 @@ -1487,12 +1487,13 @@ ("scsi_scan_bus\n")); switch (request_ccb->ccb_h.func_code) { case XPT_SCAN_BUS: + case XPT_SCAN_TGT: { scsi_scan_bus_info *scan_info; union ccb *work_ccb, *reset_ccb; struct cam_path *path; u_int i; - u_int max_target; + u_int low_target, max_target; u_int initiator_id; /* Find out the characteristics of the bus */ @@ -1557,13 +1558,18 @@ /* Cache on our stack so we can work asynchronously */ max_target = scan_info->cpi->max_target; + low_target = 0; initiator_id = scan_info->cpi->initiator_id; /* * We can scan all targets in parallel, or do it sequentially. */ - if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { + + if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { + max_target = low_target = request_ccb->ccb_h.target_id; + scan_info->counter = 0; + } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { max_target = 0; scan_info->counter = 0; } else { @@ -1573,7 +1579,7 @@ } } - for (i = 0; i <= max_target; i++) { + for (i = low_target; i <= max_target; i++) { cam_status status; if (i == initiator_id) continue; @@ -1688,7 +1694,9 @@ hop_again: done = 0; - if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { + if (request_ccb->ccb_h.func_code == XPT_SCAN_TGT) { + done = 1; + } else if (scan_info->cpi->hba_misc & PIM_SEQSCAN) { scan_info->counter++; if (scan_info->counter == scan_info->cpi->initiator_id) { @@ -2009,6 +2017,7 @@ break; } case XPT_SCAN_BUS: + case XPT_SCAN_TGT: scsi_scan_bus(start_ccb->ccb_h.path->periph, start_ccb); break; case XPT_SCAN_LUN: diff -r 85c0fa25a2fc sys/dev/isp/isp_freebsd.c --- a/sys/dev/isp/isp_freebsd.c Fri May 14 15:55:34 2010 -0700 +++ b/sys/dev/isp/isp_freebsd.c Fri May 14 18:14:46 2010 -0700 @@ -3898,7 +3898,7 @@ * Scan the whole bus instead of target, which will then * force a scan of all luns. */ - if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(fc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(fc->sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan"); xpt_free_ccb(ccb); return; --------------040302060404000402050808--