elevator.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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. #include <linux/fs.h>
  23. #include <linux/blkdev.h>
  24. #include <linux/elevator.h>
  25. #include <linux/blk.h>
  26. #include <linux/module.h>
  27. #include <asm/uaccess.h>
  28. /*
  29.  * This is a bit tricky. It's given that bh and rq are for the same
  30.  * device, but the next request might of course not be. Run through
  31.  * the tests below to check if we want to insert here if we can't merge
  32.  * bh into an existing request
  33.  */
  34. inline int bh_rq_in_between(struct buffer_head *bh, struct request *rq,
  35.     struct list_head *head)
  36. {
  37. struct list_head *next;
  38. struct request *next_rq;
  39. next = rq->queue.next;
  40. if (next == head)
  41. return 0;
  42. /*
  43.  * if the device is different (usually on a different partition),
  44.  * just check if bh is after rq
  45.  */
  46. next_rq = blkdev_entry_to_request(next);
  47. if (next_rq->rq_dev != rq->rq_dev)
  48. return bh->b_rsector > rq->sector;
  49. /*
  50.  * ok, rq, next_rq and bh are on the same device. if bh is in between
  51.  * the two, this is the sweet spot
  52.  */
  53. if (bh->b_rsector < next_rq->sector && bh->b_rsector > rq->sector)
  54. return 1;
  55. /*
  56.  * next_rq is ordered wrt rq, but bh is not in between the two
  57.  */
  58. if (next_rq->sector > rq->sector)
  59. return 0;
  60. /*
  61.  * next_rq and rq not ordered, if we happen to be either before
  62.  * next_rq or after rq insert here anyway
  63.  */
  64. if (bh->b_rsector > rq->sector || bh->b_rsector < next_rq->sector)
  65. return 1;
  66. return 0;
  67. }
  68. int elevator_linus_merge(request_queue_t *q, struct request **req,
  69.  struct list_head * head,
  70.  struct buffer_head *bh, int rw,
  71.  int max_sectors)
  72. {
  73. struct list_head *entry = &q->queue_head;
  74. unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
  75. struct request *__rq;
  76. while ((entry = entry->prev) != head) {
  77. __rq = blkdev_entry_to_request(entry);
  78. /*
  79.  * we can't insert beyond a zero sequence point
  80.  */
  81. if (__rq->elevator_sequence <= 0)
  82. break;
  83. if (__rq->waiting)
  84. continue;
  85. if (__rq->rq_dev != bh->b_rdev)
  86. continue;
  87. if (!*req && bh_rq_in_between(bh, __rq, &q->queue_head))
  88. *req = __rq;
  89. if (__rq->cmd != rw)
  90. continue;
  91. if (__rq->nr_sectors + count > max_sectors)
  92. continue;
  93. if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
  94. ret = ELEVATOR_BACK_MERGE;
  95. *req = __rq;
  96. break;
  97. } else if (__rq->sector - count == bh->b_rsector) {
  98. ret = ELEVATOR_FRONT_MERGE;
  99. __rq->elevator_sequence--;
  100. *req = __rq;
  101. break;
  102. }
  103. }
  104. /*
  105.  * account merge (ret != 0, cost is 1) or seeky insert (*req is set,
  106.  * cost is ELV_LINUS_SEEK_COST
  107.  */
  108. if (*req) {
  109. int scan_cost = ret ? 1 : ELV_LINUS_SEEK_COST;
  110. struct list_head *entry = &(*req)->queue;
  111. while ((entry = entry->next) != &q->queue_head) {
  112. __rq = blkdev_entry_to_request(entry);
  113. __rq->elevator_sequence -= scan_cost;
  114. }
  115. }
  116. return ret;
  117. }
  118. void elevator_linus_merge_req(struct request *req, struct request *next)
  119. {
  120. if (next->elevator_sequence < req->elevator_sequence)
  121. req->elevator_sequence = next->elevator_sequence;
  122. }
  123. /*
  124.  * See if we can find a request that this buffer can be coalesced with.
  125.  */
  126. int elevator_noop_merge(request_queue_t *q, struct request **req,
  127. struct list_head * head,
  128. struct buffer_head *bh, int rw,
  129. int max_sectors)
  130. {
  131. struct list_head *entry;
  132. unsigned int count = bh->b_size >> 9;
  133. if (list_empty(&q->queue_head))
  134. return ELEVATOR_NO_MERGE;
  135. entry = &q->queue_head;
  136. while ((entry = entry->prev) != head) {
  137. struct request *__rq = blkdev_entry_to_request(entry);
  138. if (__rq->cmd != rw)
  139. continue;
  140. if (__rq->rq_dev != bh->b_rdev)
  141. continue;
  142. if (__rq->nr_sectors + count > max_sectors)
  143. continue;
  144. if (__rq->waiting)
  145. continue;
  146. if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
  147. *req = __rq;
  148. return ELEVATOR_BACK_MERGE;
  149. } else if (__rq->sector - count == bh->b_rsector) {
  150. *req = __rq;
  151. return ELEVATOR_FRONT_MERGE;
  152. }
  153. }
  154. *req = blkdev_entry_to_request(q->queue_head.prev);
  155. return ELEVATOR_NO_MERGE;
  156. }
  157. void elevator_noop_merge_req(struct request *req, struct request *next) {}
  158. int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg)
  159. {
  160. blkelv_ioctl_arg_t output;
  161. output.queue_ID = elevator->queue_ID;
  162. output.read_latency = elevator->read_latency;
  163. output.write_latency = elevator->write_latency;
  164. output.max_bomb_segments = 0;
  165. if (copy_to_user(arg, &output, sizeof(blkelv_ioctl_arg_t)))
  166. return -EFAULT;
  167. return 0;
  168. }
  169. int blkelvset_ioctl(elevator_t * elevator, const blkelv_ioctl_arg_t * arg)
  170. {
  171. blkelv_ioctl_arg_t input;
  172. if (copy_from_user(&input, arg, sizeof(blkelv_ioctl_arg_t)))
  173. return -EFAULT;
  174. if (input.read_latency < 0)
  175. return -EINVAL;
  176. if (input.write_latency < 0)
  177. return -EINVAL;
  178. elevator->read_latency = input.read_latency;
  179. elevator->write_latency = input.write_latency;
  180. return 0;
  181. }
  182. void elevator_init(elevator_t * elevator, elevator_t type)
  183. {
  184. static unsigned int queue_ID;
  185. *elevator = type;
  186. elevator->queue_ID = queue_ID++;
  187. }