]> git.hungrycats.org Git - linux/commitdiff
[PATCH] read-ahead and failfast
authorJens Axboe <axboe@suse.de>
Fri, 25 Jul 2003 07:39:23 +0000 (00:39 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Fri, 25 Jul 2003 07:39:23 +0000 (00:39 -0700)
Here's the patch to enable failfast flag in the bio submission code, and
use it for multipath and readahead.

drivers/block/ll_rw_blk.c
drivers/ide/ide-cd.c
drivers/ide/ide-disk.c
drivers/ide/ide-io.c
drivers/md/multipath.c
include/linux/bio.h
include/linux/blkdev.h
include/linux/sched.h
mm/readahead.c

index f9678d95a0435cf6830fa93ff83ccb5f85f82ed8..f6ca4f797e73abba0487792d976f4a628af780b3 100644 (file)
@@ -689,7 +689,7 @@ void blk_queue_invalidate_tags(request_queue_t *q)
 
 static char *rq_flags[] = {
        "REQ_RW",
-       "REQ_RW_AHEAD",
+       "REQ_FAILFAST",
        "REQ_SOFTBARRIER",
        "REQ_HARDBARRIER",
        "REQ_CMD",
@@ -706,6 +706,10 @@ static char *rq_flags[] = {
        "REQ_DRIVE_CMD",
        "REQ_DRIVE_TASK",
        "REQ_DRIVE_TASKFILE",
+       "REQ_PREEMPT",
+       "REQ_PM_SUSPEND",
+       "REQ_PM_RESUME",
+       "REQ_PM_SHUTDOWN",
 };
 
 void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -1793,7 +1797,7 @@ void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
        struct request *req, *freereq = NULL;
-       int el_ret, rw, nr_sectors, cur_nr_sectors, barrier;
+       int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra;
        struct list_head *insert_here;
        sector_t sector;
 
@@ -1814,6 +1818,8 @@ static int __make_request(request_queue_t *q, struct bio *bio)
 
        barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
 
+       ra = bio_flagged(bio, BIO_RW_AHEAD) || current->flags & PF_READAHEAD;
+
 again:
        insert_here = NULL;
        spin_lock_irq(q->queue_lock);
@@ -1901,7 +1907,7 @@ get_rq:
                        /*
                         * READA bit set
                         */
-                       if (bio_flagged(bio, BIO_RW_AHEAD))
+                       if (ra)
                                goto end_io;
        
                        freereq = get_request_wait(q, rw);
@@ -1921,6 +1927,12 @@ get_rq:
        if (barrier)
                req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
 
+       /*
+        * don't stack up retries for read ahead
+        */
+       if (ra)
+               req->flags |= REQ_FAILFAST;
+
        req->errors = 0;
        req->hard_sector = req->sector = sector;
        req->hard_nr_sectors = req->nr_sectors = nr_sectors;
index ea211467f65241a97e24685f76c696fad5d4923e..bfa975636ede0f0ab0d72bc827552d46cfec7f14 100644 (file)
@@ -767,6 +767,9 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
        } else if (blk_fs_request(rq)) {
                /* Handle errors from READ and WRITE requests. */
 
+               if (blk_noretry_request(rq))
+                       cdrom_end_request(drive, 0);
+
                if (sense_key == NOT_READY) {
                        /* Tray open. */
                        cdrom_saw_media_change (drive);
index 2a90ce3aed3fe11bcedbec298d0d51f50f16f41a..6bfd1ded67f670125cae331e933617662bcd8d09 100644 (file)
@@ -907,7 +907,7 @@ ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat)
                /* force an abort */
                hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
        }
-       if (rq->errors >= ERROR_MAX)
+       if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
                DRIVER(drive)->end_request(drive, 0, 0);
        else {
                if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
index acac8e3dfeeae01e6a22a9b2b724dae4fa4cd31c..515018c7b2611c508da1cb6781f979d6401f8d67 100644 (file)
@@ -58,8 +58,7 @@
 
 #if (DISK_RECOVERY_TIME > 0)
 
-Error So the User Has To Fix the Compilation And Stop Hacking Port 0x43
-Does anyone ever use this anyway ??
+#error So the User Has To Fix the Compilation And Stop Hacking Port 0x43. Does anyone ever use this anyway ??
 
 /*
  * For really screwy hardware (hey, at least it *can* be used with Linux)
@@ -113,6 +112,13 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
        if (!nr_sectors)
                nr_sectors = rq->hard_cur_sectors;
 
+       /*
+        * if failfast is set on a request, override number of sectors and
+        * complete the whole request right now
+        */
+       if (blk_noretry_request(rq) && !uptodate)
+               nr_sectors = rq->hard_nr_sectors;
+
        /*
         * decide whether to reenable DMA -- 3 is a random magic for now,
         * if we DMA timeout more than 3 times, just stay in PIO
index eeab0139520c67b22b45059f0b67e28f1e5936d8..8d04138441015ba2b8615ea0a7ef7a0290e6f196 100644 (file)
@@ -179,6 +179,7 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
 
        mp_bh->bio = *bio;
        mp_bh->bio.bi_bdev = multipath->rdev->bdev;
+       mp_bh->bio.bi_flags |= (1 << BIO_RW_FAILFAST);
        mp_bh->bio.bi_end_io = multipath_end_request;
        mp_bh->bio.bi_private = mp_bh;
        generic_make_request(&mp_bh->bio);
index d3f47b1b0f6a1e0875ec516f6179ced9cd9e77e1..6ad6d20d37786b85bf6b1637648d164205331382 100644 (file)
@@ -119,10 +119,12 @@ struct bio {
  * bit 0 -- read (not set) or write (set)
  * bit 1 -- rw-ahead when set
  * bit 2 -- barrier
+ * bit 3 -- fail fast, don't want low level driver retries
  */
 #define BIO_RW         0
 #define BIO_RW_AHEAD   1
 #define BIO_RW_BARRIER 2
+#define BIO_RW_FAILFAST        3
 
 /*
  * various member access, note that bio_data should of course not be used
index d951995038e569d7e2d5bb8ef10aa3fb4e402c01..fa14b066b2bb91dcbc7dc899d8524f4bc870f3da 100644 (file)
@@ -165,25 +165,25 @@ struct request {
  * first three bits match BIO_RW* bits, important
  */
 enum rq_flag_bits {
-       __REQ_RW,       /* not set, read. set, write */
-       __REQ_RW_AHEAD, /* READA */
+       __REQ_RW,               /* not set, read. set, write */
+       __REQ_FAILFAST,         /* no low level driver retries */
        __REQ_SOFTBARRIER,      /* may not be passed by ioscheduler */
        __REQ_HARDBARRIER,      /* may not be passed by drive either */
-       __REQ_CMD,      /* is a regular fs rw request */
-       __REQ_NOMERGE,  /* don't touch this for merging */
-       __REQ_STARTED,  /* drive already may have started this one */
-       __REQ_DONTPREP, /* don't call prep for this one */
-       __REQ_QUEUED,   /* uses queueing */
+       __REQ_CMD,              /* is a regular fs rw request */
+       __REQ_NOMERGE,          /* don't touch this for merging */
+       __REQ_STARTED,          /* drive already may have started this one */
+       __REQ_DONTPREP,         /* don't call prep for this one */
+       __REQ_QUEUED,           /* uses queueing */
        /*
         * for ATA/ATAPI devices
         */
-       __REQ_PC,       /* packet command (special) */
-       __REQ_BLOCK_PC, /* queued down pc from block layer */
-       __REQ_SENSE,    /* sense retrival */
+       __REQ_PC,               /* packet command (special) */
+       __REQ_BLOCK_PC,         /* queued down pc from block layer */
+       __REQ_SENSE,            /* sense retrival */
 
-       __REQ_FAILED,   /* set if the request failed */
-       __REQ_QUIET,    /* don't worry about errors */
-       __REQ_SPECIAL,  /* driver suplied command */
+       __REQ_FAILED,           /* set if the request failed */
+       __REQ_QUIET,            /* don't worry about errors */
+       __REQ_SPECIAL,          /* driver suplied command */
        __REQ_DRIVE_CMD,
        __REQ_DRIVE_TASK,
        __REQ_DRIVE_TASKFILE,
@@ -191,11 +191,11 @@ enum rq_flag_bits {
        __REQ_PM_SUSPEND,       /* suspend request */
        __REQ_PM_RESUME,        /* resume request */
        __REQ_PM_SHUTDOWN,      /* shutdown request */
-       __REQ_NR_BITS,  /* stops here */
+       __REQ_NR_BITS,          /* stops here */
 };
 
 #define REQ_RW         (1 << __REQ_RW)
-#define REQ_RW_AHEAD   (1 << __REQ_RW_AHEAD)
+#define REQ_FAILFAST   (1 << __REQ_FAILFAST)
 #define REQ_SOFTBARRIER        (1 << __REQ_SOFTBARRIER)
 #define REQ_HARDBARRIER        (1 << __REQ_HARDBARRIER)
 #define REQ_CMD                (1 << __REQ_CMD)
@@ -364,6 +364,7 @@ struct request_queue
 #define blk_queue_tagged(q)    test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
 #define blk_fs_request(rq)     ((rq)->flags & REQ_CMD)
 #define blk_pc_request(rq)     ((rq)->flags & REQ_BLOCK_PC)
+#define blk_noretry_request(rq)        ((rq)->flags & REQ_FAILFAST)
 
 #define blk_pm_suspend_request(rq)     ((rq)->flags & REQ_PM_SUSPEND)
 #define blk_pm_resume_request(rq)      ((rq)->flags & REQ_PM_RESUME)
index bf740af246c0c9ff5312acef445d9c4f57a9c5fe..b20db4e5fbfa1ff690992e3754f03cca819f079c 100644 (file)
@@ -487,6 +487,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
 #define PF_SWAPOFF     0x00080000      /* I am in swapoff */
 #define PF_LESS_THROTTLE 0x01000000    /* Throttle me less: I clena memory */
 #define PF_SYNCWRITE   0x00200000      /* I am doing a sync write */
+#define PF_READAHEAD   0x00400000      /* I am doing read-ahead */
 
 #ifdef CONFIG_SMP
 extern int set_cpus_allowed(task_t *p, unsigned long new_mask);
index 08d7e877ca97399e0330bce811c4d322be1afb1d..d5db6345b4c161aab74f0121c600ef05b06133e7 100644 (file)
@@ -94,9 +94,14 @@ static int read_pages(struct address_space *mapping, struct file *filp,
 {
        unsigned page_idx;
        struct pagevec lru_pvec;
+       int ret = 0;
+
+       current->flags |= PF_READAHEAD;
 
-       if (mapping->a_ops->readpages)
-               return mapping->a_ops->readpages(filp, mapping, pages, nr_pages);
+       if (mapping->a_ops->readpages) {
+               ret = mapping->a_ops->readpages(filp, mapping, pages, nr_pages);
+               goto out;
+       }
 
        pagevec_init(&lru_pvec, 0);
        for (page_idx = 0; page_idx < nr_pages; page_idx++) {
@@ -112,7 +117,9 @@ static int read_pages(struct address_space *mapping, struct file *filp,
                }
        }
        pagevec_lru_add(&lru_pvec);
-       return 0;
+out:
+       current->flags &= ~PF_READAHEAD;
+       return ret;
 }
 
 /*