NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/38923: ATAIOCCOMMAND ioctl does not work
The following reply was made to PR kern/38923; it has been noted by GNATS.
From: Michael van Elst <mlelstv%serpens.de@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/38923: ATAIOCCOMMAND ioctl does not work
Date: Tue, 17 Jun 2008 13:59:38 +0200
The ioctl hanging comes from physio waiting for the buffer
to become "un-busy". Obviously this will never become true
when the buffer isn't used yet.
physio() is called with a buffer here:
dev/qbus/qd.c
dev/gpib/mt.c
arch/hp300/dev/mt.c
dev/ata/wd.c
dev/scsipi/scsipi_ioctl.c
dev/qbus/qd.c looks broken..
dev/gpib/mt.c and
arch/hp300/dev/mt.c don't use buf_init() but poke the structure.
They use BC_BUSY to reserve a single command buffer that is used
synchronously by the read/write functions and asynchronously by
the strategy functions.
dev/ata/wd.c and
dev/scsipi/scsipi_ioctl.c malloc buffers and use buf_init().
Reserving a buffer doesn't make sense, as each request uses
its private buffer.
When physio() isn't called with a buffer, as in most device drivers,
then it uses getphysbuf() -> getiobuf() to allocate a private one
from the biopl pool. getiobuf uses buf_init() which now sets BC_BUSY
and getphysbuf() sets BC_BUSY again.
buf_init() is called in getnewbuf() to return a fresh buffer
from the bufpl pool. If allocating a fresh buffer is not wanted
then a buffer is fetched from the free list and marked BC_BUSY.
buf_init() is called in
uvm/uvm_swap.c
dev/ccd.c
dev/ata/ld_ataraid.c
dev/vnd.c
only to get the cflags overwritten with flags from another buffer.
buf_init() is called in
dev/fss.c
to get most data overwritten, maybe the cflags were forgotten.
I'm not sure wether a busy buffer breaks fss.
buf_init() is called in
arch/xen/xen/xbdback.c
arch/xen/xen/xbdback_xenbus.c
after allocating a buffer from a pool, when that buffer is
used, it gets overwritten, in particular cflags is set to 0.
buf_init() is called from
fs/udf/udf_strat_rmw.c
and then b_cflags is set to BC_BUSY /* needed? */
However, that buffer isn't used, but split into nested buffers.
nestiobuf_setup() does set BC_BUSY on the nested buffer.
Apparently buf_init() isn't supposed to declare a buffer busy
and doing so only saves to mark the buffer busy in getnewbuf().
E.g.:
Index: kern/vfs_bio.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_bio.c,v
retrieving revision 1.203
diff -u -r1.203 vfs_bio.c
--- kern/vfs_bio.c 16 Jun 2008 09:47:55 -0000 1.203
+++ kern/vfs_bio.c 17 Jun 2008 11:57:08 -0000
@@ -1301,6 +1301,8 @@
if (bp != NULL) {
memset((char *)bp, 0, sizeof(*bp));
buf_init(bp);
+ /* Buffer is busy now. */
+ SET(bp->b_cflags, BC_BUSY);
mutex_enter(&bufcache_lock);
#if defined(DIAGNOSTIC)
bp->b_freelistindex = -1;
@@ -2017,7 +2019,7 @@
bp->b_dev = NODEV;
bp->b_error = 0;
bp->b_flags = 0;
- bp->b_cflags = BC_BUSY;
+ bp->b_cflags = 0;
bp->b_oflags = 0;
bp->b_objlock = &buffer_lock;
bp->b_iodone = NULL;
--
Michael van Elst
Internet: mlelstv%serpens.de@localhost
"A potential Snark may lurk in every tree."
Home |
Main Index |
Thread Index |
Old Index