OK, I have my latest patchset ready for you guys to try. I think
I have corrected all of the lockup issues that arise when you access the
same device in both character device and block device mode (only generics
is going get you into this kind of situation). This also corrects the
race between scsi_allocate_cmnd() and scsi_release_command().
Other than this problem, things have been pretty quiet. I like it
that way :-). There was one bug mentioned on linux-kernel that I still
need to look into, but I am still waiting for details.
I started to change scsi_allocate_command() to always be
interruptible by signals in the event that we were blocked (i.e. ioctl, or
character device access), but there was a place in sd.c where we were
requesting a command block with the wait flag set where it seemed unwise.
This is where we were re-reading the capacity after a media change, and it
just didn't seem good to allow that to interrupt. Thus what I did was to
add another parameter to scsi_allocate_command. In most of the other
places I fixed it to pass FALSE for this parameter - meaning no change in
behavior. When you are ready to deal with interruptibility by signals,
then just change the last parameter to TRUE. The exception is
scsi_ioctl.c and sg.c, which I made a half-hearted attempt to switch over.
I need to review those changes again before I send them off to Linus & Co.
Anyways, the upshot is that the people who understand the tape and cdrom
code a bit better can make the appropriate changes.
I fixed the problem of the error handler shutting down in
single-user mode. Instead of using SIGKILL, I switched to using SIGHUP.
The init process doesn't send SIGHUP, so it all works correctly now.
Also did some cleanups. Removed some dead code, updated comments,
that kind of stuff.
Patches are enclosed. I also put a file on my ftp site that
contains before and after images of the files I modified. This is in
ftp://ftp.andante.org/tux/eric/scsi/changed.2333.tar.bz2. All of this is
against 2.3.33. I would like to give this patch a couple of days of soak
time before sending it off...
-Eric
"The world was a library, and its books were the stones, leaves,
brooks, grass, and the birds of the earth. We learned to do what only
a student of nature ever learns, and that was to feel beauty."
Chief Luther Standing Bear - Teton Sioux
diff -c -r ../linux/drivers/scsi/scsi.c ./drivers/scsi/scsi.c
*** ../linux/drivers/scsi/scsi.c Tue Dec 14 20:03:52 1999
--- ./drivers/scsi/scsi.c Wed Dec 15 21:36:51 1999
***************
*** 470,476 ****
initialize_merge_fn(SDpnt);
! init_waitqueue_head(&SDpnt->device_wait);
/*
* Next, hook the device to the host in question.
--- 470,479 ----
initialize_merge_fn(SDpnt);
! /*
! * Initialize the object that we will use to wait for command blocks.
! */
! init_waitqueue_head(&SDpnt->scpnt_wait);
/*
* Next, hook the device to the host in question.
***************
*** 901,907 ****
SDpnt->device_queue = SCpnt;
SDpnt->online = TRUE;
! init_waitqueue_head(&SDpnt->device_wait);
/*
* Since we just found one device, there had damn well better be one in the
list
--- 904,913 ----
SDpnt->device_queue = SCpnt;
SDpnt->online = TRUE;
! /*
! * Initialize the object that we will use to wait for command blocks.
! */
! init_waitqueue_head(&SDpnt->scpnt_wait);
/*
* Since we just found one device, there had damn well better be one in the
list
***************
*** 984,1007 ****
#define IN_RESET3 8
- /* This function takes a quick look at a request, and decides if it
- * can be queued now, or if there would be a stall while waiting for
- * something else to finish. This routine assumes that interrupts are
- * turned off when entering the routine. It is the responsibility
- * of the calling code to ensure that this is the case.
- */
-
-
- /* This function returns a structure pointer that will be valid for
- * the device. The wait parameter tells us whether we should wait for
- * the unit to become free or not. We are also able to tell this routine
- * not to return a descriptor if the host is unable to accept any more
- * commands for the time being. We need to keep in mind that there is no
- * guarantee that the host remain not busy. Keep in mind the
- * scsi_request_queueable function also knows the internal allocation scheme
- * of the packets for each device
- */
-
/*
* This lock protects the freelist for all devices on the system.
* We could make this finer grained by having a single lock per
--- 990,995 ----
***************
*** 1029,1043 ****
* Arguments: device - device for which we want a command descriptor
* wait - 1 if we should wait in the event that none
* are available.
*
* Lock status: No locks assumed to be held. This function is SMP-safe.
*
* Returns: Pointer to command descriptor.
*
* Notes: Prior to the new queue code, this function was not SMP-safe.
*/
! Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait)
{
struct Scsi_Host *host;
Scsi_Cmnd *SCpnt = NULL;
--- 1017,1040 ----
* Arguments: device - device for which we want a command descriptor
* wait - 1 if we should wait in the event that none
* are available.
+ * interruptible - 1 if we should unblock and return NULL
+ * in the event that we must wait, and a signal
+ * arrives.
*
* Lock status: No locks assumed to be held. This function is SMP-safe.
*
* Returns: Pointer to command descriptor.
*
* Notes: Prior to the new queue code, this function was not SMP-safe.
+ *
+ * If the wait flag is true, and we are waiting for a free
+ * command block, this function will interrupt and return
+ * NULL in the event that a signal arrives that needs to
+ * be handled.
*/
! Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait,
! int interruptable)
{
struct Scsi_Host *host;
Scsi_Cmnd *SCpnt = NULL;
***************
*** 1121,1135 ****
* If we have been asked to wait for a free block, then
* wait here.
*/
- spin_unlock_irqrestore(&device_request_lock, flags);
if (wait) {
/*
* This should block until a device command block
* becomes available.
*/
! sleep_on(&device->device_wait);
spin_lock_irqsave(&device_request_lock, flags);
} else {
return NULL;
}
}
--- 1118,1170 ----
* If we have been asked to wait for a free block, then
* wait here.
*/
if (wait) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ /*
+ * We need to wait for a free commandblock. We need to
+ * insert ourselves into the list before we release the
+ * lock. This way if a block were released the same
+ * microsecond that we released the lock, the call
+ * to schedule() wouldn't block (well, it might switch,
+ * but the current task will still be schedulable.
+ */
+ add_wait_queue(&device->scpnt_wait, &wait);
+ if( interruptable ) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ } else {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ }
+
+ spin_unlock_irqrestore(&device_request_lock, flags);
+
/*
* This should block until a device command block
* becomes available.
*/
! schedule();
!
spin_lock_irqsave(&device_request_lock, flags);
+
+ remove_wait_queue(&device->scpnt_wait, &wait);
+ /*
+ * FIXME - Isn't this redundant?? Someone
+ * else will have forced the state back to running.
+ */
+ set_current_state(TASK_RUNNING);
+ /*
+ * In the event that a signal has arrived that we need
+ * to consider, then simply return NULL. Everyone
+ * that calls us should be prepared for this
+ * possibility, and pass the appropriate code back
+ * to the user.
+ */
+ if( interruptable ) {
+ if (signal_pending(current))
+ return NULL;
+ }
} else {
+ spin_unlock_irqrestore(&device_request_lock, flags);
return NULL;
}
}
***************
*** 1172,1182 ****
*
* Notes: The command block can no longer be used by the caller once
* this funciton is called. This is in effect the inverse
! * of scsi_allocate_device/scsi_request_queueable.
*/
void scsi_release_command(Scsi_Cmnd * SCpnt)
{
unsigned long flags;
spin_lock_irqsave(&device_request_lock, flags);
SCpnt->request.rq_status = RQ_INACTIVE;
--- 1207,1228 ----
*
* Notes: The command block can no longer be used by the caller once
* this funciton is called. This is in effect the inverse
! * of scsi_allocate_device. Note that we also must perform
! * a couple of additional tasks. We must first wake up any
! * processes that might have blocked waiting for a command
! * block, and secondly we must hit the queue handler function
! * to make sure that the device is busy.
! *
! * The idea is that a lot of the mid-level internals gunk
! * gets hidden in this function. Upper level drivers don't
! * have any chickens to wave in the air to get things to
! * work reliably.
*/
void scsi_release_command(Scsi_Cmnd * SCpnt)
{
unsigned long flags;
+ Scsi_Device * SDpnt;
+
spin_lock_irqsave(&device_request_lock, flags);
SCpnt->request.rq_status = RQ_INACTIVE;
***************
*** 1204,1216 ****
atomic_read(&SCpnt->host->eh_wait->count)));
up(SCpnt->host->eh_wait);
}
spin_unlock_irqrestore(&device_request_lock, flags);
}
/*
! * This is inline because we have stack problemes if we recurse to deeply.
*/
-
int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
{
#ifdef DEBUG_DELAY
--- 1250,1290 ----
atomic_read(&SCpnt->host->eh_wait->count)));
up(SCpnt->host->eh_wait);
}
+
+ SDpnt = SCpnt->device;
+
spin_unlock_irqrestore(&device_request_lock, flags);
+
+ /*
+ * Wake up anyone waiting for this device. Do this after we
+ * have released the lock, as they will need it as soon as
+ * they wake up.
+ */
+ wake_up(&SDpnt->scpnt_wait);
+
+ /*
+ * Finally, hit the queue request function to make sure that
+ * the device is actually busy if there are requests present.
+ * This won't block - if the device cannot take any more, life
+ * will go on.
+ */
+ {
+ request_queue_t *q;
+
+ q = &SDpnt->request_queue;
+ scsi_queue_next_request(q, NULL);
+ }
}
/*
! * Function: scsi_dispatch_command
! *
! * Purpose: Dispatch a command to the low-level driver.
! *
! * Arguments: SCpnt - command block we are dispatching.
! *
! * Notes:
*/
int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
{
#ifdef DEBUG_DELAY
***************
*** 1921,1928 ****
SCpnt->lun = SDpnt->lun;
SCpnt->channel = SDpnt->channel;
SCpnt->request.rq_status = RQ_INACTIVE;
- SCpnt->host_wait = FALSE;
- SCpnt->device_wait = FALSE;
SCpnt->use_sg = 0;
SCpnt->old_use_sg = 0;
SCpnt->old_cmd_len = 0;
--- 1995,2000 ----
***************
*** 2885,2891 ****
DECLARE_MUTEX_LOCKED(sem);
shpnt->eh_notify = &sem;
! send_sig(SIGKILL, shpnt->ehandler, 1);
down(&sem);
shpnt->eh_notify = NULL;
}
--- 2957,2963 ----
DECLARE_MUTEX_LOCKED(sem);
shpnt->eh_notify = &sem;
! send_sig(SIGHUP, shpnt->ehandler, 1);
down(&sem);
shpnt->eh_notify = NULL;
}
diff -c -r ../linux/drivers/scsi/scsi.h ./drivers/scsi/scsi.h
*** ../linux/drivers/scsi/scsi.h Tue Dec 14 20:03:52 1999
--- ./drivers/scsi/scsi.h Wed Dec 15 21:32:31 1999
***************
*** 407,412 ****
--- 407,413 ----
*/
extern void initialize_merge_fn(Scsi_Device * SDpnt);
extern void scsi_request_fn(request_queue_t * q);
+ extern void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt);
extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int);
extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
***************
*** 427,433 ****
void (*done) (struct scsi_cmnd *),
int timeout, int retries);
! extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int);
extern Scsi_Cmnd *scsi_request_queueable(struct request *, Scsi_Device *);
--- 428,434 ----
void (*done) (struct scsi_cmnd *),
int timeout, int retries);
! extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int, int);
extern Scsi_Cmnd *scsi_request_queueable(struct request *, Scsi_Device *);
***************
*** 456,462 ****
*/
struct scsi_device *next; /* Used for linked list */
struct scsi_device *prev; /* Used for linked list */
! wait_queue_head_t device_wait; /* Used to wait if
device is busy */
struct Scsi_Host *host;
request_queue_t request_queue;
--- 457,463 ----
*/
struct scsi_device *next; /* Used for linked list */
struct scsi_device *prev; /* Used for linked list */
! wait_queue_head_t scpnt_wait; /* Used to wait if
device is busy */
struct Scsi_Host *host;
request_queue_t request_queue;
***************
*** 636,651 ****
* timeout handler is already running.
*/
unsigned done_late:1;
-
- /*
- * These two flags are used to track commands that are in the
- * mid-level queue. The idea is that a command can be there for
- * one of two reasons - either the host is busy or the device is
- * busy. Thus when a command on the host finishes, we only try
- * and requeue commands that we might expect to be queueable.
- */
- unsigned host_wait:1;
- unsigned device_wait:1;
/* Low-level done function - can be used by low-level driver to point
* to completion function. Not used by mid/upper level code. */
--- 637,642 ----
diff -c -r ../linux/drivers/scsi/scsi_error.c ./drivers/scsi/scsi_error.c
*** ../linux/drivers/scsi/scsi_error.c Tue Dec 14 20:03:52 1999
--- ./drivers/scsi/scsi_error.c Wed Dec 15 21:32:31 1999
***************
*** 40,47 ****
* the host drivers that we are using may be loaded as modules, and
* when we unload these, we need to ensure that the error handler thread
* can be shut down.
*/
! #define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
#ifdef DEBUG
#define SENSE_TIMEOUT SCSI_TIMEOUT
--- 40,53 ----
* the host drivers that we are using may be loaded as modules, and
* when we unload these, we need to ensure that the error handler thread
* can be shut down.
+ *
+ * Note - when we unload a module, we send a SIGHUP. We mustn't
+ * enable SIGTERM, as this is how the init shuts things down when you
+ * go to single-user mode. For that matter, init also sends SIGKILL,
+ * so we mustn't enable that one either. We use SIGHUP instead. Other
+ * options would be SIGPWR, I suppose.
*/
! #define SHUTDOWN_SIGS (sigmask(SIGHUP))
#ifdef DEBUG
#define SENSE_TIMEOUT SCSI_TIMEOUT
diff -c -r ../linux/drivers/scsi/scsi_ioctl.c ./drivers/scsi/scsi_ioctl.c
*** ../linux/drivers/scsi/scsi_ioctl.c Tue Dec 14 20:02:48 1999
--- ./drivers/scsi/scsi_ioctl.c Wed Dec 15 21:32:31 1999
***************
*** 111,117 ****
SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0]));
! SCpnt = scsi_allocate_device(dev, 1);
{
DECLARE_MUTEX_LOCKED(sem);
SCpnt->request.sem = &sem;
--- 111,122 ----
SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0]));
! SCpnt = scsi_allocate_device(dev, TRUE, TRUE);
! if( SCpnt == NULL )
! {
! return -EINTR;
! }
!
{
DECLARE_MUTEX_LOCKED(sem);
SCpnt->request.sem = &sem;
***************
*** 163,170 ****
scsi_release_command(SCpnt);
SCpnt = NULL;
-
- wake_up(&SDpnt->device_wait);
return result;
}
--- 168,173 ----
***************
*** 297,303 ****
#ifndef DEBUG_NO_CMD
! SCpnt = scsi_allocate_device(dev, 1);
{
DECLARE_MUTEX_LOCKED(sem);
--- 300,310 ----
#ifndef DEBUG_NO_CMD
! SCpnt = scsi_allocate_device(dev, TRUE, TRUE);
! if( SCpnt == NULL )
! {
! return -EINTR;
! }
{
DECLARE_MUTEX_LOCKED(sem);
***************
*** 328,334 ****
result = SCpnt->result;
- wake_up(&SCpnt->device->device_wait);
SDpnt = SCpnt->device;
scsi_release_command(SCpnt);
SCpnt = NULL;
--- 335,340 ----
diff -c -r ../linux/drivers/scsi/scsi_lib.c ./drivers/scsi/scsi_lib.c
*** ../linux/drivers/scsi/scsi_lib.c Tue Dec 14 20:03:52 1999
--- ./drivers/scsi/scsi_lib.c Wed Dec 15 21:32:32 1999
***************
*** 87,94 ****
SCpnt->request.special = (void *) SCpnt;
/*
! * For the moment, we insert at the head of the queue. This may turn
! * out to be a bad idea, but we will see about that when we get there.
*/
spin_lock_irqsave(&io_request_lock, flags);
--- 87,96 ----
SCpnt->request.special = (void *) SCpnt;
/*
! * We have the option of inserting the head or the tail of the queue.
! * Typically we use the tail for new ioctls and so forth. We use the
! * head of the queue for things like a QUEUE_FULL message from a
! * device, or a host that is unable to accept a particular command.
*/
spin_lock_irqsave(&io_request_lock, flags);
***************
*** 97,104 ****
q->current_request = &SCpnt->request;
} else {
/*
! * FIXME(eric) - we always insert at the tail of the list. Otherwise
! * ioctl commands would always take precedence over normal I/O.
*/
SCpnt->request.next = NULL;
if (q->current_request == NULL) {
--- 99,110 ----
q->current_request = &SCpnt->request;
} else {
/*
! * FIXME(eric) - we always insert at the tail of the
! * list. Otherwise ioctl commands would always take
! * precedence over normal I/O. An ioctl on a busy
! * disk might be delayed indefinitely because the
! * request might not float high enough in the queue
! * to be scheduled.
*/
SCpnt->request.next = NULL;
if (q->current_request == NULL) {
***************
*** 116,124 ****
}
/*
! * Now hit the requeue function for the queue. If the host is already
! * busy, so be it - we have nothing special to do. If the host can queue
! * it, then send it off.
*/
q->request_fn(q);
spin_unlock_irqrestore(&io_request_lock, flags);
--- 122,130 ----
}
/*
! * Now hit the requeue function for the queue. If the host is
! * already busy, so be it - we have nothing special to do. If
! * the host can queue it, then send it off.
*/
q->request_fn(q);
spin_unlock_irqrestore(&io_request_lock, flags);
***************
*** 219,231 ****
q->current_request = &SCpnt->request;
SCpnt->request.special = (void *) SCpnt;
}
/*
* Just hit the requeue function for the queue.
- * FIXME - if this queue is empty, check to see if we might need to
- * start requests for other devices attached to the same host.
*/
q->request_fn(q);
/*
* Now see whether there are other devices on the bus which
* might be starved. If so, hit the request function. If we
--- 225,265 ----
q->current_request = &SCpnt->request;
SCpnt->request.special = (void *) SCpnt;
}
+
/*
* Just hit the requeue function for the queue.
*/
q->request_fn(q);
+ SDpnt = (Scsi_Device *) q->queuedata;
+ SHpnt = SDpnt->host;
+
+ /*
+ * If this is a single-lun device, and we are currently finished
+ * with this device, then see if we need to get another device
+ * started. FIXME(eric) - if this function gets too cluttered
+ * with special case code, then spin off separate versions and
+ * use function pointers to pick the right one.
+ */
+ if (SDpnt->single_lun
+ && q->current_request == NULL
+ && SDpnt->device_busy == 0) {
+ request_queue_t *q;
+
+ for (SDpnt = SHpnt->host_queue;
+ SDpnt;
+ SDpnt = SDpnt->next) {
+ if (((SHpnt->can_queue > 0)
+ && (SHpnt->host_busy >= SHpnt->can_queue))
+ || (SHpnt->host_blocked)
+ || (SDpnt->device_blocked)) {
+ break;
+ }
+ q = &SDpnt->request_queue;
+ q->request_fn(q);
+ }
+ }
+
/*
* Now see whether there are other devices on the bus which
* might be starved. If so, hit the request function. If we
***************
*** 234,241 ****
* flag as the queue function releases the lock and thus some
* other device might have become starved along the way.
*/
- SDpnt = (Scsi_Device *) q->queuedata;
- SHpnt = SDpnt->host;
all_clear = 1;
if (SHpnt->some_device_starved) {
for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
--- 268,273 ----
***************
*** 274,279 ****
--- 306,314 ----
*
* Notes: This is called for block device requests in order to
* mark some number of sectors as complete.
+ *
+ * We are guaranteeing that the request queue will be goosed
+ * at some point during this call.
*/
Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
{
***************
*** 311,317 ****
--- 346,361 ----
* to queue the remainder of them.
*/
if (req->bh) {
+ request_queue_t *q;
+
+ q = &SCpnt->device->request_queue;
+
req->buffer = bh->b_data;
+ /*
+ * Bleah. Leftovers again. Stick the leftovers in
+ * the front of the queue, and goose the queue again.
+ */
+ scsi_queue_next_request(q, SCpnt);
return SCpnt;
}
/*
***************
*** 323,328 ****
--- 367,377 ----
up(req->sem);
}
add_blkdev_randomness(MAJOR(req->rq_dev));
+
+ /*
+ * This will goose the queue request function at the end, so we don't
+ * need to worry about launching another command.
+ */
scsi_release_command(SCpnt);
return NULL;
}
***************
*** 351,356 ****
--- 400,418 ----
int this_count = SCpnt->bufflen >> 9;
request_queue_t *q = &SCpnt->device->request_queue;
+ /*
+ * We must do one of several things here:
+ *
+ * Call scsi_end_request. This will finish off the specified
+ * number of sectors. If we are done, the command block will
+ * be released, and the queue function will be goosed. If we
+ * are not done, then scsi_end_request will directly goose
+ * the the queue.
+ *
+ * We can just use scsi_queue_next_request() here. This
+ * would be used if we just wanted to retry, for example.
+ *
+ */
ASSERT_LOCK(&io_request_lock, 0);
/*
***************
*** 417,423 ****
* rest of the command, or start a new one.
*/
if (result == 0) {
- scsi_queue_next_request(q, SCpnt);
return;
}
}
--- 479,484 ----
***************
*** 446,458 ****
*/
SCpnt->device->changed = 1;
SCpnt = scsi_end_request(SCpnt, 0, this_count);
- scsi_queue_next_request(q, SCpnt);
return;
} else {
/*
! * Must have been a power glitch, or a bus reset.
! * Could not have been a media change, so we just
retry
! * the request and see what happens.
*/
scsi_queue_next_request(q, SCpnt);
return;
--- 507,519 ----
*/
SCpnt->device->changed = 1;
SCpnt = scsi_end_request(SCpnt, 0, this_count);
return;
} else {
/*
! * Must have been a power glitch, or a
! * bus reset. Could not have been a
! * media change, so we just retry the
! * request and see what happens.
*/
scsi_queue_next_request(q, SCpnt);
return;
***************
*** 469,479 ****
case ILLEGAL_REQUEST:
if (SCpnt->device->ten) {
SCpnt->device->ten = 0;
scsi_queue_next_request(q, SCpnt);
result = 0;
} else {
SCpnt = scsi_end_request(SCpnt, 0, this_count);
- scsi_queue_next_request(q, SCpnt);
return;
}
break;
--- 530,543 ----
case ILLEGAL_REQUEST:
if (SCpnt->device->ten) {
SCpnt->device->ten = 0;
+ /*
+ * This will cause a retry with a 6-byte
+ * command.
+ */
scsi_queue_next_request(q, SCpnt);
result = 0;
} else {
SCpnt = scsi_end_request(SCpnt, 0, this_count);
return;
}
break;
***************
*** 481,487 ****
printk(KERN_INFO "Device %x not ready.\n",
SCpnt->request.rq_dev);
SCpnt = scsi_end_request(SCpnt, 0, this_count);
- scsi_queue_next_request(q, SCpnt);
return;
break;
case MEDIUM_ERROR:
--- 545,550 ----
***************
*** 492,498 ****
print_command(SCpnt->cmnd);
print_sense("sd", SCpnt);
SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
- scsi_queue_next_request(q, SCpnt);
return;
default:
break;
--- 555,560 ----
***************
*** 508,514 ****
if (driver_byte(result) & DRIVER_SENSE)
print_sense("sd", SCpnt);
SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
- scsi_queue_next_request(q, SCpnt);
return;
}
}
--- 570,575 ----
***************
*** 603,609 ****
*/
while (1 == 1) {
/*
! * If the host cannot accept another request, then quit.
*/
if (SDpnt->device_blocked) {
break;
--- 664,670 ----
*/
while (1 == 1) {
/*
! * If the device cannot accept another request, then quit.
*/
if (SDpnt->device_blocked) {
break;
***************
*** 671,677 ****
*/
recount_segments(SCpnt);
} else {
! SCpnt = scsi_allocate_device(SDpnt, FALSE);
}
/*
* If so, we are ready to do something. Bump the count
--- 732,738 ----
*/
recount_segments(SCpnt);
} else {
! SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);
}
/*
* If so, we are ready to do something. Bump the count
***************
*** 785,813 ****
* the request queue and try to find another command.
*/
spin_lock_irq(&io_request_lock);
- }
-
- /*
- * If this is a single-lun device, and we are currently finished
- * with this device, then see if we need to get another device
- * started.
- */
- if (SDpnt->single_lun
- && q->current_request == NULL
- && SDpnt->device_busy == 0) {
- request_queue_t *q;
-
- for (SDpnt = SHpnt->host_queue;
- SDpnt;
- SDpnt = SDpnt->next) {
- if (((SHpnt->can_queue > 0)
- && (SHpnt->host_busy >= SHpnt->can_queue))
- || (SHpnt->host_blocked)
- || (SDpnt->device_blocked)) {
- break;
- }
- q = &SDpnt->request_queue;
- q->request_fn(q);
- }
}
}
--- 846,850 ----
diff -c -r ../linux/drivers/scsi/scsi_queue.c ./drivers/scsi/scsi_queue.c
*** ../linux/drivers/scsi/scsi_queue.c Tue Dec 14 20:02:49 1999
--- ./drivers/scsi/scsi_queue.c Wed Dec 15 21:32:32 1999
***************
*** 108,114 ****
}
}
host->host_blocked = TRUE;
- cmd->host_wait = TRUE;
} else {
/*
* Protect against race conditions. If the device isn't busy,
--- 108,113 ----
***************
*** 124,130 ****
}
}
cmd->device->device_blocked = TRUE;
- cmd->device_wait = TRUE;
}
/*
--- 123,128 ----
diff -c -r ../linux/drivers/scsi/sd.c ./drivers/scsi/sd.c
*** ../linux/drivers/scsi/sd.c Tue Dec 14 20:02:49 1999
--- ./drivers/scsi/sd.c Wed Dec 15 21:32:32 1999
***************
*** 705,711 ****
* just after a scsi bus reset.
*/
! SCpnt = scsi_allocate_device(rscsi_disks[i].device, 1);
buffer = (unsigned char *) scsi_malloc(512);
--- 705,711 ----
* just after a scsi bus reset.
*/
! SCpnt = scsi_allocate_device(rscsi_disks[i].device, 1, FALSE);
buffer = (unsigned char *) scsi_malloc(512);
***************
*** 950,956 ****
SCpnt->device->remap = 1;
SCpnt->device->sector_size = sector_size;
/* Wake up a process waiting for device */
- wake_up(&SCpnt->device->device_wait);
scsi_release_command(SCpnt);
SCpnt = NULL;
--- 950,955 ----
diff -c -r ../linux/drivers/scsi/sg.c ./drivers/scsi/sg.c
*** ../linux/drivers/scsi/sg.c Tue Dec 14 20:03:52 1999
--- ./drivers/scsi/sg.c Wed Dec 15 21:32:32 1999
***************
*** 65,70 ****
--- 65,71 ----
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
+ static spinlock_t sg_request_lock = SPIN_LOCK_UNLOCKED;
int sg_big_buff = SG_DEF_RESERVED_SIZE; /* sg_big_buff is ro through sysctl */
/* N.B. This global is here to keep existing software happy. It now holds
***************
*** 432,440 ****
}
/* SCSI_LOG_TIMEOUT(7, printk("sg_write: allocating device\n")); */
if (! (SCpnt = scsi_allocate_device(sdp->device,
! !(filp->f_flags & O_NONBLOCK))))
! {
sg_finish_rem_req(srp, NULL, 0);
return -EAGAIN; /* No available command blocks at the moment */
}
/* SCSI_LOG_TIMEOUT(7, printk("sg_write: device allocated\n")); */
--- 433,445 ----
}
/* SCSI_LOG_TIMEOUT(7, printk("sg_write: allocating device\n")); */
if (! (SCpnt = scsi_allocate_device(sdp->device,
! !(filp->f_flags & O_NONBLOCK),
! TRUE))) {
sg_finish_rem_req(srp, NULL, 0);
+ if( signal_pending(current) )
+ {
+ return -EINTR;
+ }
return -EAGAIN; /* No available command blocks at the moment */
}
/* SCSI_LOG_TIMEOUT(7, printk("sg_write: device allocated\n")); */
***************
*** 1043,1049 ****
continue; /* dirty but lowers nesting */
if (sdp->headfp) {
/* Need to stop sg_command_done() playing with this list during this loop */
! spin_lock_irqsave(&io_request_lock, flags);
sfp = sdp->headfp;
while (sfp) {
srp = sfp->headrp;
--- 1048,1054 ----
continue; /* dirty but lowers nesting */
if (sdp->headfp) {
/* Need to stop sg_command_done() playing with this list during this loop */
! spin_lock_irqsave(&sg_request_lock, flags);
sfp = sdp->headfp;
while (sfp) {
srp = sfp->headrp;
***************
*** 1054,1060 ****
}
sfp = sfp->nextfp;
}
! spin_unlock_irqrestore(&io_request_lock, flags);
SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty, sleep(3)\n", k));
scsi_sleep(3); /* sleep 3 jiffies, hoping for timeout to go off */
}
--- 1059,1065 ----
}
sfp = sfp->nextfp;
}
! spin_unlock_irqrestore(&sg_request_lock, flags);
SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty, sleep(3)\n", k));
scsi_sleep(3); /* sleep 3 jiffies, hoping for timeout to go off */
}
***************
*** 1114,1122 ****
scsi_add_timer(scpnt, scpnt->timeout_per_command,
scsi_old_times_out);
#else
! spin_unlock_irq(&io_request_lock);
scsi_sleep(HZ); /* just sleep 1 second and hope ... */
! spin_lock_irq(&io_request_lock);
#endif
}
--- 1119,1127 ----
scsi_add_timer(scpnt, scpnt->timeout_per_command,
scsi_old_times_out);
#else
! spin_unlock_irq(&sg_request_lock);
scsi_sleep(HZ); /* just sleep 1 second and hope ... */
! spin_lock_irq(&sg_request_lock);
#endif
}
diff -c -r ../linux/drivers/scsi/sr.c ./drivers/scsi/sr.c
*** ../linux/drivers/scsi/sr.c Tue Dec 14 20:02:49 1999
--- ./drivers/scsi/sr.c Wed Dec 15 21:36:28 1999
***************
*** 486,492 ****
buffer = (unsigned char *) scsi_malloc(512);
! SCpnt = scsi_allocate_device(scsi_CDs[i].device, 1);
retries = 3;
do {
--- 486,492 ----
buffer = (unsigned char *) scsi_malloc(512);
! SCpnt = scsi_allocate_device(scsi_CDs[i].device, 1, FALSE);
retries = 3;
do {
***************
*** 509,515 ****
} while (the_result && retries);
- wake_up(&SCpnt->device->device_wait);
scsi_release_command(SCpnt);
SCpnt = NULL;
--- 509,514 ----
***************
*** 659,665 ****
int buflen;
/* get the device */
! SCpnt = scsi_allocate_device(device, 1);
if (SCpnt == NULL)
return -ENODEV; /* this just doesn't seem right /axboe */
--- 658,664 ----
int buflen;
/* get the device */
! SCpnt = scsi_allocate_device(device, 1, FALSE);
if (SCpnt == NULL)
return -ENODEV; /* this just doesn't seem right /axboe */
***************
*** 864,870 ****
sr_hardsizes = NULL;
}
blksize_size[MAJOR_NR] = NULL;
! hardsect_size[MAJOR_NR] = sr_hardsizes;
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
blk_size[MAJOR_NR] = NULL;
read_ahead[MAJOR_NR] = 0;
--- 863,869 ----
sr_hardsizes = NULL;
}
blksize_size[MAJOR_NR] = NULL;
! hardsect_size[MAJOR_NR] = NULL;
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
blk_size[MAJOR_NR] = NULL;
read_ahead[MAJOR_NR] = 0;
diff -c -r ../linux/drivers/scsi/sr_ioctl.c ./drivers/scsi/sr_ioctl.c
*** ../linux/drivers/scsi/sr_ioctl.c Tue Dec 14 20:02:49 1999
--- ./drivers/scsi/sr_ioctl.c Wed Dec 15 21:32:32 1999
***************
*** 59,65 ****
char *bounce_buffer;
SDev = scsi_CDs[target].device;
! SCpnt = scsi_allocate_device(scsi_CDs[target].device, 1);
/* use ISA DMA buffer if necessary */
SCpnt->request.buffer = buffer;
--- 59,65 ----
char *bounce_buffer;
SDev = scsi_CDs[target].device;
! SCpnt = scsi_allocate_device(scsi_CDs[target].device, 1, FALSE);
/* use ISA DMA buffer if necessary */
SCpnt->request.buffer = buffer;
***************
*** 142,148 ****
}
result = SCpnt->result;
/* Wake up a process waiting for device */
- wake_up(&SCpnt->device->device_wait);
scsi_release_command(SCpnt);
SCpnt = NULL;
return err;
--- 142,147 ----
diff -c -r ../linux/drivers/scsi/st.c ./drivers/scsi/st.c
*** ../linux/drivers/scsi/st.c Tue Dec 14 20:02:50 1999
--- ./drivers/scsi/st.c Wed Dec 15 21:32:32 1999
***************
*** 289,295 ****
unsigned char *bp;
if (SCpnt == NULL)
! SCpnt = scsi_allocate_device(STp->device, 1);
if (SCpnt == NULL) {
printk(KERN_ERR "st%d: Can't get SCSI request.\n",
TAPE_NR(STp->devt));
--- 289,295 ----
unsigned char *bp;
if (SCpnt == NULL)
! SCpnt = scsi_allocate_device(STp->device, 1, FALSE);
if (SCpnt == NULL) {
printk(KERN_ERR "st%d: Can't get SCSI request.\n",
TAPE_NR(STp->devt));