~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/block/elevator.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/drivers/block/elevator.c
  3  *
  4  *  Block device elevator/IO-scheduler.
  5  *
  6  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
  7  *
  8  * 30042000 Jens Axboe <axboe@suse.de> :
  9  *
 10  * Split the elevator a bit so that it is possible to choose a different
 11  * one or even write a new "plug in". There are three pieces:
 12  * - elevator_fn, inserts a new request in the queue list
 13  * - elevator_merge_fn, decides whether a new buffer can be merged with
 14  *   an existing request
 15  * - elevator_dequeue_fn, called when a request is taken off the active list
 16  *
 17  * 20082000 Dave Jones <davej@suse.de> :
 18  * Removed tests for max-bomb-segments, which was breaking elvtune
 19  *  when run without -bN
 20  *
 21  */
 22 
 23 #include <linux/fs.h>
 24 #include <linux/blkdev.h>
 25 #include <linux/elevator.h>
 26 #include <linux/blk.h>
 27 #include <linux/module.h>
 28 #include <asm/uaccess.h>
 29 
 30 int elevator_linus_merge(request_queue_t *q, struct request **req,
 31                          struct list_head * head,
 32                          struct buffer_head *bh, int rw,
 33                          int max_sectors, int max_segments)
 34 {
 35         struct list_head *entry = &q->queue_head;
 36         unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
 37 
 38         while ((entry = entry->prev) != head) {
 39                 struct request *__rq = blkdev_entry_to_request(entry);
 40 
 41                 /*
 42                  * simply "aging" of requests in queue
 43                  */
 44                 if (__rq->elevator_sequence-- <= 0) {
 45                         *req = __rq;
 46                         break;
 47                 }
 48 
 49                 if (__rq->sem)
 50                         continue;
 51                 if (__rq->cmd != rw)
 52                         continue;
 53                 if (__rq->rq_dev != bh->b_rdev)
 54                         continue;
 55                 if (__rq->nr_sectors + count > max_sectors)
 56                         continue;
 57                 if (__rq->elevator_sequence < count)
 58                         break;
 59                 if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
 60                         ret = ELEVATOR_BACK_MERGE;
 61                         *req = __rq;
 62                         break;
 63                 } else if (__rq->sector - count == bh->b_rsector) {
 64                         ret = ELEVATOR_FRONT_MERGE;
 65                         __rq->elevator_sequence -= count;
 66                         *req = __rq;
 67                         break;
 68                 } else if (!*req && BHRQ_IN_ORDER(bh, __rq))
 69                         *req = __rq;
 70         }
 71 
 72         return ret;
 73 }
 74 
 75 void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count)
 76 {
 77         struct list_head *entry = &req->queue, *head = &q->queue_head;
 78 
 79         /*
 80          * second pass scan of requests that got passed over, if any
 81          */
 82         while ((entry = entry->next) != head) {
 83                 struct request *tmp = blkdev_entry_to_request(entry);
 84                 tmp->elevator_sequence -= count;
 85         }
 86 }
 87 
 88 void elevator_linus_merge_req(struct request *req, struct request *next)
 89 {
 90         if (next->elevator_sequence < req->elevator_sequence)
 91                 req->elevator_sequence = next->elevator_sequence;
 92 }
 93 
 94 /*
 95  * See if we can find a request that this buffer can be coalesced with.
 96  */
 97 int elevator_noop_merge(request_queue_t *q, struct request **req,
 98                         struct list_head * head,
 99                         struct buffer_head *bh, int rw,
100                         int max_sectors, int max_segments)
101 {
102         struct list_head *entry;
103         unsigned int count = bh->b_size >> 9;
104 
105         if (list_empty(&q->queue_head))
106                 return ELEVATOR_NO_MERGE;
107 
108         entry = &q->queue_head;
109         while ((entry = entry->prev) != head) {
110                 struct request *__rq = blkdev_entry_to_request(entry);
111 
112                 if (__rq->cmd != rw)
113                         continue;
114                 if (__rq->rq_dev != bh->b_rdev)
115                         continue;
116                 if (__rq->nr_sectors + count > max_sectors)
117                         continue;
118                 if (__rq->sem)
119                         continue;
120                 if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
121                         *req = __rq;
122                         return ELEVATOR_BACK_MERGE;
123                 } else if (__rq->sector - count == bh->b_rsector) {
124                         *req = __rq;
125                         return ELEVATOR_FRONT_MERGE;
126                 }
127         }
128 
129         *req = blkdev_entry_to_request(q->queue_head.prev);
130         return ELEVATOR_NO_MERGE;
131 }
132 
133 void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {}
134 
135 void elevator_noop_merge_req(struct request *req, struct request *next) {}
136 
137 int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg)
138 {
139         blkelv_ioctl_arg_t output;
140 
141         output.queue_ID                 = elevator->queue_ID;
142         output.read_latency             = elevator->read_latency;
143         output.write_latency            = elevator->write_latency;
144         output.max_bomb_segments        = 0;
145 
146         if (copy_to_user(arg, &output, sizeof(blkelv_ioctl_arg_t)))
147                 return -EFAULT;
148 
149         return 0;
150 }
151 
152 int blkelvset_ioctl(elevator_t * elevator, const blkelv_ioctl_arg_t * arg)
153 {
154         blkelv_ioctl_arg_t input;
155 
156         if (copy_from_user(&input, arg, sizeof(blkelv_ioctl_arg_t)))
157                 return -EFAULT;
158 
159         if (input.read_latency < 0)
160                 return -EINVAL;
161         if (input.write_latency < 0)
162                 return -EINVAL;
163 
164         elevator->read_latency          = input.read_latency;
165         elevator->write_latency         = input.write_latency;
166         return 0;
167 }
168 
169 void elevator_init(elevator_t * elevator, elevator_t type)
170 {
171         static unsigned int queue_ID;
172 
173         *elevator = type;
174         elevator->queue_ID = queue_ID++;
175 }
176 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.