From owner-svn-src-all@FreeBSD.ORG Fri May 1 08:03:47 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3EB6A1065679; Fri, 1 May 2009 08:03:47 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2BB0A8FC16; Fri, 1 May 2009 08:03:47 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n4183lUH036019; Fri, 1 May 2009 08:03:47 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4183kGE036016; Fri, 1 May 2009 08:03:46 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <200905010803.n4183kGE036016@svn.freebsd.org> From: Alexander Motin Date: Fri, 1 May 2009 08:03:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r191717 - head/sys/dev/ata X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 May 2009 08:03:47 -0000 Author: mav Date: Fri May 1 08:03:46 2009 New Revision: 191717 URL: http://svn.freebsd.org/changeset/base/191717 Log: Improve kernel dumping reliability for busy ATA channels: - Generate fake channel interrupts even if channel busy with previous request to let it finish. Without this, dumping requests were just queued and never processed. - Drop pre-dump requests queue on dumping. ATA code, working in dumping (interruptless) mode, unable to handle long request queue. Actually, to get coherent dump we anyway should do as few unrelated actions as possible. Modified: head/sys/dev/ata/ata-all.h head/sys/dev/ata/ata-disk.c head/sys/dev/ata/ata-queue.c Modified: head/sys/dev/ata/ata-all.h ============================================================================== --- head/sys/dev/ata/ata-all.h Fri May 1 03:24:03 2009 (r191716) +++ head/sys/dev/ata/ata-all.h Fri May 1 08:03:46 2009 (r191717) @@ -584,6 +584,7 @@ void ata_finish(struct ata_request *requ void ata_timeout(struct ata_request *); void ata_catch_inflight(device_t dev); void ata_fail_requests(device_t dev); +void ata_drop_requests(device_t dev); char *ata_cmd2str(struct ata_request *request); /* ata-lowlevel.c: */ Modified: head/sys/dev/ata/ata-disk.c ============================================================================== --- head/sys/dev/ata/ata-disk.c Fri May 1 03:24:03 2009 (r191716) +++ head/sys/dev/ata/ata-disk.c Fri May 1 08:03:46 2009 (r191717) @@ -346,15 +346,23 @@ ad_dump(void *arg, void *virtual, vm_off off_t offset, size_t length) { struct disk *dp = arg; + device_t dev = dp->d_drv1; struct bio bp; + /* XXX: Drop pre-dump request queue. Long request queue processing + * causes stack overflow in ATA working in dumping (interruptless) mode. + * Conter-XXX: To make dump coherent we should avoid doing anything + * else while dumping. + */ + ata_drop_requests(dev); + /* length zero is special and really means flush buffers to media */ if (!length) { - struct ata_device *atadev = device_get_softc(dp->d_drv1); + struct ata_device *atadev = device_get_softc(dev); int error = 0; if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE) - error = ata_controlcmd(dp->d_drv1, ATA_FLUSHCACHE, 0, 0, 0); + error = ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0); return error; } Modified: head/sys/dev/ata/ata-queue.c ============================================================================== --- head/sys/dev/ata/ata-queue.c Fri May 1 03:24:03 2009 (r191716) +++ head/sys/dev/ata/ata-queue.c Fri May 1 08:03:46 2009 (r191717) @@ -218,20 +218,17 @@ ata_start(device_t dev) ata_finish(request); return; } - if (dumping) { - mtx_unlock(&ch->state_mtx); - mtx_unlock(&ch->queue_mtx); - while (ch->running) { - ata_interrupt(ch); - DELAY(10); - } - return; - } } mtx_unlock(&ch->state_mtx); } } mtx_unlock(&ch->queue_mtx); + if (dumping) { + while (ch->running) { + ata_interrupt(ch); + DELAY(10); + } + } } void @@ -560,6 +557,24 @@ ata_fail_requests(device_t dev) } } +/* + * Rudely drop all requests queued to the channel of specified device. + * XXX: The requests are leaked, use only in fatal case. + */ +void +ata_drop_requests(device_t dev) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + struct ata_request *request, *tmp; + + mtx_lock(&ch->queue_mtx); + TAILQ_FOREACH_SAFE(request, &ch->ata_queue, chain, tmp) { + TAILQ_REMOVE(&ch->ata_queue, request, chain); + request->result = ENXIO; + } + mtx_unlock(&ch->queue_mtx); +} + static u_int64_t ata_get_lba(struct ata_request *request) {