plug_device and unplu_device question

Ravi Wijayaratne (ravi@dropzone.tamu.edu)
Mon, 8 Feb 1999 10:20:39 -0600 (CST)


Hi,

This question is about the plug_device and unplug_device routines in
lnux/drivers/block/ll_rw_blk.c

1. I cannot find the place where linux fills up the dev->plug structure
apart from the initilizing routine. But in unplug_device routine
dev->plug.next is used. Also in plug device
dev->current_request =&dev->plug is done.
Where is the contents from dev->plug coming from ?

2. The plug_device is called when there is a request to the device but
dev->current_request is currently empty.(in make request).
However my understanding is that the request is actually attached to the
request queue of the device in add_request routine which is called after
the task is scheduled. What happens is the dev->req_fn() is called before
add_request can schdule the requests ? Or is this possible ?

3. If some one can explain how the plug_device and the unplug_device works
with the ide disk drives that will be the answer I am looking for.

Some help on these questions is very much appreciated.

Thanx
Ravi

***************************************************************************
plug_device and unplug_device fit in as follows

*****************************************************************************
The initialising is done here

blk_dev_init()
{
.....

for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) {
dev->request_fn = NULL;
dev->current_request = NULL;
dev->plug.rq_status = RQ_INACTIVE;
dev->plug.cmd = -1;
dev->plug.next = NULL;
dev->plug_tq.routine = &unplug_device;
dev->plug_tq.data = dev;
}

.......
}

The calling is done in

static void make_request(int major,int rw, struct buffer_head * bh)
{
......

req = blk_dev[major].current_request;

if (!req) {
/* MD and loop can't handle plugging without deadlocking
*/
if (major != MD_MAJOR && major != LOOP_MAJOR)
plug_device(blk_dev + major);
} else switch (major) {

.............
}

and the two routines are as follows

static inline void plug_device(struct blk_dev_struct * dev)
{
dev->current_request = &dev->plug;
queue_task_irq_off(&dev->plug_tq, &tq_disk);
}

void unplug_device(void * data)
{
struct blk_dev_struct * dev = (struct blk_dev_struct *) data;
unsigned long flags;

save_flags(flags);
cli();
if (dev->current_request == &dev->plug) {
struct request * next = dev->plug.next;
dev->current_request = next;
if (next) {
dev->plug.next = NULL;
(dev->request_fn)();
}
}
restore_flags(flags);
}

**********************************************************************

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/