2005-04-17 06:20:36 +08:00
|
|
|
#ifndef _LINUX_ELEVATOR_H
|
|
|
|
#define _LINUX_ELEVATOR_H
|
|
|
|
|
2006-07-22 21:37:43 +08:00
|
|
|
#include <linux/percpu.h>
|
|
|
|
|
[PATCH] BLOCK: Make it possible to disable the block layer [try #6]
Make it possible to disable the block layer. Not all embedded devices require
it, some can make do with just JFFS2, NFS, ramfs, etc - none of which require
the block layer to be present.
This patch does the following:
(*) Introduces CONFIG_BLOCK to disable the block layer, buffering and blockdev
support.
(*) Adds dependencies on CONFIG_BLOCK to any configuration item that controls
an item that uses the block layer. This includes:
(*) Block I/O tracing.
(*) Disk partition code.
(*) All filesystems that are block based, eg: Ext3, ReiserFS, ISOFS.
(*) The SCSI layer. As far as I can tell, even SCSI chardevs use the
block layer to do scheduling. Some drivers that use SCSI facilities -
such as USB storage - end up disabled indirectly from this.
(*) Various block-based device drivers, such as IDE and the old CDROM
drivers.
(*) MTD blockdev handling and FTL.
(*) JFFS - which uses set_bdev_super(), something it could avoid doing by
taking a leaf out of JFFS2's book.
(*) Makes most of the contents of linux/blkdev.h, linux/buffer_head.h and
linux/elevator.h contingent on CONFIG_BLOCK being set. sector_div() is,
however, still used in places, and so is still available.
(*) Also made contingent are the contents of linux/mpage.h, linux/genhd.h and
parts of linux/fs.h.
(*) Makes a number of files in fs/ contingent on CONFIG_BLOCK.
(*) Makes mm/bounce.c (bounce buffering) contingent on CONFIG_BLOCK.
(*) set_page_dirty() doesn't call __set_page_dirty_buffers() if CONFIG_BLOCK
is not enabled.
(*) fs/no-block.c is created to hold out-of-line stubs and things that are
required when CONFIG_BLOCK is not set:
(*) Default blockdev file operations (to give error ENODEV on opening).
(*) Makes some /proc changes:
(*) /proc/devices does not list any blockdevs.
(*) /proc/diskstats and /proc/partitions are contingent on CONFIG_BLOCK.
(*) Makes some compat ioctl handling contingent on CONFIG_BLOCK.
(*) If CONFIG_BLOCK is not defined, makes sys_quotactl() return -ENODEV if
given command other than Q_SYNC or if a special device is specified.
(*) In init/do_mounts.c, no reference is made to the blockdev routines if
CONFIG_BLOCK is not defined. This does not prohibit NFS roots or JFFS2.
(*) The bdflush, ioprio_set and ioprio_get syscalls can now be absent (return
error ENOSYS by way of cond_syscall if so).
(*) The seclvl_bd_claim() and seclvl_bd_release() security calls do nothing if
CONFIG_BLOCK is not set, since they can't then happen.
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2006-10-01 02:45:40 +08:00
|
|
|
#ifdef CONFIG_BLOCK
|
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef int (elevator_merge_fn) (struct request_queue *, struct request **,
|
2005-04-17 06:20:36 +08:00
|
|
|
struct bio *);
|
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef void (elevator_merge_req_fn) (struct request_queue *, struct request *, struct request *);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef void (elevator_merged_fn) (struct request_queue *, struct request *, int);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef int (elevator_allow_merge_fn) (struct request_queue *, struct request *, struct bio *);
|
2006-12-20 18:04:12 +08:00
|
|
|
|
2010-04-09 12:14:23 +08:00
|
|
|
typedef void (elevator_bio_merged_fn) (struct request_queue *,
|
|
|
|
struct request *, struct bio *);
|
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef int (elevator_dispatch_fn) (struct request_queue *, int);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef void (elevator_add_req_fn) (struct request_queue *, struct request *);
|
|
|
|
typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *);
|
|
|
|
typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *);
|
|
|
|
typedef int (elevator_may_queue_fn) (struct request_queue *, int);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef int (elevator_set_req_fn) (struct request_queue *, struct request *, gfp_t);
|
2006-12-01 17:42:33 +08:00
|
|
|
typedef void (elevator_put_req_fn) (struct request *);
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef void (elevator_activate_req_fn) (struct request_queue *, struct request *);
|
|
|
|
typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct request *);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
typedef void *(elevator_init_fn) (struct request_queue *);
|
2008-10-31 17:05:07 +08:00
|
|
|
typedef void (elevator_exit_fn) (struct elevator_queue *);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
struct elevator_ops
|
|
|
|
{
|
|
|
|
elevator_merge_fn *elevator_merge_fn;
|
|
|
|
elevator_merged_fn *elevator_merged_fn;
|
|
|
|
elevator_merge_req_fn *elevator_merge_req_fn;
|
2006-12-20 18:04:12 +08:00
|
|
|
elevator_allow_merge_fn *elevator_allow_merge_fn;
|
2011-10-19 20:33:08 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Used for both plugged list and elevator merging and in the
|
|
|
|
* former case called without queue_lock. Read comment on top of
|
|
|
|
* attempt_plug_merge() for details.
|
|
|
|
*/
|
2010-04-09 12:14:23 +08:00
|
|
|
elevator_bio_merged_fn *elevator_bio_merged_fn;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-10-20 22:23:44 +08:00
|
|
|
elevator_dispatch_fn *elevator_dispatch_fn;
|
2005-04-17 06:20:36 +08:00
|
|
|
elevator_add_req_fn *elevator_add_req_fn;
|
2005-10-20 22:23:44 +08:00
|
|
|
elevator_activate_req_fn *elevator_activate_req_fn;
|
2005-04-17 06:20:36 +08:00
|
|
|
elevator_deactivate_req_fn *elevator_deactivate_req_fn;
|
|
|
|
|
|
|
|
elevator_completed_req_fn *elevator_completed_req_fn;
|
|
|
|
|
|
|
|
elevator_request_list_fn *elevator_former_req_fn;
|
|
|
|
elevator_request_list_fn *elevator_latter_req_fn;
|
|
|
|
|
|
|
|
elevator_set_req_fn *elevator_set_req_fn;
|
|
|
|
elevator_put_req_fn *elevator_put_req_fn;
|
|
|
|
|
|
|
|
elevator_may_queue_fn *elevator_may_queue_fn;
|
|
|
|
|
|
|
|
elevator_init_fn *elevator_init_fn;
|
|
|
|
elevator_exit_fn *elevator_exit_fn;
|
2006-03-19 02:21:20 +08:00
|
|
|
void (*trim)(struct io_context *);
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define ELV_NAME_MAX (16)
|
|
|
|
|
2006-03-19 11:27:18 +08:00
|
|
|
struct elv_fs_entry {
|
|
|
|
struct attribute attr;
|
2008-10-31 17:05:07 +08:00
|
|
|
ssize_t (*show)(struct elevator_queue *, char *);
|
|
|
|
ssize_t (*store)(struct elevator_queue *, const char *, size_t);
|
2006-03-19 11:27:18 +08:00
|
|
|
};
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* identifies an elevator type, such as AS or deadline
|
|
|
|
*/
|
|
|
|
struct elevator_type
|
|
|
|
{
|
|
|
|
struct list_head list;
|
|
|
|
struct elevator_ops ops;
|
2006-03-19 11:27:18 +08:00
|
|
|
struct elv_fs_entry *elevator_attrs;
|
2005-04-17 06:20:36 +08:00
|
|
|
char elevator_name[ELV_NAME_MAX];
|
|
|
|
struct module *elevator_owner;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2006-01-10 07:09:36 +08:00
|
|
|
* each queue has an elevator_queue associated with it
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
struct elevator_queue
|
|
|
|
{
|
|
|
|
struct elevator_ops *ops;
|
|
|
|
void *elevator_data;
|
|
|
|
struct kobject kobj;
|
|
|
|
struct elevator_type *elevator_type;
|
2006-03-19 07:35:43 +08:00
|
|
|
struct mutex sysfs_lock;
|
2006-07-28 15:23:08 +08:00
|
|
|
struct hlist_head *hash;
|
2010-10-07 15:35:16 +08:00
|
|
|
unsigned int registered:1;
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* block elevator interface
|
|
|
|
*/
|
2007-07-24 15:28:11 +08:00
|
|
|
extern void elv_dispatch_sort(struct request_queue *, struct request *);
|
|
|
|
extern void elv_dispatch_add_tail(struct request_queue *, struct request *);
|
2011-03-10 15:52:07 +08:00
|
|
|
extern void elv_add_request(struct request_queue *, struct request *, int);
|
|
|
|
extern void __elv_add_request(struct request_queue *, struct request *, int);
|
2007-07-24 15:28:11 +08:00
|
|
|
extern int elv_merge(struct request_queue *, struct request **, struct bio *);
|
2011-03-08 20:19:51 +08:00
|
|
|
extern int elv_try_merge(struct request *, struct bio *);
|
2007-07-24 15:28:11 +08:00
|
|
|
extern void elv_merge_requests(struct request_queue *, struct request *,
|
2005-04-17 06:20:36 +08:00
|
|
|
struct request *);
|
2007-07-24 15:28:11 +08:00
|
|
|
extern void elv_merged_request(struct request_queue *, struct request *, int);
|
2010-04-09 12:14:23 +08:00
|
|
|
extern void elv_bio_merged(struct request_queue *q, struct request *,
|
|
|
|
struct bio *);
|
2007-07-24 15:28:11 +08:00
|
|
|
extern void elv_requeue_request(struct request_queue *, struct request *);
|
|
|
|
extern struct request *elv_former_request(struct request_queue *, struct request *);
|
|
|
|
extern struct request *elv_latter_request(struct request_queue *, struct request *);
|
|
|
|
extern int elv_register_queue(struct request_queue *q);
|
|
|
|
extern void elv_unregister_queue(struct request_queue *q);
|
|
|
|
extern int elv_may_queue(struct request_queue *, int);
|
2008-09-14 02:31:27 +08:00
|
|
|
extern void elv_abort_queue(struct request_queue *);
|
2007-07-24 15:28:11 +08:00
|
|
|
extern void elv_completed_request(struct request_queue *, struct request *);
|
|
|
|
extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
|
|
|
|
extern void elv_put_request(struct request_queue *, struct request *);
|
2009-03-27 17:31:51 +08:00
|
|
|
extern void elv_drain_elevator(struct request_queue *);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* io scheduler registration
|
|
|
|
*/
|
2007-12-13 01:51:56 +08:00
|
|
|
extern void elv_register(struct elevator_type *);
|
2005-04-17 06:20:36 +08:00
|
|
|
extern void elv_unregister(struct elevator_type *);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* io scheduler sysfs switching
|
|
|
|
*/
|
2007-07-24 15:28:11 +08:00
|
|
|
extern ssize_t elv_iosched_show(struct request_queue *, char *);
|
|
|
|
extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2007-07-24 15:28:11 +08:00
|
|
|
extern int elevator_init(struct request_queue *, char *);
|
2008-10-31 17:05:07 +08:00
|
|
|
extern void elevator_exit(struct elevator_queue *);
|
2010-08-23 19:52:19 +08:00
|
|
|
extern int elevator_change(struct request_queue *, const char *);
|
2005-04-17 06:20:36 +08:00
|
|
|
extern int elv_rq_merge_ok(struct request *, struct bio *);
|
|
|
|
|
2006-07-13 17:55:04 +08:00
|
|
|
/*
|
|
|
|
* Helper functions.
|
|
|
|
*/
|
2007-07-24 15:28:11 +08:00
|
|
|
extern struct request *elv_rb_former_request(struct request_queue *, struct request *);
|
|
|
|
extern struct request *elv_rb_latter_request(struct request_queue *, struct request *);
|
2006-07-13 17:55:04 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* rb support functions.
|
|
|
|
*/
|
iosched: prevent aliased requests from starving other I/O
Hi, Jens,
If you recall, I posted an RFC patch for this back in July of last year:
http://lkml.org/lkml/2010/7/13/279
The basic problem is that a process can issue a never-ending stream of
async direct I/Os to the same sector on a device, thus starving out
other I/O in the system (due to the way the alias handling works in both
cfq and deadline). The solution I proposed back then was to start
dispatching from the fifo after a certain number of aliases had been
dispatched. Vivek asked why we had to treat aliases differently at all,
and I never had a good answer. So, I put together a simple patch which
allows aliases to be added to the rb tree (it adds them to the right,
though that doesn't matter as the order isn't guaranteed anyway). I
think this is the preferred solution, as it doesn't break up time slices
in CFQ or batches in deadline. I've tested it, and it does solve the
starvation issue. Let me know what you think.
Cheers,
Jeff
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
2011-06-03 03:19:05 +08:00
|
|
|
extern void elv_rb_add(struct rb_root *, struct request *);
|
2006-07-13 17:55:04 +08:00
|
|
|
extern void elv_rb_del(struct rb_root *, struct request *);
|
|
|
|
extern struct request *elv_rb_find(struct rb_root *, sector_t);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Return values from elevator merger
|
|
|
|
*/
|
|
|
|
#define ELEVATOR_NO_MERGE 0
|
|
|
|
#define ELEVATOR_FRONT_MERGE 1
|
|
|
|
#define ELEVATOR_BACK_MERGE 2
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Insertion selection
|
|
|
|
*/
|
|
|
|
#define ELEVATOR_INSERT_FRONT 1
|
|
|
|
#define ELEVATOR_INSERT_BACK 2
|
|
|
|
#define ELEVATOR_INSERT_SORT 3
|
2006-01-06 16:51:03 +08:00
|
|
|
#define ELEVATOR_INSERT_REQUEUE 4
|
2011-01-25 19:43:54 +08:00
|
|
|
#define ELEVATOR_INSERT_FLUSH 5
|
2011-03-21 17:14:27 +08:00
|
|
|
#define ELEVATOR_INSERT_SORT_MERGE 6
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* return values from elevator_may_queue_fn
|
|
|
|
*/
|
|
|
|
enum {
|
|
|
|
ELV_MQUEUE_MAY,
|
|
|
|
ELV_MQUEUE_NO,
|
|
|
|
ELV_MQUEUE_MUST,
|
|
|
|
};
|
|
|
|
|
2009-05-07 21:24:41 +08:00
|
|
|
#define rq_end_sector(rq) (blk_rq_pos(rq) + blk_rq_sectors(rq))
|
2006-07-13 17:55:04 +08:00
|
|
|
#define rb_entry_rq(node) rb_entry((node), struct request, rb_node)
|
2005-10-20 22:37:00 +08:00
|
|
|
|
2006-07-12 03:49:15 +08:00
|
|
|
/*
|
2008-09-14 02:26:01 +08:00
|
|
|
* Hack to reuse the csd.list list_head as the fifo time holder while
|
2006-07-12 03:49:15 +08:00
|
|
|
* the request is in the io scheduler. Saves an unsigned long in rq.
|
|
|
|
*/
|
2008-09-14 02:26:01 +08:00
|
|
|
#define rq_fifo_time(rq) ((unsigned long) (rq)->csd.list.next)
|
|
|
|
#define rq_set_fifo_time(rq,exp) ((rq)->csd.list.next = (void *) (exp))
|
2006-07-12 03:49:15 +08:00
|
|
|
#define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist)
|
|
|
|
#define rq_fifo_clear(rq) do { \
|
|
|
|
list_del_init(&(rq)->queuelist); \
|
2008-09-14 02:26:01 +08:00
|
|
|
INIT_LIST_HEAD(&(rq)->csd.list); \
|
2006-07-12 03:49:15 +08:00
|
|
|
} while (0)
|
|
|
|
|
2006-07-22 21:37:43 +08:00
|
|
|
/*
|
|
|
|
* io context count accounting
|
|
|
|
*/
|
2010-12-08 23:22:55 +08:00
|
|
|
#define elv_ioc_count_mod(name, __val) this_cpu_add(name, __val)
|
|
|
|
#define elv_ioc_count_inc(name) this_cpu_inc(name)
|
|
|
|
#define elv_ioc_count_dec(name) this_cpu_dec(name)
|
2006-07-22 21:37:43 +08:00
|
|
|
|
|
|
|
#define elv_ioc_count_read(name) \
|
|
|
|
({ \
|
|
|
|
unsigned long __val = 0; \
|
|
|
|
int __cpu; \
|
|
|
|
smp_wmb(); \
|
|
|
|
for_each_possible_cpu(__cpu) \
|
|
|
|
__val += per_cpu(name, __cpu); \
|
|
|
|
__val; \
|
|
|
|
})
|
|
|
|
|
[PATCH] BLOCK: Make it possible to disable the block layer [try #6]
Make it possible to disable the block layer. Not all embedded devices require
it, some can make do with just JFFS2, NFS, ramfs, etc - none of which require
the block layer to be present.
This patch does the following:
(*) Introduces CONFIG_BLOCK to disable the block layer, buffering and blockdev
support.
(*) Adds dependencies on CONFIG_BLOCK to any configuration item that controls
an item that uses the block layer. This includes:
(*) Block I/O tracing.
(*) Disk partition code.
(*) All filesystems that are block based, eg: Ext3, ReiserFS, ISOFS.
(*) The SCSI layer. As far as I can tell, even SCSI chardevs use the
block layer to do scheduling. Some drivers that use SCSI facilities -
such as USB storage - end up disabled indirectly from this.
(*) Various block-based device drivers, such as IDE and the old CDROM
drivers.
(*) MTD blockdev handling and FTL.
(*) JFFS - which uses set_bdev_super(), something it could avoid doing by
taking a leaf out of JFFS2's book.
(*) Makes most of the contents of linux/blkdev.h, linux/buffer_head.h and
linux/elevator.h contingent on CONFIG_BLOCK being set. sector_div() is,
however, still used in places, and so is still available.
(*) Also made contingent are the contents of linux/mpage.h, linux/genhd.h and
parts of linux/fs.h.
(*) Makes a number of files in fs/ contingent on CONFIG_BLOCK.
(*) Makes mm/bounce.c (bounce buffering) contingent on CONFIG_BLOCK.
(*) set_page_dirty() doesn't call __set_page_dirty_buffers() if CONFIG_BLOCK
is not enabled.
(*) fs/no-block.c is created to hold out-of-line stubs and things that are
required when CONFIG_BLOCK is not set:
(*) Default blockdev file operations (to give error ENODEV on opening).
(*) Makes some /proc changes:
(*) /proc/devices does not list any blockdevs.
(*) /proc/diskstats and /proc/partitions are contingent on CONFIG_BLOCK.
(*) Makes some compat ioctl handling contingent on CONFIG_BLOCK.
(*) If CONFIG_BLOCK is not defined, makes sys_quotactl() return -ENODEV if
given command other than Q_SYNC or if a special device is specified.
(*) In init/do_mounts.c, no reference is made to the blockdev routines if
CONFIG_BLOCK is not defined. This does not prohibit NFS roots or JFFS2.
(*) The bdflush, ioprio_set and ioprio_get syscalls can now be absent (return
error ENOSYS by way of cond_syscall if so).
(*) The seclvl_bd_claim() and seclvl_bd_release() security calls do nothing if
CONFIG_BLOCK is not set, since they can't then happen.
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2006-10-01 02:45:40 +08:00
|
|
|
#endif /* CONFIG_BLOCK */
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|