diff options
147 files changed, 2841 insertions, 2884 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 28e1c7b9244a..f0cd5a3f6de6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -501,7 +501,7 @@ S: Maintained | |||
| 501 | 501 | ||
| 502 | BLOCK LAYER | 502 | BLOCK LAYER |
| 503 | P: Jens Axboe | 503 | P: Jens Axboe |
| 504 | M: axboe@suse.de | 504 | M: axboe@kernel.dk |
| 505 | L: linux-kernel@vger.kernel.org | 505 | L: linux-kernel@vger.kernel.org |
| 506 | T: git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git | 506 | T: git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git |
| 507 | S: Maintained | 507 | S: Maintained |
| @@ -1380,7 +1380,7 @@ S: Maintained | |||
| 1380 | 1380 | ||
| 1381 | IDE/ATAPI CDROM DRIVER | 1381 | IDE/ATAPI CDROM DRIVER |
| 1382 | P: Jens Axboe | 1382 | P: Jens Axboe |
| 1383 | M: axboe@suse.de | 1383 | M: axboe@kernel.dk |
| 1384 | L: linux-kernel@vger.kernel.org | 1384 | L: linux-kernel@vger.kernel.org |
| 1385 | W: http://www.kernel.dk | 1385 | W: http://www.kernel.dk |
| 1386 | S: Maintained | 1386 | S: Maintained |
| @@ -2531,7 +2531,7 @@ S: Maintained | |||
| 2531 | 2531 | ||
| 2532 | SCSI CDROM DRIVER | 2532 | SCSI CDROM DRIVER |
| 2533 | P: Jens Axboe | 2533 | P: Jens Axboe |
| 2534 | M: axboe@suse.de | 2534 | M: axboe@kernel.dk |
| 2535 | L: linux-scsi@vger.kernel.org | 2535 | L: linux-scsi@vger.kernel.org |
| 2536 | W: http://www.kernel.dk | 2536 | W: http://www.kernel.dk |
| 2537 | S: Maintained | 2537 | S: Maintained |
| @@ -2976,7 +2976,7 @@ S: Maintained | |||
| 2976 | 2976 | ||
| 2977 | UNIFORM CDROM DRIVER | 2977 | UNIFORM CDROM DRIVER |
| 2978 | P: Jens Axboe | 2978 | P: Jens Axboe |
| 2979 | M: axboe@suse.de | 2979 | M: axboe@kernel.dk |
| 2980 | L: linux-kernel@vger.kernel.org | 2980 | L: linux-kernel@vger.kernel.org |
| 2981 | W: http://www.kernel.dk | 2981 | W: http://www.kernel.dk |
| 2982 | S: Maintained | 2982 | S: Maintained |
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 477c5334ec1b..50c17eaa7f25 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
| @@ -42,6 +42,8 @@ | |||
| 42 | 42 | ||
| 43 | #include "signal-common.h" | 43 | #include "signal-common.h" |
| 44 | 44 | ||
| 45 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | ||
| 46 | |||
| 45 | /* | 47 | /* |
| 46 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... | 48 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... |
| 47 | */ | 49 | */ |
| @@ -81,8 +83,6 @@ struct rt_sigframe_n32 { | |||
| 81 | #endif | 83 | #endif |
| 82 | }; | 84 | }; |
| 83 | 85 | ||
| 84 | extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat); | ||
| 85 | |||
| 86 | save_static_function(sysn32_rt_sigsuspend); | 86 | save_static_function(sysn32_rt_sigsuspend); |
| 87 | __attribute_used__ noinline static int | 87 | __attribute_used__ noinline static int |
| 88 | _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | 88 | _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) |
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 5fa4c8e258a4..fda4a3940698 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
| @@ -981,8 +981,6 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
| 981 | __u64 offset; | 981 | __u64 offset; |
| 982 | int len; | 982 | int len; |
| 983 | 983 | ||
| 984 | if(req->rq_status == RQ_INACTIVE) return(1); | ||
| 985 | |||
| 986 | /* This should be impossible now */ | 984 | /* This should be impossible now */ |
| 987 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ | 985 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ |
| 988 | printk("Write attempted on readonly ubd device %s\n", | 986 | printk("Write attempted on readonly ubd device %s\n", |
diff --git a/block/Kconfig b/block/Kconfig index b6f5f0a79655..9af6c614dfde 100644 --- a/block/Kconfig +++ b/block/Kconfig | |||
| @@ -1,6 +1,24 @@ | |||
| 1 | # | 1 | # |
| 2 | # Block layer core configuration | 2 | # Block layer core configuration |
| 3 | # | 3 | # |
| 4 | config BLOCK | ||
| 5 | bool "Enable the block layer" | ||
| 6 | default y | ||
| 7 | help | ||
| 8 | This permits the block layer to be removed from the kernel if it's not | ||
| 9 | needed (on some embedded devices for example). If this option is | ||
| 10 | disabled, then blockdev files will become unusable and some | ||
| 11 | filesystems (such as ext3) will become unavailable. | ||
| 12 | |||
| 13 | This option will also disable SCSI character devices and USB storage | ||
| 14 | since they make use of various block layer definitions and | ||
| 15 | facilities. | ||
| 16 | |||
| 17 | Say Y here unless you know you really don't want to mount disks and | ||
| 18 | suchlike. | ||
| 19 | |||
| 20 | if BLOCK | ||
| 21 | |||
| 4 | #XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64 | 22 | #XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64 |
| 5 | #for instance. | 23 | #for instance. |
| 6 | config LBD | 24 | config LBD |
| @@ -33,4 +51,6 @@ config LSF | |||
| 33 | 51 | ||
| 34 | If unsure, say Y. | 52 | If unsure, say Y. |
| 35 | 53 | ||
| 54 | endif | ||
| 55 | |||
| 36 | source block/Kconfig.iosched | 56 | source block/Kconfig.iosched |
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index 48d090e266fc..903f0d3b6852 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | if BLOCK | ||
| 1 | 2 | ||
| 2 | menu "IO Schedulers" | 3 | menu "IO Schedulers" |
| 3 | 4 | ||
| @@ -67,3 +68,5 @@ config DEFAULT_IOSCHED | |||
| 67 | default "noop" if DEFAULT_NOOP | 68 | default "noop" if DEFAULT_NOOP |
| 68 | 69 | ||
| 69 | endmenu | 70 | endmenu |
| 71 | |||
| 72 | endif | ||
diff --git a/block/Makefile b/block/Makefile index c05de0e0037f..4b84d0d5947b 100644 --- a/block/Makefile +++ b/block/Makefile | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # Makefile for the kernel block layer | 2 | # Makefile for the kernel block layer |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o | 5 | obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o | 7 | obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o |
| 8 | obj-$(CONFIG_IOSCHED_AS) += as-iosched.o | 8 | obj-$(CONFIG_IOSCHED_AS) += as-iosched.o |
diff --git a/block/as-iosched.c b/block/as-iosched.c index 5da56d48fbd3..165509e8659e 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Anticipatory & deadline i/o scheduler. | 2 | * Anticipatory & deadline i/o scheduler. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 Jens Axboe <axboe@suse.de> | 4 | * Copyright (C) 2002 Jens Axboe <axboe@kernel.dk> |
| 5 | * Nick Piggin <nickpiggin@yahoo.com.au> | 5 | * Nick Piggin <nickpiggin@yahoo.com.au> |
| 6 | * | 6 | * |
| 7 | */ | 7 | */ |
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/compiler.h> | 16 | #include <linux/compiler.h> |
| 17 | #include <linux/hash.h> | ||
| 18 | #include <linux/rbtree.h> | 17 | #include <linux/rbtree.h> |
| 19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 20 | 19 | ||
| @@ -93,9 +92,8 @@ struct as_data { | |||
| 93 | struct rb_root sort_list[2]; | 92 | struct rb_root sort_list[2]; |
| 94 | struct list_head fifo_list[2]; | 93 | struct list_head fifo_list[2]; |
| 95 | 94 | ||
| 96 | struct as_rq *next_arq[2]; /* next in sort order */ | 95 | struct request *next_rq[2]; /* next in sort order */ |
| 97 | sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ | 96 | sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ |
| 98 | struct hlist_head *hash; /* request hash */ | ||
| 99 | 97 | ||
| 100 | unsigned long exit_prob; /* probability a task will exit while | 98 | unsigned long exit_prob; /* probability a task will exit while |
| 101 | being waited on */ | 99 | being waited on */ |
| @@ -115,7 +113,6 @@ struct as_data { | |||
| 115 | int write_batch_count; /* max # of reqs in a write batch */ | 113 | int write_batch_count; /* max # of reqs in a write batch */ |
| 116 | int current_write_count; /* how many requests left this batch */ | 114 | int current_write_count; /* how many requests left this batch */ |
| 117 | int write_batch_idled; /* has the write batch gone idle? */ | 115 | int write_batch_idled; /* has the write batch gone idle? */ |
| 118 | mempool_t *arq_pool; | ||
| 119 | 116 | ||
| 120 | enum anticipation_status antic_status; | 117 | enum anticipation_status antic_status; |
| 121 | unsigned long antic_start; /* jiffies: when it started */ | 118 | unsigned long antic_start; /* jiffies: when it started */ |
| @@ -133,8 +130,6 @@ struct as_data { | |||
| 133 | unsigned long antic_expire; | 130 | unsigned long antic_expire; |
| 134 | }; | 131 | }; |
| 135 | 132 | ||
| 136 | #define list_entry_fifo(ptr) list_entry((ptr), struct as_rq, fifo) | ||
| 137 | |||
| 138 | /* | 133 | /* |
| 139 | * per-request data. | 134 | * per-request data. |
| 140 | */ | 135 | */ |
| @@ -150,40 +145,14 @@ enum arq_state { | |||
| 150 | AS_RQ_POSTSCHED, /* when they shouldn't be */ | 145 | AS_RQ_POSTSCHED, /* when they shouldn't be */ |
| 151 | }; | 146 | }; |
| 152 | 147 | ||
| 153 | struct as_rq { | 148 | #define RQ_IOC(rq) ((struct io_context *) (rq)->elevator_private) |
| 154 | /* | 149 | #define RQ_STATE(rq) ((enum arq_state)(rq)->elevator_private2) |
| 155 | * rbtree index, key is the starting offset | 150 | #define RQ_SET_STATE(rq, state) ((rq)->elevator_private2 = (void *) state) |
| 156 | */ | ||
| 157 | struct rb_node rb_node; | ||
| 158 | sector_t rb_key; | ||
| 159 | |||
| 160 | struct request *request; | ||
| 161 | |||
| 162 | struct io_context *io_context; /* The submitting task */ | ||
| 163 | |||
| 164 | /* | ||
| 165 | * request hash, key is the ending offset (for back merge lookup) | ||
| 166 | */ | ||
| 167 | struct hlist_node hash; | ||
| 168 | |||
| 169 | /* | ||
| 170 | * expire fifo | ||
| 171 | */ | ||
| 172 | struct list_head fifo; | ||
| 173 | unsigned long expires; | ||
| 174 | 151 | ||
| 175 | unsigned int is_sync; | 152 | static DEFINE_PER_CPU(unsigned long, ioc_count); |
| 176 | enum arq_state state; | ||
| 177 | }; | ||
| 178 | |||
| 179 | #define RQ_DATA(rq) ((struct as_rq *) (rq)->elevator_private) | ||
| 180 | |||
| 181 | static kmem_cache_t *arq_pool; | ||
| 182 | |||
| 183 | static atomic_t ioc_count = ATOMIC_INIT(0); | ||
| 184 | static struct completion *ioc_gone; | 153 | static struct completion *ioc_gone; |
| 185 | 154 | ||
| 186 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); | 155 | static void as_move_to_dispatch(struct as_data *ad, struct request *rq); |
| 187 | static void as_antic_stop(struct as_data *ad); | 156 | static void as_antic_stop(struct as_data *ad); |
| 188 | 157 | ||
| 189 | /* | 158 | /* |
| @@ -194,7 +163,8 @@ static void as_antic_stop(struct as_data *ad); | |||
| 194 | static void free_as_io_context(struct as_io_context *aic) | 163 | static void free_as_io_context(struct as_io_context *aic) |
| 195 | { | 164 | { |
| 196 | kfree(aic); | 165 | kfree(aic); |
| 197 | if (atomic_dec_and_test(&ioc_count) && ioc_gone) | 166 | elv_ioc_count_dec(ioc_count); |
| 167 | if (ioc_gone && !elv_ioc_count_read(ioc_count)) | ||
| 198 | complete(ioc_gone); | 168 | complete(ioc_gone); |
| 199 | } | 169 | } |
| 200 | 170 | ||
| @@ -230,7 +200,7 @@ static struct as_io_context *alloc_as_io_context(void) | |||
| 230 | ret->seek_total = 0; | 200 | ret->seek_total = 0; |
| 231 | ret->seek_samples = 0; | 201 | ret->seek_samples = 0; |
| 232 | ret->seek_mean = 0; | 202 | ret->seek_mean = 0; |
| 233 | atomic_inc(&ioc_count); | 203 | elv_ioc_count_inc(ioc_count); |
| 234 | } | 204 | } |
| 235 | 205 | ||
| 236 | return ret; | 206 | return ret; |
| @@ -240,9 +210,9 @@ static struct as_io_context *alloc_as_io_context(void) | |||
| 240 | * If the current task has no AS IO context then create one and initialise it. | 210 | * If the current task has no AS IO context then create one and initialise it. |
| 241 | * Then take a ref on the task's io context and return it. | 211 | * Then take a ref on the task's io context and return it. |
| 242 | */ | 212 | */ |
| 243 | static struct io_context *as_get_io_context(void) | 213 | static struct io_context *as_get_io_context(int node) |
| 244 | { | 214 | { |
| 245 | struct io_context *ioc = get_io_context(GFP_ATOMIC); | 215 | struct io_context *ioc = get_io_context(GFP_ATOMIC, node); |
| 246 | if (ioc && !ioc->aic) { | 216 | if (ioc && !ioc->aic) { |
| 247 | ioc->aic = alloc_as_io_context(); | 217 | ioc->aic = alloc_as_io_context(); |
| 248 | if (!ioc->aic) { | 218 | if (!ioc->aic) { |
| @@ -253,194 +223,43 @@ static struct io_context *as_get_io_context(void) | |||
| 253 | return ioc; | 223 | return ioc; |
| 254 | } | 224 | } |
| 255 | 225 | ||
| 256 | static void as_put_io_context(struct as_rq *arq) | 226 | static void as_put_io_context(struct request *rq) |
| 257 | { | 227 | { |
| 258 | struct as_io_context *aic; | 228 | struct as_io_context *aic; |
| 259 | 229 | ||
| 260 | if (unlikely(!arq->io_context)) | 230 | if (unlikely(!RQ_IOC(rq))) |
| 261 | return; | 231 | return; |
| 262 | 232 | ||
| 263 | aic = arq->io_context->aic; | 233 | aic = RQ_IOC(rq)->aic; |
| 264 | 234 | ||
| 265 | if (arq->is_sync == REQ_SYNC && aic) { | 235 | if (rq_is_sync(rq) && aic) { |
| 266 | spin_lock(&aic->lock); | 236 | spin_lock(&aic->lock); |
| 267 | set_bit(AS_TASK_IORUNNING, &aic->state); | 237 | set_bit(AS_TASK_IORUNNING, &aic->state); |
| 268 | aic->last_end_request = jiffies; | 238 | aic->last_end_request = jiffies; |
| 269 | spin_unlock(&aic->lock); | 239 | spin_unlock(&aic->lock); |
| 270 | } | 240 | } |
| 271 | 241 | ||
| 272 | put_io_context(arq->io_context); | 242 | put_io_context(RQ_IOC(rq)); |
| 273 | } | ||
| 274 | |||
| 275 | /* | ||
| 276 | * the back merge hash support functions | ||
| 277 | */ | ||
| 278 | static const int as_hash_shift = 6; | ||
| 279 | #define AS_HASH_BLOCK(sec) ((sec) >> 3) | ||
| 280 | #define AS_HASH_FN(sec) (hash_long(AS_HASH_BLOCK((sec)), as_hash_shift)) | ||
| 281 | #define AS_HASH_ENTRIES (1 << as_hash_shift) | ||
| 282 | #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) | ||
| 283 | |||
| 284 | static inline void __as_del_arq_hash(struct as_rq *arq) | ||
| 285 | { | ||
| 286 | hlist_del_init(&arq->hash); | ||
| 287 | } | ||
| 288 | |||
| 289 | static inline void as_del_arq_hash(struct as_rq *arq) | ||
| 290 | { | ||
| 291 | if (!hlist_unhashed(&arq->hash)) | ||
| 292 | __as_del_arq_hash(arq); | ||
| 293 | } | ||
| 294 | |||
| 295 | static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq) | ||
| 296 | { | ||
| 297 | struct request *rq = arq->request; | ||
| 298 | |||
| 299 | BUG_ON(!hlist_unhashed(&arq->hash)); | ||
| 300 | |||
| 301 | hlist_add_head(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]); | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * move hot entry to front of chain | ||
| 306 | */ | ||
| 307 | static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq) | ||
| 308 | { | ||
| 309 | struct request *rq = arq->request; | ||
| 310 | struct hlist_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))]; | ||
| 311 | |||
| 312 | if (hlist_unhashed(&arq->hash)) { | ||
| 313 | WARN_ON(1); | ||
| 314 | return; | ||
| 315 | } | ||
| 316 | |||
| 317 | if (&arq->hash != head->first) { | ||
| 318 | hlist_del(&arq->hash); | ||
| 319 | hlist_add_head(&arq->hash, head); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset) | ||
| 324 | { | ||
| 325 | struct hlist_head *hash_list = &ad->hash[AS_HASH_FN(offset)]; | ||
| 326 | struct hlist_node *entry, *next; | ||
| 327 | struct as_rq *arq; | ||
| 328 | |||
| 329 | hlist_for_each_entry_safe(arq, entry, next, hash_list, hash) { | ||
| 330 | struct request *__rq = arq->request; | ||
| 331 | |||
| 332 | BUG_ON(hlist_unhashed(&arq->hash)); | ||
| 333 | |||
| 334 | if (!rq_mergeable(__rq)) { | ||
| 335 | as_del_arq_hash(arq); | ||
| 336 | continue; | ||
| 337 | } | ||
| 338 | |||
| 339 | if (rq_hash_key(__rq) == offset) | ||
| 340 | return __rq; | ||
| 341 | } | ||
| 342 | |||
| 343 | return NULL; | ||
| 344 | } | 243 | } |
| 345 | 244 | ||
| 346 | /* | 245 | /* |
| 347 | * rb tree support functions | 246 | * rb tree support functions |
| 348 | */ | 247 | */ |
| 349 | #define rb_entry_arq(node) rb_entry((node), struct as_rq, rb_node) | 248 | #define RQ_RB_ROOT(ad, rq) (&(ad)->sort_list[rq_is_sync((rq))]) |
| 350 | #define ARQ_RB_ROOT(ad, arq) (&(ad)->sort_list[(arq)->is_sync]) | ||
| 351 | #define rq_rb_key(rq) (rq)->sector | ||
| 352 | |||
| 353 | /* | ||
| 354 | * as_find_first_arq finds the first (lowest sector numbered) request | ||
| 355 | * for the specified data_dir. Used to sweep back to the start of the disk | ||
| 356 | * (1-way elevator) after we process the last (highest sector) request. | ||
| 357 | */ | ||
| 358 | static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir) | ||
| 359 | { | ||
| 360 | struct rb_node *n = ad->sort_list[data_dir].rb_node; | ||
| 361 | |||
| 362 | if (n == NULL) | ||
| 363 | return NULL; | ||
| 364 | |||
| 365 | for (;;) { | ||
| 366 | if (n->rb_left == NULL) | ||
| 367 | return rb_entry_arq(n); | ||
| 368 | |||
| 369 | n = n->rb_left; | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | /* | ||
| 374 | * Add the request to the rb tree if it is unique. If there is an alias (an | ||
| 375 | * existing request against the same sector), which can happen when using | ||
| 376 | * direct IO, then return the alias. | ||
| 377 | */ | ||
| 378 | static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq) | ||
| 379 | { | ||
| 380 | struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node; | ||
| 381 | struct rb_node *parent = NULL; | ||
| 382 | struct as_rq *__arq; | ||
| 383 | struct request *rq = arq->request; | ||
| 384 | |||
| 385 | arq->rb_key = rq_rb_key(rq); | ||
| 386 | |||
| 387 | while (*p) { | ||
| 388 | parent = *p; | ||
| 389 | __arq = rb_entry_arq(parent); | ||
| 390 | |||
| 391 | if (arq->rb_key < __arq->rb_key) | ||
| 392 | p = &(*p)->rb_left; | ||
| 393 | else if (arq->rb_key > __arq->rb_key) | ||
| 394 | p = &(*p)->rb_right; | ||
| 395 | else | ||
| 396 | return __arq; | ||
| 397 | } | ||
| 398 | |||
| 399 | rb_link_node(&arq->rb_node, parent, p); | ||
| 400 | rb_insert_color(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); | ||
| 401 | |||
| 402 | return NULL; | ||
| 403 | } | ||
| 404 | 249 | ||
| 405 | static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq) | 250 | static void as_add_rq_rb(struct as_data *ad, struct request *rq) |
| 406 | { | 251 | { |
| 407 | struct as_rq *alias; | 252 | struct request *alias; |
| 408 | 253 | ||
| 409 | while ((unlikely(alias = __as_add_arq_rb(ad, arq)))) { | 254 | while ((unlikely(alias = elv_rb_add(RQ_RB_ROOT(ad, rq), rq)))) { |
| 410 | as_move_to_dispatch(ad, alias); | 255 | as_move_to_dispatch(ad, alias); |
| 411 | as_antic_stop(ad); | 256 | as_antic_stop(ad); |
| 412 | } | 257 | } |
| 413 | } | 258 | } |
| 414 | 259 | ||
| 415 | static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) | 260 | static inline void as_del_rq_rb(struct as_data *ad, struct request *rq) |
| 416 | { | ||
| 417 | if (!RB_EMPTY_NODE(&arq->rb_node)) { | ||
| 418 | WARN_ON(1); | ||
| 419 | return; | ||
| 420 | } | ||
| 421 | |||
| 422 | rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); | ||
| 423 | RB_CLEAR_NODE(&arq->rb_node); | ||
| 424 | } | ||
| 425 | |||
| 426 | static struct request * | ||
| 427 | as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir) | ||
| 428 | { | 261 | { |
| 429 | struct rb_node *n = ad->sort_list[data_dir].rb_node; | 262 | elv_rb_del(RQ_RB_ROOT(ad, rq), rq); |
| 430 | struct as_rq *arq; | ||
| 431 | |||
| 432 | while (n) { | ||
| 433 | arq = rb_entry_arq(n); | ||
| 434 | |||
| 435 | if (sector < arq->rb_key) | ||
| 436 | n = n->rb_left; | ||
| 437 | else if (sector > arq->rb_key) | ||
| 438 | n = n->rb_right; | ||
| 439 | else | ||
| 440 | return arq->request; | ||
| 441 | } | ||
| 442 | |||
| 443 | return NULL; | ||
| 444 | } | 263 | } |
| 445 | 264 | ||
| 446 | /* | 265 | /* |
| @@ -458,26 +277,26 @@ as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir) | |||
| 458 | * as_choose_req selects the preferred one of two requests of the same data_dir | 277 | * as_choose_req selects the preferred one of two requests of the same data_dir |
| 459 | * ignoring time - eg. timeouts, which is the job of as_dispatch_request | 278 | * ignoring time - eg. timeouts, which is the job of as_dispatch_request |
| 460 | */ | 279 | */ |
| 461 | static struct as_rq * | 280 | static struct request * |
| 462 | as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2) | 281 | as_choose_req(struct as_data *ad, struct request *rq1, struct request *rq2) |
| 463 | { | 282 | { |
| 464 | int data_dir; | 283 | int data_dir; |
| 465 | sector_t last, s1, s2, d1, d2; | 284 | sector_t last, s1, s2, d1, d2; |
| 466 | int r1_wrap=0, r2_wrap=0; /* requests are behind the disk head */ | 285 | int r1_wrap=0, r2_wrap=0; /* requests are behind the disk head */ |
| 467 | const sector_t maxback = MAXBACK; | 286 | const sector_t maxback = MAXBACK; |
| 468 | 287 | ||
| 469 | if (arq1 == NULL || arq1 == arq2) | 288 | if (rq1 == NULL || rq1 == rq2) |
| 470 | return arq2; | 289 | return rq2; |
| 471 | if (arq2 == NULL) | 290 | if (rq2 == NULL) |
| 472 | return arq1; | 291 | return rq1; |
| 473 | 292 | ||
| 474 | data_dir = arq1->is_sync; | 293 | data_dir = rq_is_sync(rq1); |
| 475 | 294 | ||
| 476 | last = ad->last_sector[data_dir]; | 295 | last = ad->last_sector[data_dir]; |
| 477 | s1 = arq1->request->sector; | 296 | s1 = rq1->sector; |
| 478 | s2 = arq2->request->sector; | 297 | s2 = rq2->sector; |
| 479 | 298 | ||
| 480 | BUG_ON(data_dir != arq2->is_sync); | 299 | BUG_ON(data_dir != rq_is_sync(rq2)); |
| 481 | 300 | ||
| 482 | /* | 301 | /* |
| 483 | * Strict one way elevator _except_ in the case where we allow | 302 | * Strict one way elevator _except_ in the case where we allow |
| @@ -504,61 +323,58 @@ as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2) | |||
| 504 | 323 | ||
| 505 | /* Found required data */ | 324 | /* Found required data */ |
| 506 | if (!r1_wrap && r2_wrap) | 325 | if (!r1_wrap && r2_wrap) |
| 507 | return arq1; | 326 | return rq1; |
| 508 | else if (!r2_wrap && r1_wrap) | 327 | else if (!r2_wrap && r1_wrap) |
| 509 | return arq2; | 328 | return rq2; |
| 510 | else if (r1_wrap && r2_wrap) { | 329 | else if (r1_wrap && r2_wrap) { |
| 511 | /* both behind the head */ | 330 | /* both behind the head */ |
| 512 | if (s1 <= s2) | 331 | if (s1 <= s2) |
| 513 | return arq1; | 332 | return rq1; |
| 514 | else | 333 | else |
| 515 | return arq2; | 334 | return rq2; |
| 516 | } | 335 | } |
| 517 | 336 | ||
| 518 | /* Both requests in front of the head */ | 337 | /* Both requests in front of the head */ |
| 519 | if (d1 < d2) | 338 | if (d1 < d2) |
| 520 | return arq1; | 339 | return rq1; |
| 521 | else if (d2 < d1) | 340 | else if (d2 < d1) |
| 522 | return arq2; | 341 | return rq2; |
| 523 | else { | 342 | else { |
| 524 | if (s1 >= s2) | 343 | if (s1 >= s2) |
| 525 | return arq1; | 344 | return rq1; |
| 526 | else | 345 | else |
| 527 | return arq2; | 346 | return rq2; |
| 528 | } | 347 | } |
| 529 | } | 348 | } |
| 530 | 349 | ||
| 531 | /* | 350 | /* |
| 532 | * as_find_next_arq finds the next request after @prev in elevator order. | 351 | * as_find_next_rq finds the next request after @prev in elevator order. |
| 533 | * this with as_choose_req form the basis for how the scheduler chooses | 352 | * this with as_choose_req form the basis for how the scheduler chooses |
| 534 | * what request to process next. Anticipation works on top of this. | 353 | * what request to process next. Anticipation works on top of this. |
| 535 | */ | 354 | */ |
| 536 | static struct as_rq *as_find_next_arq(struct as_data *ad, struct as_rq *last) | 355 | static struct request * |
| 356 | as_find_next_rq(struct as_data *ad, struct request *last) | ||
| 537 | { | 357 | { |
| 538 | const int data_dir = last->is_sync; | ||
| 539 | struct as_rq *ret; | ||
| 540 | struct rb_node *rbnext = rb_next(&last->rb_node); | 358 | struct rb_node *rbnext = rb_next(&last->rb_node); |
| 541 | struct rb_node *rbprev = rb_prev(&last->rb_node); | 359 | struct rb_node *rbprev = rb_prev(&last->rb_node); |
| 542 | struct as_rq *arq_next, *arq_prev; | 360 | struct request *next = NULL, *prev = NULL; |
| 543 | 361 | ||
| 544 | BUG_ON(!RB_EMPTY_NODE(&last->rb_node)); | 362 | BUG_ON(RB_EMPTY_NODE(&last->rb_node)); |
| 545 | 363 | ||
| 546 | if (rbprev) | 364 | if (rbprev) |
| 547 | arq_prev = rb_entry_arq(rbprev); | 365 | prev = rb_entry_rq(rbprev); |
| 548 | else | ||
| 549 | arq_prev = NULL; | ||
| 550 | 366 | ||
| 551 | if (rbnext) | 367 | if (rbnext) |
| 552 | arq_next = rb_entry_arq(rbnext); | 368 | next = rb_entry_rq(rbnext); |
| 553 | else { | 369 | else { |
| 554 | arq_next = as_find_first_arq(ad, data_dir); | 370 | const int data_dir = rq_is_sync(last); |
| 555 | if (arq_next == last) | ||
| 556 | arq_next = NULL; | ||
| 557 | } | ||
| 558 | 371 | ||
| 559 | ret = as_choose_req(ad, arq_next, arq_prev); | 372 | rbnext = rb_first(&ad->sort_list[data_dir]); |
| 373 | if (rbnext && rbnext != &last->rb_node) | ||
| 374 | next = rb_entry_rq(rbnext); | ||
| 375 | } | ||
| 560 | 376 | ||
| 561 | return ret; | 377 | return as_choose_req(ad, next, prev); |
| 562 | } | 378 | } |
| 563 | 379 | ||
| 564 | /* | 380 | /* |
| @@ -712,8 +528,7 @@ static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic, | |||
| 712 | static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, | 528 | static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, |
| 713 | struct request *rq) | 529 | struct request *rq) |
| 714 | { | 530 | { |
| 715 | struct as_rq *arq = RQ_DATA(rq); | 531 | int data_dir = rq_is_sync(rq); |
| 716 | int data_dir = arq->is_sync; | ||
| 717 | unsigned long thinktime = 0; | 532 | unsigned long thinktime = 0; |
| 718 | sector_t seek_dist; | 533 | sector_t seek_dist; |
| 719 | 534 | ||
| @@ -752,11 +567,11 @@ static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, | |||
| 752 | * previous one issued. | 567 | * previous one issued. |
| 753 | */ | 568 | */ |
| 754 | static int as_close_req(struct as_data *ad, struct as_io_context *aic, | 569 | static int as_close_req(struct as_data *ad, struct as_io_context *aic, |
| 755 | struct as_rq *arq) | 570 | struct request *rq) |
| 756 | { | 571 | { |
| 757 | unsigned long delay; /* milliseconds */ | 572 | unsigned long delay; /* milliseconds */ |
| 758 | sector_t last = ad->last_sector[ad->batch_data_dir]; | 573 | sector_t last = ad->last_sector[ad->batch_data_dir]; |
| 759 | sector_t next = arq->request->sector; | 574 | sector_t next = rq->sector; |
| 760 | sector_t delta; /* acceptable close offset (in sectors) */ | 575 | sector_t delta; /* acceptable close offset (in sectors) */ |
| 761 | sector_t s; | 576 | sector_t s; |
| 762 | 577 | ||
| @@ -813,7 +628,7 @@ static int as_close_req(struct as_data *ad, struct as_io_context *aic, | |||
| 813 | * | 628 | * |
| 814 | * If this task has queued some other IO, do not enter enticipation. | 629 | * If this task has queued some other IO, do not enter enticipation. |
| 815 | */ | 630 | */ |
| 816 | static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) | 631 | static int as_can_break_anticipation(struct as_data *ad, struct request *rq) |
| 817 | { | 632 | { |
| 818 | struct io_context *ioc; | 633 | struct io_context *ioc; |
| 819 | struct as_io_context *aic; | 634 | struct as_io_context *aic; |
| @@ -821,7 +636,7 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) | |||
| 821 | ioc = ad->io_context; | 636 | ioc = ad->io_context; |
| 822 | BUG_ON(!ioc); | 637 | BUG_ON(!ioc); |
| 823 | 638 | ||
| 824 | if (arq && ioc == arq->io_context) { | 639 | if (rq && ioc == RQ_IOC(rq)) { |
| 825 | /* request from same process */ | 640 | /* request from same process */ |
| 826 | return 1; | 641 | return 1; |
| 827 | } | 642 | } |
| @@ -848,7 +663,7 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) | |||
| 848 | return 1; | 663 | return 1; |
| 849 | } | 664 | } |
| 850 | 665 | ||
| 851 | if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, aic, arq)) { | 666 | if (rq && rq_is_sync(rq) && as_close_req(ad, aic, rq)) { |
| 852 | /* | 667 | /* |
| 853 | * Found a close request that is not one of ours. | 668 | * Found a close request that is not one of ours. |
| 854 | * | 669 | * |
| @@ -864,7 +679,7 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) | |||
| 864 | ad->exit_no_coop = (7*ad->exit_no_coop)/8; | 679 | ad->exit_no_coop = (7*ad->exit_no_coop)/8; |
| 865 | } | 680 | } |
| 866 | 681 | ||
| 867 | as_update_iohist(ad, aic, arq->request); | 682 | as_update_iohist(ad, aic, rq); |
| 868 | return 1; | 683 | return 1; |
| 869 | } | 684 | } |
| 870 | 685 | ||
| @@ -891,10 +706,10 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) | |||
| 891 | } | 706 | } |
| 892 | 707 | ||
| 893 | /* | 708 | /* |
| 894 | * as_can_anticipate indicates whether we should either run arq | 709 | * as_can_anticipate indicates whether we should either run rq |
| 895 | * or keep anticipating a better request. | 710 | * or keep anticipating a better request. |
| 896 | */ | 711 | */ |
| 897 | static int as_can_anticipate(struct as_data *ad, struct as_rq *arq) | 712 | static int as_can_anticipate(struct as_data *ad, struct request *rq) |
| 898 | { | 713 | { |
| 899 | if (!ad->io_context) | 714 | if (!ad->io_context) |
| 900 | /* | 715 | /* |
| @@ -908,7 +723,7 @@ static int as_can_anticipate(struct as_data *ad, struct as_rq *arq) | |||
| 908 | */ | 723 | */ |
| 909 | return 0; | 724 | return 0; |
| 910 | 725 | ||
| 911 | if (as_can_break_anticipation(ad, arq)) | 726 | if (as_can_break_anticipation(ad, rq)) |
| 912 | /* | 727 | /* |
| 913 | * This request is a good candidate. Don't keep anticipating, | 728 | * This request is a good candidate. Don't keep anticipating, |
| 914 | * run it. | 729 | * run it. |
| @@ -926,16 +741,16 @@ static int as_can_anticipate(struct as_data *ad, struct as_rq *arq) | |||
| 926 | } | 741 | } |
| 927 | 742 | ||
| 928 | /* | 743 | /* |
| 929 | * as_update_arq must be called whenever a request (arq) is added to | 744 | * as_update_rq must be called whenever a request (rq) is added to |
| 930 | * the sort_list. This function keeps caches up to date, and checks if the | 745 | * the sort_list. This function keeps caches up to date, and checks if the |
| 931 | * request might be one we are "anticipating" | 746 | * request might be one we are "anticipating" |
| 932 | */ | 747 | */ |
| 933 | static void as_update_arq(struct as_data *ad, struct as_rq *arq) | 748 | static void as_update_rq(struct as_data *ad, struct request *rq) |
| 934 | { | 749 | { |
| 935 | const int data_dir = arq->is_sync; | 750 | const int data_dir = rq_is_sync(rq); |
| 936 | 751 | ||
| 937 | /* keep the next_arq cache up to date */ | 752 | /* keep the next_rq cache up to date */ |
| 938 | ad->next_arq[data_dir] = as_choose_req(ad, arq, ad->next_arq[data_dir]); | 753 | ad->next_rq[data_dir] = as_choose_req(ad, rq, ad->next_rq[data_dir]); |
| 939 | 754 | ||
| 940 | /* | 755 | /* |
| 941 | * have we been anticipating this request? | 756 | * have we been anticipating this request? |
| @@ -944,7 +759,7 @@ static void as_update_arq(struct as_data *ad, struct as_rq *arq) | |||
| 944 | */ | 759 | */ |
| 945 | if (ad->antic_status == ANTIC_WAIT_REQ | 760 | if (ad->antic_status == ANTIC_WAIT_REQ |
| 946 | || ad->antic_status == ANTIC_WAIT_NEXT) { | 761 | || ad->antic_status == ANTIC_WAIT_NEXT) { |
| 947 | if (as_can_break_anticipation(ad, arq)) | 762 | if (as_can_break_anticipation(ad, rq)) |
| 948 | as_antic_stop(ad); | 763 | as_antic_stop(ad); |
| 949 | } | 764 | } |
| 950 | } | 765 | } |
| @@ -984,12 +799,11 @@ static void update_write_batch(struct as_data *ad) | |||
| 984 | static void as_completed_request(request_queue_t *q, struct request *rq) | 799 | static void as_completed_request(request_queue_t *q, struct request *rq) |
| 985 | { | 800 | { |
| 986 | struct as_data *ad = q->elevator->elevator_data; | 801 | struct as_data *ad = q->elevator->elevator_data; |
| 987 | struct as_rq *arq = RQ_DATA(rq); | ||
| 988 | 802 | ||
| 989 | WARN_ON(!list_empty(&rq->queuelist)); | 803 | WARN_ON(!list_empty(&rq->queuelist)); |
| 990 | 804 | ||
| 991 | if (arq->state != AS_RQ_REMOVED) { | 805 | if (RQ_STATE(rq) != AS_RQ_REMOVED) { |
| 992 | printk("arq->state %d\n", arq->state); | 806 | printk("rq->state %d\n", RQ_STATE(rq)); |
| 993 | WARN_ON(1); | 807 | WARN_ON(1); |
| 994 | goto out; | 808 | goto out; |
| 995 | } | 809 | } |
| @@ -1009,14 +823,14 @@ static void as_completed_request(request_queue_t *q, struct request *rq) | |||
| 1009 | * actually serviced. This should help devices with big TCQ windows | 823 | * actually serviced. This should help devices with big TCQ windows |
| 1010 | * and writeback caches | 824 | * and writeback caches |
| 1011 | */ | 825 | */ |
| 1012 | if (ad->new_batch && ad->batch_data_dir == arq->is_sync) { | 826 | if (ad->new_batch && ad->batch_data_dir == rq_is_sync(rq)) { |
| 1013 | update_write_batch(ad); | 827 | update_write_batch(ad); |
| 1014 | ad->current_batch_expires = jiffies + | 828 | ad->current_batch_expires = jiffies + |
| 1015 | ad->batch_expire[REQ_SYNC]; | 829 | ad->batch_expire[REQ_SYNC]; |
| 1016 | ad->new_batch = 0; | 830 | ad->new_batch = 0; |
| 1017 | } | 831 | } |
| 1018 | 832 | ||
| 1019 | if (ad->io_context == arq->io_context && ad->io_context) { | 833 | if (ad->io_context == RQ_IOC(rq) && ad->io_context) { |
| 1020 | ad->antic_start = jiffies; | 834 | ad->antic_start = jiffies; |
| 1021 | ad->ioc_finished = 1; | 835 | ad->ioc_finished = 1; |
| 1022 | if (ad->antic_status == ANTIC_WAIT_REQ) { | 836 | if (ad->antic_status == ANTIC_WAIT_REQ) { |
| @@ -1028,9 +842,9 @@ static void as_completed_request(request_queue_t *q, struct request *rq) | |||
| 1028 | } | 842 | } |
| 1029 | } | 843 | } |
| 1030 | 844 | ||
| 1031 | as_put_io_context(arq); | 845 | as_put_io_context(rq); |
| 1032 | out: | 846 | out: |
| 1033 | arq->state = AS_RQ_POSTSCHED; | 847 | RQ_SET_STATE(rq, AS_RQ_POSTSCHED); |
| 1034 | } | 848 | } |
| 1035 | 849 | ||
| 1036 | /* | 850 | /* |
| @@ -1041,27 +855,27 @@ out: | |||
| 1041 | */ | 855 | */ |
| 1042 | static void as_remove_queued_request(request_queue_t *q, struct request *rq) | 856 | static void as_remove_queued_request(request_queue_t *q, struct request *rq) |
| 1043 | { | 857 | { |
| 1044 | struct as_rq *arq = RQ_DATA(rq); | 858 | const int data_dir = rq_is_sync(rq); |
| 1045 | const int data_dir = arq->is_sync; | ||
| 1046 | struct as_data *ad = q->elevator->elevator_data; | 859 | struct as_data *ad = q->elevator->elevator_data; |
| 860 | struct io_context *ioc; | ||
| 1047 | 861 | ||
| 1048 | WARN_ON(arq->state != AS_RQ_QUEUED); | 862 | WARN_ON(RQ_STATE(rq) != AS_RQ_QUEUED); |
| 1049 | 863 | ||
| 1050 | if (arq->io_context && arq->io_context->aic) { | 864 | ioc = RQ_IOC(rq); |
| 1051 | BUG_ON(!atomic_read(&arq->io_context->aic->nr_queued)); | 865 | if (ioc && ioc->aic) { |
| 1052 | atomic_dec(&arq->io_context->aic->nr_queued); | 866 | BUG_ON(!atomic_read(&ioc->aic->nr_queued)); |
| 867 | atomic_dec(&ioc->aic->nr_queued); | ||
| 1053 | } | 868 | } |
| 1054 | 869 | ||
| 1055 | /* | 870 | /* |
| 1056 | * Update the "next_arq" cache if we are about to remove its | 871 | * Update the "next_rq" cache if we are about to remove its |
| 1057 | * entry | 872 | * entry |
| 1058 | */ | 873 | */ |
| 1059 | if (ad->next_arq[data_dir] == arq) | 874 | if (ad->next_rq[data_dir] == rq) |
| 1060 | ad->next_arq[data_dir] = as_find_next_arq(ad, arq); | 875 | ad->next_rq[data_dir] = as_find_next_rq(ad, rq); |
| 1061 | 876 | ||
| 1062 | list_del_init(&arq->fifo); | 877 | rq_fifo_clear(rq); |
| 1063 | as_del_arq_hash(arq); | 878 | as_del_rq_rb(ad, rq); |
| 1064 | as_del_arq_rb(ad, arq); | ||
| 1065 | } | 879 | } |
| 1066 | 880 | ||
| 1067 | /* | 881 | /* |
| @@ -1074,7 +888,7 @@ static void as_remove_queued_request(request_queue_t *q, struct request *rq) | |||
| 1074 | */ | 888 | */ |
| 1075 | static int as_fifo_expired(struct as_data *ad, int adir) | 889 | static int as_fifo_expired(struct as_data *ad, int adir) |
| 1076 | { | 890 | { |
| 1077 | struct as_rq *arq; | 891 | struct request *rq; |
| 1078 | long delta_jif; | 892 | long delta_jif; |
| 1079 | 893 | ||
| 1080 | delta_jif = jiffies - ad->last_check_fifo[adir]; | 894 | delta_jif = jiffies - ad->last_check_fifo[adir]; |
| @@ -1088,9 +902,9 @@ static int as_fifo_expired(struct as_data *ad, int adir) | |||
| 1088 | if (list_empty(&ad->fifo_list[adir])) | 902 | if (list_empty(&ad->fifo_list[adir])) |
| 1089 | return 0; | 903 | return 0; |
| 1090 | 904 | ||
| 1091 | arq = list_entry_fifo(ad->fifo_list[adir].next); | 905 | rq = rq_entry_fifo(ad->fifo_list[adir].next); |
| 1092 | 906 | ||
| 1093 | return time_after(jiffies, arq->expires); | 907 | return time_after(jiffies, rq_fifo_time(rq)); |
| 1094 | } | 908 | } |
| 1095 | 909 | ||
| 1096 | /* | 910 | /* |
| @@ -1113,25 +927,25 @@ static inline int as_batch_expired(struct as_data *ad) | |||
| 1113 | /* | 927 | /* |
| 1114 | * move an entry to dispatch queue | 928 | * move an entry to dispatch queue |
| 1115 | */ | 929 | */ |
| 1116 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) | 930 | static void as_move_to_dispatch(struct as_data *ad, struct request *rq) |
| 1117 | { | 931 | { |
| 1118 | struct request *rq = arq->request; | 932 | const int data_dir = rq_is_sync(rq); |
| 1119 | const int data_dir = arq->is_sync; | ||
| 1120 | 933 | ||
| 1121 | BUG_ON(!RB_EMPTY_NODE(&arq->rb_node)); | 934 | BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); |
| 1122 | 935 | ||
| 1123 | as_antic_stop(ad); | 936 | as_antic_stop(ad); |
| 1124 | ad->antic_status = ANTIC_OFF; | 937 | ad->antic_status = ANTIC_OFF; |
| 1125 | 938 | ||
| 1126 | /* | 939 | /* |
| 1127 | * This has to be set in order to be correctly updated by | 940 | * This has to be set in order to be correctly updated by |
| 1128 | * as_find_next_arq | 941 | * as_find_next_rq |
| 1129 | */ | 942 | */ |
| 1130 | ad->last_sector[data_dir] = rq->sector + rq->nr_sectors; | 943 | ad->last_sector[data_dir] = rq->sector + rq->nr_sectors; |
| 1131 | 944 | ||
| 1132 | if (data_dir == REQ_SYNC) { | 945 | if (data_dir == REQ_SYNC) { |
| 946 | struct io_context *ioc = RQ_IOC(rq); | ||
| 1133 | /* In case we have to anticipate after this */ | 947 | /* In case we have to anticipate after this */ |
| 1134 | copy_io_context(&ad->io_context, &arq->io_context); | 948 | copy_io_context(&ad->io_context, &ioc); |
| 1135 | } else { | 949 | } else { |
| 1136 | if (ad->io_context) { | 950 | if (ad->io_context) { |
| 1137 | put_io_context(ad->io_context); | 951 | put_io_context(ad->io_context); |
| @@ -1143,19 +957,19 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) | |||
| 1143 | } | 957 | } |
| 1144 | ad->ioc_finished = 0; | 958 | ad->ioc_finished = 0; |
| 1145 | 959 | ||
| 1146 | ad->next_arq[data_dir] = as_find_next_arq(ad, arq); | 960 | ad->next_rq[data_dir] = as_find_next_rq(ad, rq); |
| 1147 | 961 | ||
| 1148 | /* | 962 | /* |
| 1149 | * take it off the sort and fifo list, add to dispatch queue | 963 | * take it off the sort and fifo list, add to dispatch queue |
| 1150 | */ | 964 | */ |
| 1151 | as_remove_queued_request(ad->q, rq); | 965 | as_remove_queued_request(ad->q, rq); |
| 1152 | WARN_ON(arq->state != AS_RQ_QUEUED); | 966 | WARN_ON(RQ_STATE(rq) != AS_RQ_QUEUED); |
| 1153 | 967 | ||
| 1154 | elv_dispatch_sort(ad->q, rq); | 968 | elv_dispatch_sort(ad->q, rq); |
| 1155 | 969 | ||
| 1156 | arq->state = AS_RQ_DISPATCHED; | 970 | RQ_SET_STATE(rq, AS_RQ_DISPATCHED); |
| 1157 | if (arq->io_context && arq->io_context->aic) | 971 | if (RQ_IOC(rq) && RQ_IOC(rq)->aic) |
| 1158 | atomic_inc(&arq->io_context->aic->nr_dispatched); | 972 | atomic_inc(&RQ_IOC(rq)->aic->nr_dispatched); |
| 1159 | ad->nr_dispatched++; | 973 | ad->nr_dispatched++; |
| 1160 | } | 974 | } |
| 1161 | 975 | ||
| @@ -1167,9 +981,9 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) | |||
| 1167 | static int as_dispatch_request(request_queue_t *q, int force) | 981 | static int as_dispatch_request(request_queue_t *q, int force) |
| 1168 | { | 982 | { |
| 1169 | struct as_data *ad = q->elevator->elevator_data; | 983 | struct as_data *ad = q->elevator->elevator_data; |
| 1170 | struct as_rq *arq; | ||
| 1171 | const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]); | 984 | const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]); |
| 1172 | const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]); | 985 | const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]); |
| 986 | struct request *rq; | ||
| 1173 | 987 | ||
| 1174 | if (unlikely(force)) { | 988 | if (unlikely(force)) { |
| 1175 | /* | 989 | /* |
| @@ -1185,14 +999,14 @@ static int as_dispatch_request(request_queue_t *q, int force) | |||
| 1185 | ad->changed_batch = 0; | 999 | ad->changed_batch = 0; |
| 1186 | ad->new_batch = 0; | 1000 | ad->new_batch = 0; |
| 1187 | 1001 | ||
| 1188 | while (ad->next_arq[REQ_SYNC]) { | 1002 | while (ad->next_rq[REQ_SYNC]) { |
| 1189 | as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); | 1003 | as_move_to_dispatch(ad, ad->next_rq[REQ_SYNC]); |
| 1190 | dispatched++; | 1004 | dispatched++; |
| 1191 | } | 1005 | } |
| 1192 | ad->last_check_fifo[REQ_SYNC] = jiffies; | 1006 | ad->last_check_fifo[REQ_SYNC] = jiffies; |
| 1193 | 1007 | ||
| 1194 | while (ad->next_arq[REQ_ASYNC]) { | 1008 | while (ad->next_rq[REQ_ASYNC]) { |
| 1195 | as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); | 1009 | as_move_to_dispatch(ad, ad->next_rq[REQ_ASYNC]); |
| 1196 | dispatched++; | 1010 | dispatched++; |
| 1197 | } | 1011 | } |
| 1198 | ad->last_check_fifo[REQ_ASYNC] = jiffies; | 1012 | ad->last_check_fifo[REQ_ASYNC] = jiffies; |
| @@ -1216,19 +1030,19 @@ static int as_dispatch_request(request_queue_t *q, int force) | |||
| 1216 | /* | 1030 | /* |
| 1217 | * batch is still running or no reads or no writes | 1031 | * batch is still running or no reads or no writes |
| 1218 | */ | 1032 | */ |
| 1219 | arq = ad->next_arq[ad->batch_data_dir]; | 1033 | rq = ad->next_rq[ad->batch_data_dir]; |
| 1220 | 1034 | ||
| 1221 | if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) { | 1035 | if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) { |
| 1222 | if (as_fifo_expired(ad, REQ_SYNC)) | 1036 | if (as_fifo_expired(ad, REQ_SYNC)) |
| 1223 | goto fifo_expired; | 1037 | goto fifo_expired; |
| 1224 | 1038 | ||
| 1225 | if (as_can_anticipate(ad, arq)) { | 1039 | if (as_can_anticipate(ad, rq)) { |
| 1226 | as_antic_waitreq(ad); | 1040 | as_antic_waitreq(ad); |
| 1227 | return 0; | 1041 | return 0; |
| 1228 | } | 1042 | } |
| 1229 | } | 1043 | } |
| 1230 | 1044 | ||
| 1231 | if (arq) { | 1045 | if (rq) { |
| 1232 | /* we have a "next request" */ | 1046 | /* we have a "next request" */ |
| 1233 | if (reads && !writes) | 1047 | if (reads && !writes) |
| 1234 | ad->current_batch_expires = | 1048 | ad->current_batch_expires = |
| @@ -1256,7 +1070,7 @@ static int as_dispatch_request(request_queue_t *q, int force) | |||
| 1256 | ad->changed_batch = 1; | 1070 | ad->changed_batch = 1; |
| 1257 | } | 1071 | } |
| 1258 | ad->batch_data_dir = REQ_SYNC; | 1072 | ad->batch_data_dir = REQ_SYNC; |
| 1259 | arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next); | 1073 | rq = rq_entry_fifo(ad->fifo_list[REQ_SYNC].next); |
| 1260 | ad->last_check_fifo[ad->batch_data_dir] = jiffies; | 1074 | ad->last_check_fifo[ad->batch_data_dir] = jiffies; |
| 1261 | goto dispatch_request; | 1075 | goto dispatch_request; |
| 1262 | } | 1076 | } |
| @@ -1282,7 +1096,7 @@ dispatch_writes: | |||
| 1282 | ad->batch_data_dir = REQ_ASYNC; | 1096 | ad->batch_data_dir = REQ_ASYNC; |
| 1283 | ad->current_write_count = ad->write_batch_count; | 1097 | ad->current_write_count = ad->write_batch_count; |
| 1284 | ad->write_batch_idled = 0; | 1098 | ad->write_batch_idled = 0; |
| 1285 | arq = ad->next_arq[ad->batch_data_dir]; | 1099 | rq = ad->next_rq[ad->batch_data_dir]; |
| 1286 | goto dispatch_request; | 1100 | goto dispatch_request; |
| 1287 | } | 1101 | } |
| 1288 | 1102 | ||
| @@ -1296,8 +1110,7 @@ dispatch_request: | |||
| 1296 | 1110 | ||
| 1297 | if (as_fifo_expired(ad, ad->batch_data_dir)) { | 1111 | if (as_fifo_expired(ad, ad->batch_data_dir)) { |
| 1298 | fifo_expired: | 1112 | fifo_expired: |
| 1299 | arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next); | 1113 | rq = rq_entry_fifo(ad->fifo_list[ad->batch_data_dir].next); |
| 1300 | BUG_ON(arq == NULL); | ||
| 1301 | } | 1114 | } |
| 1302 | 1115 | ||
| 1303 | if (ad->changed_batch) { | 1116 | if (ad->changed_batch) { |
| @@ -1316,70 +1129,58 @@ fifo_expired: | |||
| 1316 | } | 1129 | } |
| 1317 | 1130 | ||
| 1318 | /* | 1131 | /* |
| 1319 | * arq is the selected appropriate request. | 1132 | * rq is the selected appropriate request. |
| 1320 | */ | 1133 | */ |
| 1321 | as_move_to_dispatch(ad, arq); | 1134 | as_move_to_dispatch(ad, rq); |
| 1322 | 1135 | ||
| 1323 | return 1; | 1136 | return 1; |
| 1324 | } | 1137 | } |
| 1325 | 1138 | ||
| 1326 | /* | 1139 | /* |
| 1327 | * add arq to rbtree and fifo | 1140 | * add rq to rbtree and fifo |
| 1328 | */ | 1141 | */ |
| 1329 | static void as_add_request(request_queue_t *q, struct request *rq) | 1142 | static void as_add_request(request_queue_t *q, struct request *rq) |
| 1330 | { | 1143 | { |
| 1331 | struct as_data *ad = q->elevator->elevator_data; | 1144 | struct as_data *ad = q->elevator->elevator_data; |
| 1332 | struct as_rq *arq = RQ_DATA(rq); | ||
| 1333 | int data_dir; | 1145 | int data_dir; |
| 1334 | 1146 | ||
| 1335 | arq->state = AS_RQ_NEW; | 1147 | RQ_SET_STATE(rq, AS_RQ_NEW); |
| 1336 | 1148 | ||
| 1337 | if (rq_data_dir(arq->request) == READ | 1149 | data_dir = rq_is_sync(rq); |
| 1338 | || (arq->request->flags & REQ_RW_SYNC)) | ||
| 1339 | arq->is_sync = 1; | ||
| 1340 | else | ||
| 1341 | arq->is_sync = 0; | ||
| 1342 | data_dir = arq->is_sync; | ||
| 1343 | 1150 | ||
| 1344 | arq->io_context = as_get_io_context(); | 1151 | rq->elevator_private = as_get_io_context(q->node); |
| 1345 | 1152 | ||
| 1346 | if (arq->io_context) { | 1153 | if (RQ_IOC(rq)) { |
| 1347 | as_update_iohist(ad, arq->io_context->aic, arq->request); | 1154 | as_update_iohist(ad, RQ_IOC(rq)->aic, rq); |
| 1348 | atomic_inc(&arq->io_context->aic->nr_queued); | 1155 | atomic_inc(&RQ_IOC(rq)->aic->nr_queued); |
| 1349 | } | 1156 | } |
| 1350 | 1157 | ||
| 1351 | as_add_arq_rb(ad, arq); | 1158 | as_add_rq_rb(ad, rq); |
| 1352 | if (rq_mergeable(arq->request)) | ||
| 1353 | as_add_arq_hash(ad, arq); | ||
| 1354 | 1159 | ||
| 1355 | /* | 1160 | /* |
| 1356 | * set expire time (only used for reads) and add to fifo list | 1161 | * set expire time (only used for reads) and add to fifo list |
| 1357 | */ | 1162 | */ |
| 1358 | arq->expires = jiffies + ad->fifo_expire[data_dir]; | 1163 | rq_set_fifo_time(rq, jiffies + ad->fifo_expire[data_dir]); |
| 1359 | list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]); | 1164 | list_add_tail(&rq->queuelist, &ad->fifo_list[data_dir]); |
| 1360 | 1165 | ||
| 1361 | as_update_arq(ad, arq); /* keep state machine up to date */ | 1166 | as_update_rq(ad, rq); /* keep state machine up to date */ |
| 1362 | arq->state = AS_RQ_QUEUED; | 1167 | RQ_SET_STATE(rq, AS_RQ_QUEUED); |
| 1363 | } | 1168 | } |
| 1364 | 1169 | ||
| 1365 | static void as_activate_request(request_queue_t *q, struct request *rq) | 1170 | static void as_activate_request(request_queue_t *q, struct request *rq) |
| 1366 | { | 1171 | { |
| 1367 | struct as_rq *arq = RQ_DATA(rq); | 1172 | WARN_ON(RQ_STATE(rq) != AS_RQ_DISPATCHED); |
| 1368 | 1173 | RQ_SET_STATE(rq, AS_RQ_REMOVED); | |
| 1369 | WARN_ON(arq->state != AS_RQ_DISPATCHED); | 1174 | if (RQ_IOC(rq) && RQ_IOC(rq)->aic) |
| 1370 | arq->state = AS_RQ_REMOVED; | 1175 | atomic_dec(&RQ_IOC(rq)->aic->nr_dispatched); |
| 1371 | if (arq->io_context && arq->io_context->aic) | ||
| 1372 | atomic_dec(&arq->io_context->aic->nr_dispatched); | ||
| 1373 | } | 1176 | } |
| 1374 | 1177 | ||
| 1375 | static void as_deactivate_request(request_queue_t *q, struct request *rq) | 1178 | static void as_deactivate_request(request_queue_t *q, struct request *rq) |
| 1376 | { | 1179 | { |
| 1377 | struct as_rq *arq = RQ_DATA(rq); | 1180 | WARN_ON(RQ_STATE(rq) != AS_RQ_REMOVED); |
| 1378 | 1181 | RQ_SET_STATE(rq, AS_RQ_DISPATCHED); | |
| 1379 | WARN_ON(arq->state != AS_RQ_REMOVED); | 1182 | if (RQ_IOC(rq) && RQ_IOC(rq)->aic) |
| 1380 | arq->state = AS_RQ_DISPATCHED; | 1183 | atomic_inc(&RQ_IOC(rq)->aic->nr_dispatched); |
| 1381 | if (arq->io_context && arq->io_context->aic) | ||
| 1382 | atomic_inc(&arq->io_context->aic->nr_dispatched); | ||
| 1383 | } | 1184 | } |
| 1384 | 1185 | ||
| 1385 | /* | 1186 | /* |
| @@ -1396,93 +1197,35 @@ static int as_queue_empty(request_queue_t *q) | |||
| 1396 | && list_empty(&ad->fifo_list[REQ_SYNC]); | 1197 | && list_empty(&ad->fifo_list[REQ_SYNC]); |
| 1397 | } | 1198 | } |
| 1398 | 1199 | ||
| 1399 | static struct request *as_former_request(request_queue_t *q, | ||
| 1400 | struct request *rq) | ||
| 1401 | { | ||
| 1402 | struct as_rq *arq = RQ_DATA(rq); | ||
| 1403 | struct rb_node *rbprev = rb_prev(&arq->rb_node); | ||
| 1404 | struct request *ret = NULL; | ||
| 1405 | |||
| 1406 | if (rbprev) | ||
| 1407 | ret = rb_entry_arq(rbprev)->request; | ||
| 1408 | |||
| 1409 | return ret; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | static struct request *as_latter_request(request_queue_t *q, | ||
| 1413 | struct request *rq) | ||
| 1414 | { | ||
| 1415 | struct as_rq *arq = RQ_DATA(rq); | ||
| 1416 | struct rb_node *rbnext = rb_next(&arq->rb_node); | ||
| 1417 | struct request *ret = NULL; | ||
| 1418 | |||
| 1419 | if (rbnext) | ||
| 1420 | ret = rb_entry_arq(rbnext)->request; | ||
| 1421 | |||
| 1422 | return ret; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | static int | 1200 | static int |
| 1426 | as_merge(request_queue_t *q, struct request **req, struct bio *bio) | 1201 | as_merge(request_queue_t *q, struct request **req, struct bio *bio) |
| 1427 | { | 1202 | { |
| 1428 | struct as_data *ad = q->elevator->elevator_data; | 1203 | struct as_data *ad = q->elevator->elevator_data; |
| 1429 | sector_t rb_key = bio->bi_sector + bio_sectors(bio); | 1204 | sector_t rb_key = bio->bi_sector + bio_sectors(bio); |
| 1430 | struct request *__rq; | 1205 | struct request *__rq; |
| 1431 | int ret; | ||
| 1432 | |||
| 1433 | /* | ||
| 1434 | * see if the merge hash can satisfy a back merge | ||
| 1435 | */ | ||
| 1436 | __rq = as_find_arq_hash(ad, bio->bi_sector); | ||
| 1437 | if (__rq) { | ||
| 1438 | BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); | ||
| 1439 | |||
| 1440 | if (elv_rq_merge_ok(__rq, bio)) { | ||
| 1441 | ret = ELEVATOR_BACK_MERGE; | ||
| 1442 | goto out; | ||
| 1443 | } | ||
| 1444 | } | ||
| 1445 | 1206 | ||
| 1446 | /* | 1207 | /* |
| 1447 | * check for front merge | 1208 | * check for front merge |
| 1448 | */ | 1209 | */ |
| 1449 | __rq = as_find_arq_rb(ad, rb_key, bio_data_dir(bio)); | 1210 | __rq = elv_rb_find(&ad->sort_list[bio_data_dir(bio)], rb_key); |
| 1450 | if (__rq) { | 1211 | if (__rq && elv_rq_merge_ok(__rq, bio)) { |
| 1451 | BUG_ON(rb_key != rq_rb_key(__rq)); | 1212 | *req = __rq; |
| 1452 | 1213 | return ELEVATOR_FRONT_MERGE; | |
| 1453 | if (elv_rq_merge_ok(__rq, bio)) { | ||
| 1454 | ret = ELEVATOR_FRONT_MERGE; | ||
| 1455 | goto out; | ||
| 1456 | } | ||
| 1457 | } | 1214 | } |
| 1458 | 1215 | ||
| 1459 | return ELEVATOR_NO_MERGE; | 1216 | return ELEVATOR_NO_MERGE; |
| 1460 | out: | ||
| 1461 | if (ret) { | ||
| 1462 | if (rq_mergeable(__rq)) | ||
| 1463 | as_hot_arq_hash(ad, RQ_DATA(__rq)); | ||
| 1464 | } | ||
| 1465 | *req = __rq; | ||
| 1466 | return ret; | ||
| 1467 | } | 1217 | } |
| 1468 | 1218 | ||
| 1469 | static void as_merged_request(request_queue_t *q, struct request *req) | 1219 | static void as_merged_request(request_queue_t *q, struct request *req, int type) |
| 1470 | { | 1220 | { |
| 1471 | struct as_data *ad = q->elevator->elevator_data; | 1221 | struct as_data *ad = q->elevator->elevator_data; |
| 1472 | struct as_rq *arq = RQ_DATA(req); | ||
| 1473 | |||
| 1474 | /* | ||
| 1475 | * hash always needs to be repositioned, key is end sector | ||
| 1476 | */ | ||
| 1477 | as_del_arq_hash(arq); | ||
| 1478 | as_add_arq_hash(ad, arq); | ||
| 1479 | 1222 | ||
| 1480 | /* | 1223 | /* |
| 1481 | * if the merge was a front merge, we need to reposition request | 1224 | * if the merge was a front merge, we need to reposition request |
| 1482 | */ | 1225 | */ |
| 1483 | if (rq_rb_key(req) != arq->rb_key) { | 1226 | if (type == ELEVATOR_FRONT_MERGE) { |
| 1484 | as_del_arq_rb(ad, arq); | 1227 | as_del_rq_rb(ad, req); |
| 1485 | as_add_arq_rb(ad, arq); | 1228 | as_add_rq_rb(ad, req); |
| 1486 | /* | 1229 | /* |
| 1487 | * Note! At this stage of this and the next function, our next | 1230 | * Note! At this stage of this and the next function, our next |
| 1488 | * request may not be optimal - eg the request may have "grown" | 1231 | * request may not be optimal - eg the request may have "grown" |
| @@ -1494,38 +1237,22 @@ static void as_merged_request(request_queue_t *q, struct request *req) | |||
| 1494 | static void as_merged_requests(request_queue_t *q, struct request *req, | 1237 | static void as_merged_requests(request_queue_t *q, struct request *req, |
| 1495 | struct request *next) | 1238 | struct request *next) |
| 1496 | { | 1239 | { |
| 1497 | struct as_data *ad = q->elevator->elevator_data; | ||
| 1498 | struct as_rq *arq = RQ_DATA(req); | ||
| 1499 | struct as_rq *anext = RQ_DATA(next); | ||
| 1500 | |||
| 1501 | BUG_ON(!arq); | ||
| 1502 | BUG_ON(!anext); | ||
| 1503 | |||
| 1504 | /* | 1240 | /* |
| 1505 | * reposition arq (this is the merged request) in hash, and in rbtree | 1241 | * if next expires before rq, assign its expire time to arq |
| 1506 | * in case of a front merge | 1242 | * and move into next position (next will be deleted) in fifo |
| 1507 | */ | 1243 | */ |
| 1508 | as_del_arq_hash(arq); | 1244 | if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) { |
| 1509 | as_add_arq_hash(ad, arq); | 1245 | if (time_before(rq_fifo_time(next), rq_fifo_time(req))) { |
| 1510 | 1246 | struct io_context *rioc = RQ_IOC(req); | |
| 1511 | if (rq_rb_key(req) != arq->rb_key) { | 1247 | struct io_context *nioc = RQ_IOC(next); |
| 1512 | as_del_arq_rb(ad, arq); | ||
| 1513 | as_add_arq_rb(ad, arq); | ||
| 1514 | } | ||
| 1515 | 1248 | ||
| 1516 | /* | 1249 | list_move(&req->queuelist, &next->queuelist); |
| 1517 | * if anext expires before arq, assign its expire time to arq | 1250 | rq_set_fifo_time(req, rq_fifo_time(next)); |
| 1518 | * and move into anext position (anext will be deleted) in fifo | ||
| 1519 | */ | ||
| 1520 | if (!list_empty(&arq->fifo) && !list_empty(&anext->fifo)) { | ||
| 1521 | if (time_before(anext->expires, arq->expires)) { | ||
| 1522 | list_move(&arq->fifo, &anext->fifo); | ||
| 1523 | arq->expires = anext->expires; | ||
| 1524 | /* | 1251 | /* |
| 1525 | * Don't copy here but swap, because when anext is | 1252 | * Don't copy here but swap, because when anext is |
| 1526 | * removed below, it must contain the unused context | 1253 | * removed below, it must contain the unused context |
| 1527 | */ | 1254 | */ |
| 1528 | swap_io_context(&arq->io_context, &anext->io_context); | 1255 | swap_io_context(&rioc, &nioc); |
| 1529 | } | 1256 | } |
| 1530 | } | 1257 | } |
| 1531 | 1258 | ||
| @@ -1533,9 +1260,9 @@ static void as_merged_requests(request_queue_t *q, struct request *req, | |||
| 1533 | * kill knowledge of next, this one is a goner | 1260 | * kill knowledge of next, this one is a goner |
| 1534 | */ | 1261 | */ |
| 1535 | as_remove_queued_request(q, next); | 1262 | as_remove_queued_request(q, next); |
| 1536 | as_put_io_context(anext); | 1263 | as_put_io_context(next); |
| 1537 | 1264 | ||
| 1538 | anext->state = AS_RQ_MERGED; | 1265 | RQ_SET_STATE(next, AS_RQ_MERGED); |
| 1539 | } | 1266 | } |
| 1540 | 1267 | ||
| 1541 | /* | 1268 | /* |
| @@ -1553,61 +1280,18 @@ static void as_work_handler(void *data) | |||
| 1553 | unsigned long flags; | 1280 | unsigned long flags; |
| 1554 | 1281 | ||
| 1555 | spin_lock_irqsave(q->queue_lock, flags); | 1282 | spin_lock_irqsave(q->queue_lock, flags); |
| 1556 | if (!as_queue_empty(q)) | 1283 | blk_start_queueing(q); |
| 1557 | q->request_fn(q); | ||
| 1558 | spin_unlock_irqrestore(q->queue_lock, flags); | 1284 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 1559 | } | 1285 | } |
| 1560 | 1286 | ||
| 1561 | static void as_put_request(request_queue_t *q, struct request *rq) | 1287 | static int as_may_queue(request_queue_t *q, int rw) |
| 1562 | { | ||
| 1563 | struct as_data *ad = q->elevator->elevator_data; | ||
| 1564 | struct as_rq *arq = RQ_DATA(rq); | ||
| 1565 | |||
| 1566 | if (!arq) { | ||
| 1567 | WARN_ON(1); | ||
| 1568 | return; | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | if (unlikely(arq->state != AS_RQ_POSTSCHED && | ||
| 1572 | arq->state != AS_RQ_PRESCHED && | ||
| 1573 | arq->state != AS_RQ_MERGED)) { | ||
| 1574 | printk("arq->state %d\n", arq->state); | ||
| 1575 | WARN_ON(1); | ||
| 1576 | } | ||
| 1577 | |||
| 1578 | mempool_free(arq, ad->arq_pool); | ||
| 1579 | rq->elevator_private = NULL; | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | static int as_set_request(request_queue_t *q, struct request *rq, | ||
| 1583 | struct bio *bio, gfp_t gfp_mask) | ||
| 1584 | { | ||
| 1585 | struct as_data *ad = q->elevator->elevator_data; | ||
| 1586 | struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask); | ||
| 1587 | |||
| 1588 | if (arq) { | ||
| 1589 | memset(arq, 0, sizeof(*arq)); | ||
| 1590 | RB_CLEAR_NODE(&arq->rb_node); | ||
| 1591 | arq->request = rq; | ||
| 1592 | arq->state = AS_RQ_PRESCHED; | ||
| 1593 | arq->io_context = NULL; | ||
| 1594 | INIT_HLIST_NODE(&arq->hash); | ||
| 1595 | INIT_LIST_HEAD(&arq->fifo); | ||
| 1596 | rq->elevator_private = arq; | ||
| 1597 | return 0; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | return 1; | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | static int as_may_queue(request_queue_t *q, int rw, struct bio *bio) | ||
| 1604 | { | 1288 | { |
| 1605 | int ret = ELV_MQUEUE_MAY; | 1289 | int ret = ELV_MQUEUE_MAY; |
| 1606 | struct as_data *ad = q->elevator->elevator_data; | 1290 | struct as_data *ad = q->elevator->elevator_data; |
| 1607 | struct io_context *ioc; | 1291 | struct io_context *ioc; |
| 1608 | if (ad->antic_status == ANTIC_WAIT_REQ || | 1292 | if (ad->antic_status == ANTIC_WAIT_REQ || |
| 1609 | ad->antic_status == ANTIC_WAIT_NEXT) { | 1293 | ad->antic_status == ANTIC_WAIT_NEXT) { |
| 1610 | ioc = as_get_io_context(); | 1294 | ioc = as_get_io_context(q->node); |
| 1611 | if (ad->io_context == ioc) | 1295 | if (ad->io_context == ioc) |
| 1612 | ret = ELV_MQUEUE_MUST; | 1296 | ret = ELV_MQUEUE_MUST; |
| 1613 | put_io_context(ioc); | 1297 | put_io_context(ioc); |
| @@ -1626,23 +1310,16 @@ static void as_exit_queue(elevator_t *e) | |||
| 1626 | BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC])); | 1310 | BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC])); |
| 1627 | BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC])); | 1311 | BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC])); |
| 1628 | 1312 | ||
| 1629 | mempool_destroy(ad->arq_pool); | ||
| 1630 | put_io_context(ad->io_context); | 1313 | put_io_context(ad->io_context); |
| 1631 | kfree(ad->hash); | ||
| 1632 | kfree(ad); | 1314 | kfree(ad); |
| 1633 | } | 1315 | } |
| 1634 | 1316 | ||
| 1635 | /* | 1317 | /* |
| 1636 | * initialize elevator private data (as_data), and alloc a arq for | 1318 | * initialize elevator private data (as_data). |
| 1637 | * each request on the free lists | ||
| 1638 | */ | 1319 | */ |
| 1639 | static void *as_init_queue(request_queue_t *q, elevator_t *e) | 1320 | static void *as_init_queue(request_queue_t *q, elevator_t *e) |
| 1640 | { | 1321 | { |
| 1641 | struct as_data *ad; | 1322 | struct as_data *ad; |
| 1642 | int i; | ||
| 1643 | |||
| 1644 | if (!arq_pool) | ||
| 1645 | return NULL; | ||
| 1646 | 1323 | ||
| 1647 | ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node); | 1324 | ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node); |
| 1648 | if (!ad) | 1325 | if (!ad) |
| @@ -1651,30 +1328,12 @@ static void *as_init_queue(request_queue_t *q, elevator_t *e) | |||
| 1651 | 1328 | ||
| 1652 | ad->q = q; /* Identify what queue the data belongs to */ | 1329 | ad->q = q; /* Identify what queue the data belongs to */ |
| 1653 | 1330 | ||
| 1654 | ad->hash = kmalloc_node(sizeof(struct hlist_head)*AS_HASH_ENTRIES, | ||
| 1655 | GFP_KERNEL, q->node); | ||
| 1656 | if (!ad->hash) { | ||
| 1657 | kfree(ad); | ||
| 1658 | return NULL; | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, | ||
| 1662 | mempool_free_slab, arq_pool, q->node); | ||
| 1663 | if (!ad->arq_pool) { | ||
| 1664 | kfree(ad->hash); | ||
| 1665 | kfree(ad); | ||
| 1666 | return NULL; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | /* anticipatory scheduling helpers */ | 1331 | /* anticipatory scheduling helpers */ |
| 1670 | ad->antic_timer.function = as_antic_timeout; | 1332 | ad->antic_timer.function = as_antic_timeout; |
| 1671 | ad->antic_timer.data = (unsigned long)q; | 1333 | ad->antic_timer.data = (unsigned long)q; |
| 1672 | init_timer(&ad->antic_timer); | 1334 | init_timer(&ad->antic_timer); |
| 1673 | INIT_WORK(&ad->antic_work, as_work_handler, q); | 1335 | INIT_WORK(&ad->antic_work, as_work_handler, q); |
| 1674 | 1336 | ||
| 1675 | for (i = 0; i < AS_HASH_ENTRIES; i++) | ||
| 1676 | INIT_HLIST_HEAD(&ad->hash[i]); | ||
| 1677 | |||
| 1678 | INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); | 1337 | INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); |
| 1679 | INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); | 1338 | INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); |
| 1680 | ad->sort_list[REQ_SYNC] = RB_ROOT; | 1339 | ad->sort_list[REQ_SYNC] = RB_ROOT; |
| @@ -1787,10 +1446,8 @@ static struct elevator_type iosched_as = { | |||
| 1787 | .elevator_deactivate_req_fn = as_deactivate_request, | 1446 | .elevator_deactivate_req_fn = as_deactivate_request, |
| 1788 | .elevator_queue_empty_fn = as_queue_empty, | 1447 | .elevator_queue_empty_fn = as_queue_empty, |
| 1789 | .elevator_completed_req_fn = as_completed_request, | 1448 | .elevator_completed_req_fn = as_completed_request, |
| 1790 | .elevator_former_req_fn = as_former_request, | 1449 | .elevator_former_req_fn = elv_rb_former_request, |
| 1791 | .elevator_latter_req_fn = as_latter_request, | 1450 | .elevator_latter_req_fn = elv_rb_latter_request, |
| 1792 | .elevator_set_req_fn = as_set_request, | ||
| 1793 | .elevator_put_req_fn = as_put_request, | ||
| 1794 | .elevator_may_queue_fn = as_may_queue, | 1451 | .elevator_may_queue_fn = as_may_queue, |
| 1795 | .elevator_init_fn = as_init_queue, | 1452 | .elevator_init_fn = as_init_queue, |
| 1796 | .elevator_exit_fn = as_exit_queue, | 1453 | .elevator_exit_fn = as_exit_queue, |
| @@ -1806,11 +1463,6 @@ static int __init as_init(void) | |||
| 1806 | { | 1463 | { |
| 1807 | int ret; | 1464 | int ret; |
| 1808 | 1465 | ||
| 1809 | arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq), | ||
| 1810 | 0, 0, NULL, NULL); | ||
| 1811 | if (!arq_pool) | ||
| 1812 | return -ENOMEM; | ||
| 1813 | |||
| 1814 | ret = elv_register(&iosched_as); | 1466 | ret = elv_register(&iosched_as); |
| 1815 | if (!ret) { | 1467 | if (!ret) { |
| 1816 | /* | 1468 | /* |
| @@ -1822,7 +1474,6 @@ static int __init as_init(void) | |||
| 1822 | return 0; | 1474 | return 0; |
| 1823 | } | 1475 | } |
| 1824 | 1476 | ||
| 1825 | kmem_cache_destroy(arq_pool); | ||
| 1826 | return ret; | 1477 | return ret; |
| 1827 | } | 1478 | } |
| 1828 | 1479 | ||
| @@ -1833,10 +1484,9 @@ static void __exit as_exit(void) | |||
| 1833 | ioc_gone = &all_gone; | 1484 | ioc_gone = &all_gone; |
| 1834 | /* ioc_gone's update must be visible before reading ioc_count */ | 1485 | /* ioc_gone's update must be visible before reading ioc_count */ |
| 1835 | smp_wmb(); | 1486 | smp_wmb(); |
| 1836 | if (atomic_read(&ioc_count)) | 1487 | if (elv_ioc_count_read(ioc_count)) |
| 1837 | wait_for_completion(ioc_gone); | 1488 | wait_for_completion(ioc_gone); |
| 1838 | synchronize_rcu(); | 1489 | synchronize_rcu(); |
| 1839 | kmem_cache_destroy(arq_pool); | ||
| 1840 | } | 1490 | } |
| 1841 | 1491 | ||
| 1842 | module_init(as_init); | 1492 | module_init(as_init); |
diff --git a/block/blktrace.c b/block/blktrace.c index 8ff33441d8a2..135593c8e45b 100644 --- a/block/blktrace.c +++ b/block/blktrace.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2006 Jens Axboe <axboe@suse.de> | 2 | * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk> |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
| @@ -69,7 +69,7 @@ static u32 ddir_act[2] __read_mostly = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK | |||
| 69 | /* | 69 | /* |
| 70 | * Bio action bits of interest | 70 | * Bio action bits of interest |
| 71 | */ | 71 | */ |
| 72 | static u32 bio_act[5] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC), 0, BLK_TC_ACT(BLK_TC_AHEAD) }; | 72 | static u32 bio_act[9] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC), 0, BLK_TC_ACT(BLK_TC_AHEAD), 0, 0, 0, BLK_TC_ACT(BLK_TC_META) }; |
| 73 | 73 | ||
| 74 | /* | 74 | /* |
| 75 | * More could be added as needed, taking care to increment the decrementer | 75 | * More could be added as needed, taking care to increment the decrementer |
| @@ -81,6 +81,8 @@ static u32 bio_act[5] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_AC | |||
| 81 | (((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1)) | 81 | (((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1)) |
| 82 | #define trace_ahead_bit(rw) \ | 82 | #define trace_ahead_bit(rw) \ |
| 83 | (((rw) & (1 << BIO_RW_AHEAD)) << (2 - BIO_RW_AHEAD)) | 83 | (((rw) & (1 << BIO_RW_AHEAD)) << (2 - BIO_RW_AHEAD)) |
| 84 | #define trace_meta_bit(rw) \ | ||
| 85 | (((rw) & (1 << BIO_RW_META)) >> (BIO_RW_META - 3)) | ||
| 84 | 86 | ||
| 85 | /* | 87 | /* |
| 86 | * The worker for the various blk_add_trace*() types. Fills out a | 88 | * The worker for the various blk_add_trace*() types. Fills out a |
| @@ -103,6 +105,7 @@ void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, | |||
| 103 | what |= bio_act[trace_barrier_bit(rw)]; | 105 | what |= bio_act[trace_barrier_bit(rw)]; |
| 104 | what |= bio_act[trace_sync_bit(rw)]; | 106 | what |= bio_act[trace_sync_bit(rw)]; |
| 105 | what |= bio_act[trace_ahead_bit(rw)]; | 107 | what |= bio_act[trace_ahead_bit(rw)]; |
| 108 | what |= bio_act[trace_meta_bit(rw)]; | ||
| 106 | 109 | ||
| 107 | pid = tsk->pid; | 110 | pid = tsk->pid; |
| 108 | if (unlikely(act_log_check(bt, what, sector, pid))) | 111 | if (unlikely(act_log_check(bt, what, sector, pid))) |
| @@ -473,6 +476,9 @@ static void blk_check_time(unsigned long long *t) | |||
| 473 | *t -= (a + b) / 2; | 476 | *t -= (a + b) / 2; |
| 474 | } | 477 | } |
| 475 | 478 | ||
| 479 | /* | ||
| 480 | * calibrate our inter-CPU timings | ||
| 481 | */ | ||
| 476 | static void blk_trace_check_cpu_time(void *data) | 482 | static void blk_trace_check_cpu_time(void *data) |
| 477 | { | 483 | { |
| 478 | unsigned long long *t; | 484 | unsigned long long *t; |
| @@ -490,20 +496,6 @@ static void blk_trace_check_cpu_time(void *data) | |||
| 490 | put_cpu(); | 496 | put_cpu(); |
| 491 | } | 497 | } |
| 492 | 498 | ||
| 493 | /* | ||
| 494 | * Call blk_trace_check_cpu_time() on each CPU to calibrate our inter-CPU | ||
| 495 | * timings | ||
| 496 | */ | ||
| 497 | static void blk_trace_calibrate_offsets(void) | ||
| 498 | { | ||
| 499 | unsigned long flags; | ||
| 500 | |||
| 501 | smp_call_function(blk_trace_check_cpu_time, NULL, 1, 1); | ||
| 502 | local_irq_save(flags); | ||
| 503 | blk_trace_check_cpu_time(NULL); | ||
| 504 | local_irq_restore(flags); | ||
| 505 | } | ||
| 506 | |||
| 507 | static void blk_trace_set_ht_offsets(void) | 499 | static void blk_trace_set_ht_offsets(void) |
| 508 | { | 500 | { |
| 509 | #if defined(CONFIG_SCHED_SMT) | 501 | #if defined(CONFIG_SCHED_SMT) |
| @@ -532,7 +524,7 @@ static void blk_trace_set_ht_offsets(void) | |||
| 532 | static __init int blk_trace_init(void) | 524 | static __init int blk_trace_init(void) |
| 533 | { | 525 | { |
| 534 | mutex_init(&blk_tree_mutex); | 526 | mutex_init(&blk_tree_mutex); |
| 535 | blk_trace_calibrate_offsets(); | 527 | on_each_cpu(blk_trace_check_cpu_time, NULL, 1, 1); |
| 536 | blk_trace_set_ht_offsets(); | 528 | blk_trace_set_ht_offsets(); |
| 537 | 529 | ||
| 538 | return 0; | 530 | return 0; |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3a3aee08ec5f..99116e2a310a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * Based on ideas from a previously unfinished io | 4 | * Based on ideas from a previously unfinished io |
| 5 | * scheduler (round robin per-process disk scheduling) and Andrea Arcangeli. | 5 | * scheduler (round robin per-process disk scheduling) and Andrea Arcangeli. |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2003 Jens Axboe <axboe@suse.de> | 7 | * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk> |
| 8 | */ | 8 | */ |
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
| @@ -17,7 +17,6 @@ | |||
| 17 | * tunables | 17 | * tunables |
| 18 | */ | 18 | */ |
| 19 | static const int cfq_quantum = 4; /* max queue in one round of service */ | 19 | static const int cfq_quantum = 4; /* max queue in one round of service */ |
| 20 | static const int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ | ||
| 21 | static const int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; | 20 | static const int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; |
| 22 | static const int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ | 21 | static const int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ |
| 23 | static const int cfq_back_penalty = 2; /* penalty of a backwards seek */ | 22 | static const int cfq_back_penalty = 2; /* penalty of a backwards seek */ |
| @@ -32,8 +31,6 @@ static int cfq_slice_idle = HZ / 125; | |||
| 32 | 31 | ||
| 33 | #define CFQ_KEY_ASYNC (0) | 32 | #define CFQ_KEY_ASYNC (0) |
| 34 | 33 | ||
| 35 | static DEFINE_SPINLOCK(cfq_exit_lock); | ||
| 36 | |||
| 37 | /* | 34 | /* |
| 38 | * for the hash of cfqq inside the cfqd | 35 | * for the hash of cfqq inside the cfqd |
| 39 | */ | 36 | */ |
| @@ -41,37 +38,19 @@ static DEFINE_SPINLOCK(cfq_exit_lock); | |||
| 41 | #define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT) | 38 | #define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT) |
| 42 | #define list_entry_qhash(entry) hlist_entry((entry), struct cfq_queue, cfq_hash) | 39 | #define list_entry_qhash(entry) hlist_entry((entry), struct cfq_queue, cfq_hash) |
| 43 | 40 | ||
| 44 | /* | ||
| 45 | * for the hash of crq inside the cfqq | ||
| 46 | */ | ||
| 47 | #define CFQ_MHASH_SHIFT 6 | ||
| 48 | #define CFQ_MHASH_BLOCK(sec) ((sec) >> 3) | ||
| 49 | #define CFQ_MHASH_ENTRIES (1 << CFQ_MHASH_SHIFT) | ||
| 50 | #define CFQ_MHASH_FN(sec) hash_long(CFQ_MHASH_BLOCK(sec), CFQ_MHASH_SHIFT) | ||
| 51 | #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) | ||
| 52 | #define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash) | ||
| 53 | |||
| 54 | #define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) | 41 | #define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) |
| 55 | #define list_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) | ||
| 56 | 42 | ||
| 57 | #define RQ_DATA(rq) (rq)->elevator_private | 43 | #define RQ_CIC(rq) ((struct cfq_io_context*)(rq)->elevator_private) |
| 44 | #define RQ_CFQQ(rq) ((rq)->elevator_private2) | ||
| 58 | 45 | ||
| 59 | /* | ||
| 60 | * rb-tree defines | ||
| 61 | */ | ||
| 62 | #define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) | ||
| 63 | #define rq_rb_key(rq) (rq)->sector | ||
| 64 | |||
| 65 | static kmem_cache_t *crq_pool; | ||
| 66 | static kmem_cache_t *cfq_pool; | 46 | static kmem_cache_t *cfq_pool; |
| 67 | static kmem_cache_t *cfq_ioc_pool; | 47 | static kmem_cache_t *cfq_ioc_pool; |
| 68 | 48 | ||
| 69 | static atomic_t ioc_count = ATOMIC_INIT(0); | 49 | static DEFINE_PER_CPU(unsigned long, ioc_count); |
| 70 | static struct completion *ioc_gone; | 50 | static struct completion *ioc_gone; |
| 71 | 51 | ||
| 72 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR | 52 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR |
| 73 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) | 53 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) |
| 74 | #define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) | ||
| 75 | #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) | 54 | #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) |
| 76 | 55 | ||
| 77 | #define ASYNC (0) | 56 | #define ASYNC (0) |
| @@ -103,29 +82,14 @@ struct cfq_data { | |||
| 103 | unsigned int busy_queues; | 82 | unsigned int busy_queues; |
| 104 | 83 | ||
| 105 | /* | 84 | /* |
| 106 | * non-ordered list of empty cfqq's | ||
| 107 | */ | ||
| 108 | struct list_head empty_list; | ||
| 109 | |||
| 110 | /* | ||
| 111 | * cfqq lookup hash | 85 | * cfqq lookup hash |
| 112 | */ | 86 | */ |
| 113 | struct hlist_head *cfq_hash; | 87 | struct hlist_head *cfq_hash; |
| 114 | 88 | ||
| 115 | /* | ||
| 116 | * global crq hash for all queues | ||
| 117 | */ | ||
| 118 | struct hlist_head *crq_hash; | ||
| 119 | |||
| 120 | mempool_t *crq_pool; | ||
| 121 | |||
| 122 | int rq_in_driver; | 89 | int rq_in_driver; |
| 123 | int hw_tag; | 90 | int hw_tag; |
| 124 | 91 | ||
| 125 | /* | 92 | /* |
| 126 | * schedule slice state info | ||
| 127 | */ | ||
| 128 | /* | ||
| 129 | * idle window management | 93 | * idle window management |
| 130 | */ | 94 | */ |
| 131 | struct timer_list idle_slice_timer; | 95 | struct timer_list idle_slice_timer; |
| @@ -141,13 +105,10 @@ struct cfq_data { | |||
| 141 | sector_t last_sector; | 105 | sector_t last_sector; |
| 142 | unsigned long last_end_request; | 106 | unsigned long last_end_request; |
| 143 | 107 | ||
| 144 | unsigned int rq_starved; | ||
| 145 | |||
| 146 | /* | 108 | /* |
| 147 | * tunables, see top of file | 109 | * tunables, see top of file |
| 148 | */ | 110 | */ |
| 149 | unsigned int cfq_quantum; | 111 | unsigned int cfq_quantum; |
| 150 | unsigned int cfq_queued; | ||
| 151 | unsigned int cfq_fifo_expire[2]; | 112 | unsigned int cfq_fifo_expire[2]; |
| 152 | unsigned int cfq_back_penalty; | 113 | unsigned int cfq_back_penalty; |
| 153 | unsigned int cfq_back_max; | 114 | unsigned int cfq_back_max; |
| @@ -170,23 +131,24 @@ struct cfq_queue { | |||
| 170 | struct hlist_node cfq_hash; | 131 | struct hlist_node cfq_hash; |
| 171 | /* hash key */ | 132 | /* hash key */ |
| 172 | unsigned int key; | 133 | unsigned int key; |
| 173 | /* on either rr or empty list of cfqd */ | 134 | /* member of the rr/busy/cur/idle cfqd list */ |
| 174 | struct list_head cfq_list; | 135 | struct list_head cfq_list; |
| 175 | /* sorted list of pending requests */ | 136 | /* sorted list of pending requests */ |
| 176 | struct rb_root sort_list; | 137 | struct rb_root sort_list; |
| 177 | /* if fifo isn't expired, next request to serve */ | 138 | /* if fifo isn't expired, next request to serve */ |
| 178 | struct cfq_rq *next_crq; | 139 | struct request *next_rq; |
| 179 | /* requests queued in sort_list */ | 140 | /* requests queued in sort_list */ |
| 180 | int queued[2]; | 141 | int queued[2]; |
| 181 | /* currently allocated requests */ | 142 | /* currently allocated requests */ |
| 182 | int allocated[2]; | 143 | int allocated[2]; |
| 144 | /* pending metadata requests */ | ||
| 145 | int meta_pending; | ||
| 183 | /* fifo list of requests in sort_list */ | 146 | /* fifo list of requests in sort_list */ |
| 184 | struct list_head fifo; | 147 | struct list_head fifo; |
| 185 | 148 | ||
| 186 | unsigned long slice_start; | 149 | unsigned long slice_start; |
| 187 | unsigned long slice_end; | 150 | unsigned long slice_end; |
| 188 | unsigned long slice_left; | 151 | unsigned long slice_left; |
| 189 | unsigned long service_last; | ||
| 190 | 152 | ||
| 191 | /* number of requests that are on the dispatch list */ | 153 | /* number of requests that are on the dispatch list */ |
| 192 | int on_dispatch[2]; | 154 | int on_dispatch[2]; |
| @@ -199,18 +161,6 @@ struct cfq_queue { | |||
| 199 | unsigned int flags; | 161 | unsigned int flags; |
| 200 | }; | 162 | }; |
| 201 | 163 | ||
| 202 | struct cfq_rq { | ||
| 203 | struct rb_node rb_node; | ||
| 204 | sector_t rb_key; | ||
| 205 | struct request *request; | ||
| 206 | struct hlist_node hash; | ||
| 207 | |||
| 208 | struct cfq_queue *cfq_queue; | ||
| 209 | struct cfq_io_context *io_context; | ||
| 210 | |||
| 211 | unsigned int crq_flags; | ||
| 212 | }; | ||
| 213 | |||
| 214 | enum cfqq_state_flags { | 164 | enum cfqq_state_flags { |
| 215 | CFQ_CFQQ_FLAG_on_rr = 0, | 165 | CFQ_CFQQ_FLAG_on_rr = 0, |
| 216 | CFQ_CFQQ_FLAG_wait_request, | 166 | CFQ_CFQQ_FLAG_wait_request, |
| @@ -220,6 +170,7 @@ enum cfqq_state_flags { | |||
| 220 | CFQ_CFQQ_FLAG_fifo_expire, | 170 | CFQ_CFQQ_FLAG_fifo_expire, |
| 221 | CFQ_CFQQ_FLAG_idle_window, | 171 | CFQ_CFQQ_FLAG_idle_window, |
| 222 | CFQ_CFQQ_FLAG_prio_changed, | 172 | CFQ_CFQQ_FLAG_prio_changed, |
| 173 | CFQ_CFQQ_FLAG_queue_new, | ||
| 223 | }; | 174 | }; |
| 224 | 175 | ||
| 225 | #define CFQ_CFQQ_FNS(name) \ | 176 | #define CFQ_CFQQ_FNS(name) \ |
| @@ -244,70 +195,14 @@ CFQ_CFQQ_FNS(must_dispatch); | |||
| 244 | CFQ_CFQQ_FNS(fifo_expire); | 195 | CFQ_CFQQ_FNS(fifo_expire); |
| 245 | CFQ_CFQQ_FNS(idle_window); | 196 | CFQ_CFQQ_FNS(idle_window); |
| 246 | CFQ_CFQQ_FNS(prio_changed); | 197 | CFQ_CFQQ_FNS(prio_changed); |
| 198 | CFQ_CFQQ_FNS(queue_new); | ||
| 247 | #undef CFQ_CFQQ_FNS | 199 | #undef CFQ_CFQQ_FNS |
| 248 | 200 | ||
| 249 | enum cfq_rq_state_flags { | ||
| 250 | CFQ_CRQ_FLAG_is_sync = 0, | ||
| 251 | }; | ||
| 252 | |||
| 253 | #define CFQ_CRQ_FNS(name) \ | ||
| 254 | static inline void cfq_mark_crq_##name(struct cfq_rq *crq) \ | ||
| 255 | { \ | ||
| 256 | crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name); \ | ||
| 257 | } \ | ||
| 258 | static inline void cfq_clear_crq_##name(struct cfq_rq *crq) \ | ||
| 259 | { \ | ||
| 260 | crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name); \ | ||
| 261 | } \ | ||
| 262 | static inline int cfq_crq_##name(const struct cfq_rq *crq) \ | ||
| 263 | { \ | ||
| 264 | return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \ | ||
| 265 | } | ||
| 266 | |||
| 267 | CFQ_CRQ_FNS(is_sync); | ||
| 268 | #undef CFQ_CRQ_FNS | ||
| 269 | |||
| 270 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); | 201 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); |
| 271 | static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); | 202 | static void cfq_dispatch_insert(request_queue_t *, struct request *); |
| 272 | static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask); | 203 | static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask); |
| 273 | 204 | ||
| 274 | /* | 205 | /* |
| 275 | * lots of deadline iosched dupes, can be abstracted later... | ||
| 276 | */ | ||
| 277 | static inline void cfq_del_crq_hash(struct cfq_rq *crq) | ||
| 278 | { | ||
| 279 | hlist_del_init(&crq->hash); | ||
| 280 | } | ||
| 281 | |||
| 282 | static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq) | ||
| 283 | { | ||
| 284 | const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request)); | ||
| 285 | |||
| 286 | hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]); | ||
| 287 | } | ||
| 288 | |||
| 289 | static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) | ||
| 290 | { | ||
| 291 | struct hlist_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)]; | ||
| 292 | struct hlist_node *entry, *next; | ||
| 293 | |||
| 294 | hlist_for_each_safe(entry, next, hash_list) { | ||
| 295 | struct cfq_rq *crq = list_entry_hash(entry); | ||
| 296 | struct request *__rq = crq->request; | ||
| 297 | |||
| 298 | if (!rq_mergeable(__rq)) { | ||
| 299 | cfq_del_crq_hash(crq); | ||
| 300 | continue; | ||
| 301 | } | ||
| 302 | |||
| 303 | if (rq_hash_key(__rq) == offset) | ||
| 304 | return __rq; | ||
| 305 | } | ||
| 306 | |||
| 307 | return NULL; | ||
| 308 | } | ||
| 309 | |||
| 310 | /* | ||
| 311 | * scheduler run of queue, if there are requests pending and no one in the | 206 | * scheduler run of queue, if there are requests pending and no one in the |
| 312 | * driver that will restart queueing | 207 | * driver that will restart queueing |
| 313 | */ | 208 | */ |
| @@ -333,12 +228,12 @@ static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) | |||
| 333 | } | 228 | } |
| 334 | 229 | ||
| 335 | /* | 230 | /* |
| 336 | * Lifted from AS - choose which of crq1 and crq2 that is best served now. | 231 | * Lifted from AS - choose which of rq1 and rq2 that is best served now. |
| 337 | * We choose the request that is closest to the head right now. Distance | 232 | * We choose the request that is closest to the head right now. Distance |
| 338 | * behind the head is penalized and only allowed to a certain extent. | 233 | * behind the head is penalized and only allowed to a certain extent. |
| 339 | */ | 234 | */ |
| 340 | static struct cfq_rq * | 235 | static struct request * |
| 341 | cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | 236 | cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2) |
| 342 | { | 237 | { |
| 343 | sector_t last, s1, s2, d1 = 0, d2 = 0; | 238 | sector_t last, s1, s2, d1 = 0, d2 = 0; |
| 344 | unsigned long back_max; | 239 | unsigned long back_max; |
| @@ -346,18 +241,22 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | |||
| 346 | #define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */ | 241 | #define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */ |
| 347 | unsigned wrap = 0; /* bit mask: requests behind the disk head? */ | 242 | unsigned wrap = 0; /* bit mask: requests behind the disk head? */ |
| 348 | 243 | ||
| 349 | if (crq1 == NULL || crq1 == crq2) | 244 | if (rq1 == NULL || rq1 == rq2) |
| 350 | return crq2; | 245 | return rq2; |
| 351 | if (crq2 == NULL) | 246 | if (rq2 == NULL) |
| 352 | return crq1; | 247 | return rq1; |
| 353 | 248 | ||
| 354 | if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2)) | 249 | if (rq_is_sync(rq1) && !rq_is_sync(rq2)) |
| 355 | return crq1; | 250 | return rq1; |
| 356 | else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1)) | 251 | else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) |
| 357 | return crq2; | 252 | return rq2; |
| 253 | if (rq_is_meta(rq1) && !rq_is_meta(rq2)) | ||
| 254 | return rq1; | ||
| 255 | else if (rq_is_meta(rq2) && !rq_is_meta(rq1)) | ||
| 256 | return rq2; | ||
| 358 | 257 | ||
| 359 | s1 = crq1->request->sector; | 258 | s1 = rq1->sector; |
| 360 | s2 = crq2->request->sector; | 259 | s2 = rq2->sector; |
| 361 | 260 | ||
| 362 | last = cfqd->last_sector; | 261 | last = cfqd->last_sector; |
| 363 | 262 | ||
| @@ -392,23 +291,23 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | |||
| 392 | * check two variables for all permutations: --> faster! | 291 | * check two variables for all permutations: --> faster! |
| 393 | */ | 292 | */ |
| 394 | switch (wrap) { | 293 | switch (wrap) { |
| 395 | case 0: /* common case for CFQ: crq1 and crq2 not wrapped */ | 294 | case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ |
| 396 | if (d1 < d2) | 295 | if (d1 < d2) |
| 397 | return crq1; | 296 | return rq1; |
| 398 | else if (d2 < d1) | 297 | else if (d2 < d1) |
| 399 | return crq2; | 298 | return rq2; |
| 400 | else { | 299 | else { |
| 401 | if (s1 >= s2) | 300 | if (s1 >= s2) |
| 402 | return crq1; | 301 | return rq1; |
| 403 | else | 302 | else |
| 404 | return crq2; | 303 | return rq2; |
| 405 | } | 304 | } |
| 406 | 305 | ||
| 407 | case CFQ_RQ2_WRAP: | 306 | case CFQ_RQ2_WRAP: |
| 408 | return crq1; | 307 | return rq1; |
| 409 | case CFQ_RQ1_WRAP: | 308 | case CFQ_RQ1_WRAP: |
| 410 | return crq2; | 309 | return rq2; |
| 411 | case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */ | 310 | case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both rqs wrapped */ |
| 412 | default: | 311 | default: |
| 413 | /* | 312 | /* |
| 414 | * Since both rqs are wrapped, | 313 | * Since both rqs are wrapped, |
| @@ -417,50 +316,43 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | |||
| 417 | * since back seek takes more time than forward. | 316 | * since back seek takes more time than forward. |
| 418 | */ | 317 | */ |
| 419 | if (s1 <= s2) | 318 | if (s1 <= s2) |
| 420 | return crq1; | 319 | return rq1; |
| 421 | else | 320 | else |
| 422 | return crq2; | 321 | return rq2; |
| 423 | } | 322 | } |
| 424 | } | 323 | } |
| 425 | 324 | ||
| 426 | /* | 325 | /* |
| 427 | * would be nice to take fifo expire time into account as well | 326 | * would be nice to take fifo expire time into account as well |
| 428 | */ | 327 | */ |
| 429 | static struct cfq_rq * | 328 | static struct request * |
| 430 | cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 329 | cfq_find_next_rq(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
| 431 | struct cfq_rq *last) | 330 | struct request *last) |
| 432 | { | 331 | { |
| 433 | struct cfq_rq *crq_next = NULL, *crq_prev = NULL; | 332 | struct rb_node *rbnext = rb_next(&last->rb_node); |
| 434 | struct rb_node *rbnext, *rbprev; | 333 | struct rb_node *rbprev = rb_prev(&last->rb_node); |
| 435 | 334 | struct request *next = NULL, *prev = NULL; | |
| 436 | if (!(rbnext = rb_next(&last->rb_node))) { | ||
| 437 | rbnext = rb_first(&cfqq->sort_list); | ||
| 438 | if (rbnext == &last->rb_node) | ||
| 439 | rbnext = NULL; | ||
| 440 | } | ||
| 441 | 335 | ||
| 442 | rbprev = rb_prev(&last->rb_node); | 336 | BUG_ON(RB_EMPTY_NODE(&last->rb_node)); |
| 443 | 337 | ||
| 444 | if (rbprev) | 338 | if (rbprev) |
| 445 | crq_prev = rb_entry_crq(rbprev); | 339 | prev = rb_entry_rq(rbprev); |
| 446 | if (rbnext) | ||
| 447 | crq_next = rb_entry_crq(rbnext); | ||
| 448 | |||
| 449 | return cfq_choose_req(cfqd, crq_next, crq_prev); | ||
| 450 | } | ||
| 451 | 340 | ||
| 452 | static void cfq_update_next_crq(struct cfq_rq *crq) | 341 | if (rbnext) |
| 453 | { | 342 | next = rb_entry_rq(rbnext); |
| 454 | struct cfq_queue *cfqq = crq->cfq_queue; | 343 | else { |
| 344 | rbnext = rb_first(&cfqq->sort_list); | ||
| 345 | if (rbnext && rbnext != &last->rb_node) | ||
| 346 | next = rb_entry_rq(rbnext); | ||
| 347 | } | ||
| 455 | 348 | ||
| 456 | if (cfqq->next_crq == crq) | 349 | return cfq_choose_req(cfqd, next, prev); |
| 457 | cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq); | ||
| 458 | } | 350 | } |
| 459 | 351 | ||
| 460 | static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) | 352 | static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) |
| 461 | { | 353 | { |
| 462 | struct cfq_data *cfqd = cfqq->cfqd; | 354 | struct cfq_data *cfqd = cfqq->cfqd; |
| 463 | struct list_head *list, *entry; | 355 | struct list_head *list; |
| 464 | 356 | ||
| 465 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); | 357 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); |
| 466 | 358 | ||
| @@ -485,31 +377,26 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) | |||
| 485 | } | 377 | } |
| 486 | 378 | ||
| 487 | /* | 379 | /* |
| 488 | * if queue was preempted, just add to front to be fair. busy_rr | 380 | * If this queue was preempted or is new (never been serviced), let |
| 489 | * isn't sorted, but insert at the back for fairness. | 381 | * it be added first for fairness but beind other new queues. |
| 382 | * Otherwise, just add to the back of the list. | ||
| 490 | */ | 383 | */ |
| 491 | if (preempted || list == &cfqd->busy_rr) { | 384 | if (preempted || cfq_cfqq_queue_new(cfqq)) { |
| 492 | if (preempted) | 385 | struct list_head *n = list; |
| 493 | list = list->prev; | 386 | struct cfq_queue *__cfqq; |
| 494 | 387 | ||
| 495 | list_add_tail(&cfqq->cfq_list, list); | 388 | while (n->next != list) { |
| 496 | return; | 389 | __cfqq = list_entry_cfqq(n->next); |
| 497 | } | 390 | if (!cfq_cfqq_queue_new(__cfqq)) |
| 391 | break; | ||
| 498 | 392 | ||
| 499 | /* | 393 | n = n->next; |
| 500 | * sort by when queue was last serviced | 394 | } |
| 501 | */ | ||
| 502 | entry = list; | ||
| 503 | while ((entry = entry->prev) != list) { | ||
| 504 | struct cfq_queue *__cfqq = list_entry_cfqq(entry); | ||
| 505 | 395 | ||
| 506 | if (!__cfqq->service_last) | 396 | list = n; |
| 507 | break; | ||
| 508 | if (time_before(__cfqq->service_last, cfqq->service_last)) | ||
| 509 | break; | ||
| 510 | } | 397 | } |
| 511 | 398 | ||
| 512 | list_add(&cfqq->cfq_list, entry); | 399 | list_add_tail(&cfqq->cfq_list, list); |
| 513 | } | 400 | } |
| 514 | 401 | ||
| 515 | /* | 402 | /* |
| @@ -531,7 +418,7 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 531 | { | 418 | { |
| 532 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); | 419 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); |
| 533 | cfq_clear_cfqq_on_rr(cfqq); | 420 | cfq_clear_cfqq_on_rr(cfqq); |
| 534 | list_move(&cfqq->cfq_list, &cfqd->empty_list); | 421 | list_del_init(&cfqq->cfq_list); |
| 535 | 422 | ||
| 536 | BUG_ON(!cfqd->busy_queues); | 423 | BUG_ON(!cfqd->busy_queues); |
| 537 | cfqd->busy_queues--; | 424 | cfqd->busy_queues--; |
| @@ -540,81 +427,43 @@ cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 540 | /* | 427 | /* |
| 541 | * rb tree support functions | 428 | * rb tree support functions |
| 542 | */ | 429 | */ |
| 543 | static inline void cfq_del_crq_rb(struct cfq_rq *crq) | 430 | static inline void cfq_del_rq_rb(struct request *rq) |
| 544 | { | 431 | { |
| 545 | struct cfq_queue *cfqq = crq->cfq_queue; | 432 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
| 546 | struct cfq_data *cfqd = cfqq->cfqd; | 433 | struct cfq_data *cfqd = cfqq->cfqd; |
| 547 | const int sync = cfq_crq_is_sync(crq); | 434 | const int sync = rq_is_sync(rq); |
| 548 | 435 | ||
| 549 | BUG_ON(!cfqq->queued[sync]); | 436 | BUG_ON(!cfqq->queued[sync]); |
| 550 | cfqq->queued[sync]--; | 437 | cfqq->queued[sync]--; |
| 551 | 438 | ||
| 552 | cfq_update_next_crq(crq); | 439 | elv_rb_del(&cfqq->sort_list, rq); |
| 553 | |||
| 554 | rb_erase(&crq->rb_node, &cfqq->sort_list); | ||
| 555 | 440 | ||
| 556 | if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list)) | 441 | if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list)) |
| 557 | cfq_del_cfqq_rr(cfqd, cfqq); | 442 | cfq_del_cfqq_rr(cfqd, cfqq); |
| 558 | } | 443 | } |
| 559 | 444 | ||
| 560 | static struct cfq_rq * | 445 | static void cfq_add_rq_rb(struct request *rq) |
| 561 | __cfq_add_crq_rb(struct cfq_rq *crq) | ||
| 562 | { | 446 | { |
| 563 | struct rb_node **p = &crq->cfq_queue->sort_list.rb_node; | 447 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
| 564 | struct rb_node *parent = NULL; | ||
| 565 | struct cfq_rq *__crq; | ||
| 566 | |||
| 567 | while (*p) { | ||
| 568 | parent = *p; | ||
| 569 | __crq = rb_entry_crq(parent); | ||
| 570 | |||
| 571 | if (crq->rb_key < __crq->rb_key) | ||
| 572 | p = &(*p)->rb_left; | ||
| 573 | else if (crq->rb_key > __crq->rb_key) | ||
| 574 | p = &(*p)->rb_right; | ||
| 575 | else | ||
| 576 | return __crq; | ||
| 577 | } | ||
| 578 | |||
| 579 | rb_link_node(&crq->rb_node, parent, p); | ||
| 580 | return NULL; | ||
| 581 | } | ||
| 582 | |||
| 583 | static void cfq_add_crq_rb(struct cfq_rq *crq) | ||
| 584 | { | ||
| 585 | struct cfq_queue *cfqq = crq->cfq_queue; | ||
| 586 | struct cfq_data *cfqd = cfqq->cfqd; | 448 | struct cfq_data *cfqd = cfqq->cfqd; |
| 587 | struct request *rq = crq->request; | 449 | struct request *__alias; |
| 588 | struct cfq_rq *__alias; | ||
| 589 | 450 | ||
| 590 | crq->rb_key = rq_rb_key(rq); | 451 | cfqq->queued[rq_is_sync(rq)]++; |
| 591 | cfqq->queued[cfq_crq_is_sync(crq)]++; | ||
| 592 | 452 | ||
| 593 | /* | 453 | /* |
| 594 | * looks a little odd, but the first insert might return an alias. | 454 | * looks a little odd, but the first insert might return an alias. |
| 595 | * if that happens, put the alias on the dispatch list | 455 | * if that happens, put the alias on the dispatch list |
| 596 | */ | 456 | */ |
| 597 | while ((__alias = __cfq_add_crq_rb(crq)) != NULL) | 457 | while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL) |
| 598 | cfq_dispatch_insert(cfqd->queue, __alias); | 458 | cfq_dispatch_insert(cfqd->queue, __alias); |
| 599 | |||
| 600 | rb_insert_color(&crq->rb_node, &cfqq->sort_list); | ||
| 601 | |||
| 602 | if (!cfq_cfqq_on_rr(cfqq)) | ||
| 603 | cfq_add_cfqq_rr(cfqd, cfqq); | ||
| 604 | |||
| 605 | /* | ||
| 606 | * check if this request is a better next-serve candidate | ||
| 607 | */ | ||
| 608 | cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); | ||
| 609 | } | 459 | } |
| 610 | 460 | ||
| 611 | static inline void | 461 | static inline void |
| 612 | cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) | 462 | cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq) |
| 613 | { | 463 | { |
| 614 | rb_erase(&crq->rb_node, &cfqq->sort_list); | 464 | elv_rb_del(&cfqq->sort_list, rq); |
| 615 | cfqq->queued[cfq_crq_is_sync(crq)]--; | 465 | cfqq->queued[rq_is_sync(rq)]--; |
| 616 | 466 | cfq_add_rq_rb(rq); | |
| 617 | cfq_add_crq_rb(crq); | ||
| 618 | } | 467 | } |
| 619 | 468 | ||
| 620 | static struct request * | 469 | static struct request * |
| @@ -623,27 +472,14 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio) | |||
| 623 | struct task_struct *tsk = current; | 472 | struct task_struct *tsk = current; |
| 624 | pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio)); | 473 | pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio)); |
| 625 | struct cfq_queue *cfqq; | 474 | struct cfq_queue *cfqq; |
| 626 | struct rb_node *n; | ||
| 627 | sector_t sector; | ||
| 628 | 475 | ||
| 629 | cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio); | 476 | cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio); |
| 630 | if (!cfqq) | 477 | if (cfqq) { |
| 631 | goto out; | 478 | sector_t sector = bio->bi_sector + bio_sectors(bio); |
| 632 | |||
| 633 | sector = bio->bi_sector + bio_sectors(bio); | ||
| 634 | n = cfqq->sort_list.rb_node; | ||
| 635 | while (n) { | ||
| 636 | struct cfq_rq *crq = rb_entry_crq(n); | ||
| 637 | 479 | ||
| 638 | if (sector < crq->rb_key) | 480 | return elv_rb_find(&cfqq->sort_list, sector); |
| 639 | n = n->rb_left; | ||
| 640 | else if (sector > crq->rb_key) | ||
| 641 | n = n->rb_right; | ||
| 642 | else | ||
| 643 | return crq->request; | ||
| 644 | } | 481 | } |
| 645 | 482 | ||
| 646 | out: | ||
| 647 | return NULL; | 483 | return NULL; |
| 648 | } | 484 | } |
| 649 | 485 | ||
| @@ -673,11 +509,18 @@ static void cfq_deactivate_request(request_queue_t *q, struct request *rq) | |||
| 673 | 509 | ||
| 674 | static void cfq_remove_request(struct request *rq) | 510 | static void cfq_remove_request(struct request *rq) |
| 675 | { | 511 | { |
| 676 | struct cfq_rq *crq = RQ_DATA(rq); | 512 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
| 513 | |||
| 514 | if (cfqq->next_rq == rq) | ||
| 515 | cfqq->next_rq = cfq_find_next_rq(cfqq->cfqd, cfqq, rq); | ||
| 677 | 516 | ||
| 678 | list_del_init(&rq->queuelist); | 517 | list_del_init(&rq->queuelist); |
| 679 | cfq_del_crq_rb(crq); | 518 | cfq_del_rq_rb(rq); |
| 680 | cfq_del_crq_hash(crq); | 519 | |
| 520 | if (rq_is_meta(rq)) { | ||
| 521 | WARN_ON(!cfqq->meta_pending); | ||
| 522 | cfqq->meta_pending--; | ||
| 523 | } | ||
| 681 | } | 524 | } |
| 682 | 525 | ||
| 683 | static int | 526 | static int |
| @@ -685,39 +528,23 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio) | |||
| 685 | { | 528 | { |
| 686 | struct cfq_data *cfqd = q->elevator->elevator_data; | 529 | struct cfq_data *cfqd = q->elevator->elevator_data; |
| 687 | struct request *__rq; | 530 | struct request *__rq; |
| 688 | int ret; | ||
| 689 | |||
| 690 | __rq = cfq_find_rq_hash(cfqd, bio->bi_sector); | ||
| 691 | if (__rq && elv_rq_merge_ok(__rq, bio)) { | ||
| 692 | ret = ELEVATOR_BACK_MERGE; | ||
| 693 | goto out; | ||
| 694 | } | ||
| 695 | 531 | ||
| 696 | __rq = cfq_find_rq_fmerge(cfqd, bio); | 532 | __rq = cfq_find_rq_fmerge(cfqd, bio); |
| 697 | if (__rq && elv_rq_merge_ok(__rq, bio)) { | 533 | if (__rq && elv_rq_merge_ok(__rq, bio)) { |
| 698 | ret = ELEVATOR_FRONT_MERGE; | 534 | *req = __rq; |
| 699 | goto out; | 535 | return ELEVATOR_FRONT_MERGE; |
| 700 | } | 536 | } |
| 701 | 537 | ||
| 702 | return ELEVATOR_NO_MERGE; | 538 | return ELEVATOR_NO_MERGE; |
| 703 | out: | ||
| 704 | *req = __rq; | ||
| 705 | return ret; | ||
| 706 | } | 539 | } |
| 707 | 540 | ||
| 708 | static void cfq_merged_request(request_queue_t *q, struct request *req) | 541 | static void cfq_merged_request(request_queue_t *q, struct request *req, |
| 542 | int type) | ||
| 709 | { | 543 | { |
| 710 | struct cfq_data *cfqd = q->elevator->elevator_data; | 544 | if (type == ELEVATOR_FRONT_MERGE) { |
| 711 | struct cfq_rq *crq = RQ_DATA(req); | 545 | struct cfq_queue *cfqq = RQ_CFQQ(req); |
| 712 | |||
| 713 | cfq_del_crq_hash(crq); | ||
| 714 | cfq_add_crq_hash(cfqd, crq); | ||
| 715 | |||
| 716 | if (rq_rb_key(req) != crq->rb_key) { | ||
| 717 | struct cfq_queue *cfqq = crq->cfq_queue; | ||
| 718 | 546 | ||
| 719 | cfq_update_next_crq(crq); | 547 | cfq_reposition_rq_rb(cfqq, req); |
| 720 | cfq_reposition_crq_rb(cfqq, crq); | ||
| 721 | } | 548 | } |
| 722 | } | 549 | } |
| 723 | 550 | ||
| @@ -725,8 +552,6 @@ static void | |||
| 725 | cfq_merged_requests(request_queue_t *q, struct request *rq, | 552 | cfq_merged_requests(request_queue_t *q, struct request *rq, |
| 726 | struct request *next) | 553 | struct request *next) |
| 727 | { | 554 | { |
| 728 | cfq_merged_request(q, rq); | ||
| 729 | |||
| 730 | /* | 555 | /* |
| 731 | * reposition in fifo if next is older than rq | 556 | * reposition in fifo if next is older than rq |
| 732 | */ | 557 | */ |
| @@ -768,13 +593,12 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 768 | if (cfq_cfqq_wait_request(cfqq)) | 593 | if (cfq_cfqq_wait_request(cfqq)) |
| 769 | del_timer(&cfqd->idle_slice_timer); | 594 | del_timer(&cfqd->idle_slice_timer); |
| 770 | 595 | ||
| 771 | if (!preempted && !cfq_cfqq_dispatched(cfqq)) { | 596 | if (!preempted && !cfq_cfqq_dispatched(cfqq)) |
| 772 | cfqq->service_last = now; | ||
| 773 | cfq_schedule_dispatch(cfqd); | 597 | cfq_schedule_dispatch(cfqd); |
| 774 | } | ||
| 775 | 598 | ||
| 776 | cfq_clear_cfqq_must_dispatch(cfqq); | 599 | cfq_clear_cfqq_must_dispatch(cfqq); |
| 777 | cfq_clear_cfqq_wait_request(cfqq); | 600 | cfq_clear_cfqq_wait_request(cfqq); |
| 601 | cfq_clear_cfqq_queue_new(cfqq); | ||
| 778 | 602 | ||
| 779 | /* | 603 | /* |
| 780 | * store what was left of this slice, if the queue idled out | 604 | * store what was left of this slice, if the queue idled out |
| @@ -868,26 +692,25 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) | |||
| 868 | { | 692 | { |
| 869 | struct cfq_queue *cfqq = NULL; | 693 | struct cfq_queue *cfqq = NULL; |
| 870 | 694 | ||
| 871 | /* | 695 | if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1) { |
| 872 | * if current list is non-empty, grab first entry. if it is empty, | 696 | /* |
| 873 | * get next prio level and grab first entry then if any are spliced | 697 | * if current list is non-empty, grab first entry. if it is |
| 874 | */ | 698 | * empty, get next prio level and grab first entry then if any |
| 875 | if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1) | 699 | * are spliced |
| 700 | */ | ||
| 876 | cfqq = list_entry_cfqq(cfqd->cur_rr.next); | 701 | cfqq = list_entry_cfqq(cfqd->cur_rr.next); |
| 877 | 702 | } else if (!list_empty(&cfqd->busy_rr)) { | |
| 878 | /* | 703 | /* |
| 879 | * If no new queues are available, check if the busy list has some | 704 | * If no new queues are available, check if the busy list has |
| 880 | * before falling back to idle io. | 705 | * some before falling back to idle io. |
| 881 | */ | 706 | */ |
| 882 | if (!cfqq && !list_empty(&cfqd->busy_rr)) | ||
| 883 | cfqq = list_entry_cfqq(cfqd->busy_rr.next); | 707 | cfqq = list_entry_cfqq(cfqd->busy_rr.next); |
| 884 | 708 | } else if (!list_empty(&cfqd->idle_rr)) { | |
| 885 | /* | 709 | /* |
| 886 | * if we have idle queues and no rt or be queues had pending | 710 | * if we have idle queues and no rt or be queues had pending |
| 887 | * requests, either allow immediate service if the grace period | 711 | * requests, either allow immediate service if the grace period |
| 888 | * has passed or arm the idle grace timer | 712 | * has passed or arm the idle grace timer |
| 889 | */ | 713 | */ |
| 890 | if (!cfqq && !list_empty(&cfqd->idle_rr)) { | ||
| 891 | unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE; | 714 | unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE; |
| 892 | 715 | ||
| 893 | if (time_after_eq(jiffies, end)) | 716 | if (time_after_eq(jiffies, end)) |
| @@ -942,16 +765,14 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 942 | return 1; | 765 | return 1; |
| 943 | } | 766 | } |
| 944 | 767 | ||
| 945 | static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq) | 768 | static void cfq_dispatch_insert(request_queue_t *q, struct request *rq) |
| 946 | { | 769 | { |
| 947 | struct cfq_data *cfqd = q->elevator->elevator_data; | 770 | struct cfq_data *cfqd = q->elevator->elevator_data; |
| 948 | struct cfq_queue *cfqq = crq->cfq_queue; | 771 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
| 949 | struct request *rq; | ||
| 950 | 772 | ||
| 951 | cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq); | 773 | cfq_remove_request(rq); |
| 952 | cfq_remove_request(crq->request); | 774 | cfqq->on_dispatch[rq_is_sync(rq)]++; |
| 953 | cfqq->on_dispatch[cfq_crq_is_sync(crq)]++; | 775 | elv_dispatch_sort(q, rq); |
| 954 | elv_dispatch_sort(q, crq->request); | ||
| 955 | 776 | ||
| 956 | rq = list_entry(q->queue_head.prev, struct request, queuelist); | 777 | rq = list_entry(q->queue_head.prev, struct request, queuelist); |
| 957 | cfqd->last_sector = rq->sector + rq->nr_sectors; | 778 | cfqd->last_sector = rq->sector + rq->nr_sectors; |
| @@ -960,24 +781,23 @@ static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq) | |||
| 960 | /* | 781 | /* |
| 961 | * return expired entry, or NULL to just start from scratch in rbtree | 782 | * return expired entry, or NULL to just start from scratch in rbtree |
| 962 | */ | 783 | */ |
| 963 | static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) | 784 | static inline struct request *cfq_check_fifo(struct cfq_queue *cfqq) |
| 964 | { | 785 | { |
| 965 | struct cfq_data *cfqd = cfqq->cfqd; | 786 | struct cfq_data *cfqd = cfqq->cfqd; |
| 966 | struct request *rq; | 787 | struct request *rq; |
| 967 | struct cfq_rq *crq; | 788 | int fifo; |
| 968 | 789 | ||
| 969 | if (cfq_cfqq_fifo_expire(cfqq)) | 790 | if (cfq_cfqq_fifo_expire(cfqq)) |
| 970 | return NULL; | 791 | return NULL; |
| 792 | if (list_empty(&cfqq->fifo)) | ||
| 793 | return NULL; | ||
| 971 | 794 | ||
| 972 | if (!list_empty(&cfqq->fifo)) { | 795 | fifo = cfq_cfqq_class_sync(cfqq); |
| 973 | int fifo = cfq_cfqq_class_sync(cfqq); | 796 | rq = rq_entry_fifo(cfqq->fifo.next); |
| 974 | 797 | ||
| 975 | crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next)); | 798 | if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) { |
| 976 | rq = crq->request; | 799 | cfq_mark_cfqq_fifo_expire(cfqq); |
| 977 | if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) { | 800 | return rq; |
| 978 | cfq_mark_cfqq_fifo_expire(cfqq); | ||
| 979 | return crq; | ||
| 980 | } | ||
| 981 | } | 801 | } |
| 982 | 802 | ||
| 983 | return NULL; | 803 | return NULL; |
| @@ -1063,25 +883,25 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 1063 | BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list)); | 883 | BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list)); |
| 1064 | 884 | ||
| 1065 | do { | 885 | do { |
| 1066 | struct cfq_rq *crq; | 886 | struct request *rq; |
| 1067 | 887 | ||
| 1068 | /* | 888 | /* |
| 1069 | * follow expired path, else get first next available | 889 | * follow expired path, else get first next available |
| 1070 | */ | 890 | */ |
| 1071 | if ((crq = cfq_check_fifo(cfqq)) == NULL) | 891 | if ((rq = cfq_check_fifo(cfqq)) == NULL) |
| 1072 | crq = cfqq->next_crq; | 892 | rq = cfqq->next_rq; |
| 1073 | 893 | ||
| 1074 | /* | 894 | /* |
| 1075 | * finally, insert request into driver dispatch list | 895 | * finally, insert request into driver dispatch list |
| 1076 | */ | 896 | */ |
| 1077 | cfq_dispatch_insert(cfqd->queue, crq); | 897 | cfq_dispatch_insert(cfqd->queue, rq); |
| 1078 | 898 | ||
| 1079 | cfqd->dispatch_slice++; | 899 | cfqd->dispatch_slice++; |
| 1080 | dispatched++; | 900 | dispatched++; |
| 1081 | 901 | ||
| 1082 | if (!cfqd->active_cic) { | 902 | if (!cfqd->active_cic) { |
| 1083 | atomic_inc(&crq->io_context->ioc->refcount); | 903 | atomic_inc(&RQ_CIC(rq)->ioc->refcount); |
| 1084 | cfqd->active_cic = crq->io_context; | 904 | cfqd->active_cic = RQ_CIC(rq); |
| 1085 | } | 905 | } |
| 1086 | 906 | ||
| 1087 | if (RB_EMPTY_ROOT(&cfqq->sort_list)) | 907 | if (RB_EMPTY_ROOT(&cfqq->sort_list)) |
| @@ -1112,13 +932,12 @@ static int | |||
| 1112 | cfq_forced_dispatch_cfqqs(struct list_head *list) | 932 | cfq_forced_dispatch_cfqqs(struct list_head *list) |
| 1113 | { | 933 | { |
| 1114 | struct cfq_queue *cfqq, *next; | 934 | struct cfq_queue *cfqq, *next; |
| 1115 | struct cfq_rq *crq; | ||
| 1116 | int dispatched; | 935 | int dispatched; |
| 1117 | 936 | ||
| 1118 | dispatched = 0; | 937 | dispatched = 0; |
| 1119 | list_for_each_entry_safe(cfqq, next, list, cfq_list) { | 938 | list_for_each_entry_safe(cfqq, next, list, cfq_list) { |
| 1120 | while ((crq = cfqq->next_crq)) { | 939 | while (cfqq->next_rq) { |
| 1121 | cfq_dispatch_insert(cfqq->cfqd->queue, crq); | 940 | cfq_dispatch_insert(cfqq->cfqd->queue, cfqq->next_rq); |
| 1122 | dispatched++; | 941 | dispatched++; |
| 1123 | } | 942 | } |
| 1124 | BUG_ON(!list_empty(&cfqq->fifo)); | 943 | BUG_ON(!list_empty(&cfqq->fifo)); |
| @@ -1194,8 +1013,8 @@ cfq_dispatch_requests(request_queue_t *q, int force) | |||
| 1194 | } | 1013 | } |
| 1195 | 1014 | ||
| 1196 | /* | 1015 | /* |
| 1197 | * task holds one reference to the queue, dropped when task exits. each crq | 1016 | * task holds one reference to the queue, dropped when task exits. each rq |
| 1198 | * in-flight on this queue also holds a reference, dropped when crq is freed. | 1017 | * in-flight on this queue also holds a reference, dropped when rq is freed. |
| 1199 | * | 1018 | * |
| 1200 | * queue lock must be held here. | 1019 | * queue lock must be held here. |
| 1201 | */ | 1020 | */ |
| @@ -1223,7 +1042,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq) | |||
| 1223 | kmem_cache_free(cfq_pool, cfqq); | 1042 | kmem_cache_free(cfq_pool, cfqq); |
| 1224 | } | 1043 | } |
| 1225 | 1044 | ||
| 1226 | static inline struct cfq_queue * | 1045 | static struct cfq_queue * |
| 1227 | __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, | 1046 | __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, |
| 1228 | const int hashval) | 1047 | const int hashval) |
| 1229 | { | 1048 | { |
| @@ -1260,62 +1079,63 @@ static void cfq_free_io_context(struct io_context *ioc) | |||
| 1260 | freed++; | 1079 | freed++; |
| 1261 | } | 1080 | } |
| 1262 | 1081 | ||
| 1263 | if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone) | 1082 | elv_ioc_count_mod(ioc_count, -freed); |
| 1083 | |||
| 1084 | if (ioc_gone && !elv_ioc_count_read(ioc_count)) | ||
| 1264 | complete(ioc_gone); | 1085 | complete(ioc_gone); |
| 1265 | } | 1086 | } |
| 1266 | 1087 | ||
| 1267 | static void cfq_trim(struct io_context *ioc) | 1088 | static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
| 1268 | { | 1089 | { |
| 1269 | ioc->set_ioprio = NULL; | 1090 | if (unlikely(cfqq == cfqd->active_queue)) |
| 1270 | cfq_free_io_context(ioc); | 1091 | __cfq_slice_expired(cfqd, cfqq, 0); |
| 1092 | |||
| 1093 | cfq_put_queue(cfqq); | ||
| 1271 | } | 1094 | } |
| 1272 | 1095 | ||
| 1273 | /* | 1096 | static void __cfq_exit_single_io_context(struct cfq_data *cfqd, |
| 1274 | * Called with interrupts disabled | 1097 | struct cfq_io_context *cic) |
| 1275 | */ | ||
| 1276 | static void cfq_exit_single_io_context(struct cfq_io_context *cic) | ||
| 1277 | { | 1098 | { |
| 1278 | struct cfq_data *cfqd = cic->key; | 1099 | list_del_init(&cic->queue_list); |
| 1279 | request_queue_t *q; | 1100 | smp_wmb(); |
| 1280 | 1101 | cic->key = NULL; | |
| 1281 | if (!cfqd) | ||
| 1282 | return; | ||
| 1283 | |||
| 1284 | q = cfqd->queue; | ||
| 1285 | |||
| 1286 | WARN_ON(!irqs_disabled()); | ||
| 1287 | |||
| 1288 | spin_lock(q->queue_lock); | ||
| 1289 | 1102 | ||
| 1290 | if (cic->cfqq[ASYNC]) { | 1103 | if (cic->cfqq[ASYNC]) { |
| 1291 | if (unlikely(cic->cfqq[ASYNC] == cfqd->active_queue)) | 1104 | cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]); |
| 1292 | __cfq_slice_expired(cfqd, cic->cfqq[ASYNC], 0); | ||
| 1293 | cfq_put_queue(cic->cfqq[ASYNC]); | ||
| 1294 | cic->cfqq[ASYNC] = NULL; | 1105 | cic->cfqq[ASYNC] = NULL; |
| 1295 | } | 1106 | } |
| 1296 | 1107 | ||
| 1297 | if (cic->cfqq[SYNC]) { | 1108 | if (cic->cfqq[SYNC]) { |
| 1298 | if (unlikely(cic->cfqq[SYNC] == cfqd->active_queue)) | 1109 | cfq_exit_cfqq(cfqd, cic->cfqq[SYNC]); |
| 1299 | __cfq_slice_expired(cfqd, cic->cfqq[SYNC], 0); | ||
| 1300 | cfq_put_queue(cic->cfqq[SYNC]); | ||
| 1301 | cic->cfqq[SYNC] = NULL; | 1110 | cic->cfqq[SYNC] = NULL; |
| 1302 | } | 1111 | } |
| 1112 | } | ||
| 1303 | 1113 | ||
| 1304 | cic->key = NULL; | 1114 | |
| 1305 | list_del_init(&cic->queue_list); | 1115 | /* |
| 1306 | spin_unlock(q->queue_lock); | 1116 | * Called with interrupts disabled |
| 1117 | */ | ||
| 1118 | static void cfq_exit_single_io_context(struct cfq_io_context *cic) | ||
| 1119 | { | ||
| 1120 | struct cfq_data *cfqd = cic->key; | ||
| 1121 | |||
| 1122 | if (cfqd) { | ||
| 1123 | request_queue_t *q = cfqd->queue; | ||
| 1124 | |||
| 1125 | spin_lock_irq(q->queue_lock); | ||
| 1126 | __cfq_exit_single_io_context(cfqd, cic); | ||
| 1127 | spin_unlock_irq(q->queue_lock); | ||
| 1128 | } | ||
| 1307 | } | 1129 | } |
| 1308 | 1130 | ||
| 1309 | static void cfq_exit_io_context(struct io_context *ioc) | 1131 | static void cfq_exit_io_context(struct io_context *ioc) |
| 1310 | { | 1132 | { |
| 1311 | struct cfq_io_context *__cic; | 1133 | struct cfq_io_context *__cic; |
| 1312 | unsigned long flags; | ||
| 1313 | struct rb_node *n; | 1134 | struct rb_node *n; |
| 1314 | 1135 | ||
| 1315 | /* | 1136 | /* |
| 1316 | * put the reference this task is holding to the various queues | 1137 | * put the reference this task is holding to the various queues |
| 1317 | */ | 1138 | */ |
| 1318 | spin_lock_irqsave(&cfq_exit_lock, flags); | ||
| 1319 | 1139 | ||
| 1320 | n = rb_first(&ioc->cic_root); | 1140 | n = rb_first(&ioc->cic_root); |
| 1321 | while (n != NULL) { | 1141 | while (n != NULL) { |
| @@ -1324,22 +1144,21 @@ static void cfq_exit_io_context(struct io_context *ioc) | |||
| 1324 | cfq_exit_single_io_context(__cic); | 1144 | cfq_exit_single_io_context(__cic); |
| 1325 | n = rb_next(n); | 1145 | n = rb_next(n); |
| 1326 | } | 1146 | } |
| 1327 | |||
| 1328 | spin_unlock_irqrestore(&cfq_exit_lock, flags); | ||
| 1329 | } | 1147 | } |
| 1330 | 1148 | ||
| 1331 | static struct cfq_io_context * | 1149 | static struct cfq_io_context * |
| 1332 | cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) | 1150 | cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) |
| 1333 | { | 1151 | { |
| 1334 | struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask); | 1152 | struct cfq_io_context *cic; |
| 1335 | 1153 | ||
| 1154 | cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask, cfqd->queue->node); | ||
| 1336 | if (cic) { | 1155 | if (cic) { |
| 1337 | memset(cic, 0, sizeof(*cic)); | 1156 | memset(cic, 0, sizeof(*cic)); |
| 1338 | cic->last_end_request = jiffies; | 1157 | cic->last_end_request = jiffies; |
| 1339 | INIT_LIST_HEAD(&cic->queue_list); | 1158 | INIT_LIST_HEAD(&cic->queue_list); |
| 1340 | cic->dtor = cfq_free_io_context; | 1159 | cic->dtor = cfq_free_io_context; |
| 1341 | cic->exit = cfq_exit_io_context; | 1160 | cic->exit = cfq_exit_io_context; |
| 1342 | atomic_inc(&ioc_count); | 1161 | elv_ioc_count_inc(ioc_count); |
| 1343 | } | 1162 | } |
| 1344 | 1163 | ||
| 1345 | return cic; | 1164 | return cic; |
| @@ -1420,15 +1239,12 @@ static inline void changed_ioprio(struct cfq_io_context *cic) | |||
| 1420 | spin_unlock(cfqd->queue->queue_lock); | 1239 | spin_unlock(cfqd->queue->queue_lock); |
| 1421 | } | 1240 | } |
| 1422 | 1241 | ||
| 1423 | /* | 1242 | static void cfq_ioc_set_ioprio(struct io_context *ioc) |
| 1424 | * callback from sys_ioprio_set, irqs are disabled | ||
| 1425 | */ | ||
| 1426 | static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) | ||
| 1427 | { | 1243 | { |
| 1428 | struct cfq_io_context *cic; | 1244 | struct cfq_io_context *cic; |
| 1429 | struct rb_node *n; | 1245 | struct rb_node *n; |
| 1430 | 1246 | ||
| 1431 | spin_lock(&cfq_exit_lock); | 1247 | ioc->ioprio_changed = 0; |
| 1432 | 1248 | ||
| 1433 | n = rb_first(&ioc->cic_root); | 1249 | n = rb_first(&ioc->cic_root); |
| 1434 | while (n != NULL) { | 1250 | while (n != NULL) { |
| @@ -1437,10 +1253,6 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) | |||
| 1437 | changed_ioprio(cic); | 1253 | changed_ioprio(cic); |
| 1438 | n = rb_next(n); | 1254 | n = rb_next(n); |
| 1439 | } | 1255 | } |
| 1440 | |||
| 1441 | spin_unlock(&cfq_exit_lock); | ||
| 1442 | |||
| 1443 | return 0; | ||
| 1444 | } | 1256 | } |
| 1445 | 1257 | ||
| 1446 | static struct cfq_queue * | 1258 | static struct cfq_queue * |
| @@ -1460,12 +1272,18 @@ retry: | |||
| 1460 | cfqq = new_cfqq; | 1272 | cfqq = new_cfqq; |
| 1461 | new_cfqq = NULL; | 1273 | new_cfqq = NULL; |
| 1462 | } else if (gfp_mask & __GFP_WAIT) { | 1274 | } else if (gfp_mask & __GFP_WAIT) { |
| 1275 | /* | ||
| 1276 | * Inform the allocator of the fact that we will | ||
| 1277 | * just repeat this allocation if it fails, to allow | ||
| 1278 | * the allocator to do whatever it needs to attempt to | ||
| 1279 | * free memory. | ||
| 1280 | */ | ||
| 1463 | spin_unlock_irq(cfqd->queue->queue_lock); | 1281 | spin_unlock_irq(cfqd->queue->queue_lock); |
| 1464 | new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); | 1282 | new_cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask|__GFP_NOFAIL, cfqd->queue->node); |
| 1465 | spin_lock_irq(cfqd->queue->queue_lock); | 1283 | spin_lock_irq(cfqd->queue->queue_lock); |
| 1466 | goto retry; | 1284 | goto retry; |
| 1467 | } else { | 1285 | } else { |
| 1468 | cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); | 1286 | cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask, cfqd->queue->node); |
| 1469 | if (!cfqq) | 1287 | if (!cfqq) |
| 1470 | goto out; | 1288 | goto out; |
| 1471 | } | 1289 | } |
| @@ -1480,13 +1298,13 @@ retry: | |||
| 1480 | hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); | 1298 | hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); |
| 1481 | atomic_set(&cfqq->ref, 0); | 1299 | atomic_set(&cfqq->ref, 0); |
| 1482 | cfqq->cfqd = cfqd; | 1300 | cfqq->cfqd = cfqd; |
| 1483 | cfqq->service_last = 0; | ||
| 1484 | /* | 1301 | /* |
| 1485 | * set ->slice_left to allow preemption for a new process | 1302 | * set ->slice_left to allow preemption for a new process |
| 1486 | */ | 1303 | */ |
| 1487 | cfqq->slice_left = 2 * cfqd->cfq_slice_idle; | 1304 | cfqq->slice_left = 2 * cfqd->cfq_slice_idle; |
| 1488 | cfq_mark_cfqq_idle_window(cfqq); | 1305 | cfq_mark_cfqq_idle_window(cfqq); |
| 1489 | cfq_mark_cfqq_prio_changed(cfqq); | 1306 | cfq_mark_cfqq_prio_changed(cfqq); |
| 1307 | cfq_mark_cfqq_queue_new(cfqq); | ||
| 1490 | cfq_init_prio_data(cfqq); | 1308 | cfq_init_prio_data(cfqq); |
| 1491 | } | 1309 | } |
| 1492 | 1310 | ||
| @@ -1502,12 +1320,10 @@ out: | |||
| 1502 | static void | 1320 | static void |
| 1503 | cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic) | 1321 | cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic) |
| 1504 | { | 1322 | { |
| 1505 | spin_lock(&cfq_exit_lock); | 1323 | WARN_ON(!list_empty(&cic->queue_list)); |
| 1506 | rb_erase(&cic->rb_node, &ioc->cic_root); | 1324 | rb_erase(&cic->rb_node, &ioc->cic_root); |
| 1507 | list_del_init(&cic->queue_list); | ||
| 1508 | spin_unlock(&cfq_exit_lock); | ||
| 1509 | kmem_cache_free(cfq_ioc_pool, cic); | 1325 | kmem_cache_free(cfq_ioc_pool, cic); |
| 1510 | atomic_dec(&ioc_count); | 1326 | elv_ioc_count_dec(ioc_count); |
| 1511 | } | 1327 | } |
| 1512 | 1328 | ||
| 1513 | static struct cfq_io_context * | 1329 | static struct cfq_io_context * |
| @@ -1551,7 +1367,6 @@ cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, | |||
| 1551 | cic->ioc = ioc; | 1367 | cic->ioc = ioc; |
| 1552 | cic->key = cfqd; | 1368 | cic->key = cfqd; |
| 1553 | 1369 | ||
| 1554 | ioc->set_ioprio = cfq_ioc_set_ioprio; | ||
| 1555 | restart: | 1370 | restart: |
| 1556 | parent = NULL; | 1371 | parent = NULL; |
| 1557 | p = &ioc->cic_root.rb_node; | 1372 | p = &ioc->cic_root.rb_node; |
| @@ -1573,11 +1388,12 @@ restart: | |||
| 1573 | BUG(); | 1388 | BUG(); |
| 1574 | } | 1389 | } |
| 1575 | 1390 | ||
| 1576 | spin_lock(&cfq_exit_lock); | ||
| 1577 | rb_link_node(&cic->rb_node, parent, p); | 1391 | rb_link_node(&cic->rb_node, parent, p); |
| 1578 | rb_insert_color(&cic->rb_node, &ioc->cic_root); | 1392 | rb_insert_color(&cic->rb_node, &ioc->cic_root); |
| 1393 | |||
| 1394 | spin_lock_irq(cfqd->queue->queue_lock); | ||
| 1579 | list_add(&cic->queue_list, &cfqd->cic_list); | 1395 | list_add(&cic->queue_list, &cfqd->cic_list); |
| 1580 | spin_unlock(&cfq_exit_lock); | 1396 | spin_unlock_irq(cfqd->queue->queue_lock); |
| 1581 | } | 1397 | } |
| 1582 | 1398 | ||
| 1583 | /* | 1399 | /* |
| @@ -1593,7 +1409,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
| 1593 | 1409 | ||
| 1594 | might_sleep_if(gfp_mask & __GFP_WAIT); | 1410 | might_sleep_if(gfp_mask & __GFP_WAIT); |
| 1595 | 1411 | ||
| 1596 | ioc = get_io_context(gfp_mask); | 1412 | ioc = get_io_context(gfp_mask, cfqd->queue->node); |
| 1597 | if (!ioc) | 1413 | if (!ioc) |
| 1598 | return NULL; | 1414 | return NULL; |
| 1599 | 1415 | ||
| @@ -1607,6 +1423,10 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
| 1607 | 1423 | ||
| 1608 | cfq_cic_link(cfqd, ioc, cic); | 1424 | cfq_cic_link(cfqd, ioc, cic); |
| 1609 | out: | 1425 | out: |
| 1426 | smp_read_barrier_depends(); | ||
| 1427 | if (unlikely(ioc->ioprio_changed)) | ||
| 1428 | cfq_ioc_set_ioprio(ioc); | ||
| 1429 | |||
| 1610 | return cic; | 1430 | return cic; |
| 1611 | err: | 1431 | err: |
| 1612 | put_io_context(ioc); | 1432 | put_io_context(ioc); |
| @@ -1640,15 +1460,15 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) | |||
| 1640 | 1460 | ||
| 1641 | static void | 1461 | static void |
| 1642 | cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic, | 1462 | cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic, |
| 1643 | struct cfq_rq *crq) | 1463 | struct request *rq) |
| 1644 | { | 1464 | { |
| 1645 | sector_t sdist; | 1465 | sector_t sdist; |
| 1646 | u64 total; | 1466 | u64 total; |
| 1647 | 1467 | ||
| 1648 | if (cic->last_request_pos < crq->request->sector) | 1468 | if (cic->last_request_pos < rq->sector) |
| 1649 | sdist = crq->request->sector - cic->last_request_pos; | 1469 | sdist = rq->sector - cic->last_request_pos; |
| 1650 | else | 1470 | else |
| 1651 | sdist = cic->last_request_pos - crq->request->sector; | 1471 | sdist = cic->last_request_pos - rq->sector; |
| 1652 | 1472 | ||
| 1653 | /* | 1473 | /* |
| 1654 | * Don't allow the seek distance to get too large from the | 1474 | * Don't allow the seek distance to get too large from the |
| @@ -1699,7 +1519,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 1699 | */ | 1519 | */ |
| 1700 | static int | 1520 | static int |
| 1701 | cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | 1521 | cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, |
| 1702 | struct cfq_rq *crq) | 1522 | struct request *rq) |
| 1703 | { | 1523 | { |
| 1704 | struct cfq_queue *cfqq = cfqd->active_queue; | 1524 | struct cfq_queue *cfqq = cfqd->active_queue; |
| 1705 | 1525 | ||
| @@ -1718,7 +1538,17 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
| 1718 | */ | 1538 | */ |
| 1719 | if (new_cfqq->slice_left < cfqd->cfq_slice_idle) | 1539 | if (new_cfqq->slice_left < cfqd->cfq_slice_idle) |
| 1720 | return 0; | 1540 | return 0; |
| 1721 | if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq)) | 1541 | /* |
| 1542 | * if the new request is sync, but the currently running queue is | ||
| 1543 | * not, let the sync request have priority. | ||
| 1544 | */ | ||
| 1545 | if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq)) | ||
| 1546 | return 1; | ||
| 1547 | /* | ||
| 1548 | * So both queues are sync. Let the new request get disk time if | ||
| 1549 | * it's a metadata request and the current queue is doing regular IO. | ||
| 1550 | */ | ||
| 1551 | if (rq_is_meta(rq) && !cfqq->meta_pending) | ||
| 1722 | return 1; | 1552 | return 1; |
| 1723 | 1553 | ||
| 1724 | return 0; | 1554 | return 0; |
| @@ -1730,47 +1560,45 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
| 1730 | */ | 1560 | */ |
| 1731 | static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 1561 | static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
| 1732 | { | 1562 | { |
| 1733 | struct cfq_queue *__cfqq, *next; | 1563 | cfq_slice_expired(cfqd, 1); |
| 1734 | |||
| 1735 | list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list) | ||
| 1736 | cfq_resort_rr_list(__cfqq, 1); | ||
| 1737 | 1564 | ||
| 1738 | if (!cfqq->slice_left) | 1565 | if (!cfqq->slice_left) |
| 1739 | cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; | 1566 | cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; |
| 1740 | 1567 | ||
| 1741 | cfqq->slice_end = cfqq->slice_left + jiffies; | 1568 | /* |
| 1742 | cfq_slice_expired(cfqd, 1); | 1569 | * Put the new queue at the front of the of the current list, |
| 1743 | __cfq_set_active_queue(cfqd, cfqq); | 1570 | * so we know that it will be selected next. |
| 1744 | } | 1571 | */ |
| 1745 | 1572 | BUG_ON(!cfq_cfqq_on_rr(cfqq)); | |
| 1746 | /* | 1573 | list_move(&cfqq->cfq_list, &cfqd->cur_rr); |
| 1747 | * should really be a ll_rw_blk.c helper | ||
| 1748 | */ | ||
| 1749 | static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
| 1750 | { | ||
| 1751 | request_queue_t *q = cfqd->queue; | ||
| 1752 | 1574 | ||
| 1753 | if (!blk_queue_plugged(q)) | 1575 | cfqq->slice_end = cfqq->slice_left + jiffies; |
| 1754 | q->request_fn(q); | ||
| 1755 | else | ||
| 1756 | __generic_unplug_device(q); | ||
| 1757 | } | 1576 | } |
| 1758 | 1577 | ||
| 1759 | /* | 1578 | /* |
| 1760 | * Called when a new fs request (crq) is added (to cfqq). Check if there's | 1579 | * Called when a new fs request (rq) is added (to cfqq). Check if there's |
| 1761 | * something we should do about it | 1580 | * something we should do about it |
| 1762 | */ | 1581 | */ |
| 1763 | static void | 1582 | static void |
| 1764 | cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 1583 | cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
| 1765 | struct cfq_rq *crq) | 1584 | struct request *rq) |
| 1766 | { | 1585 | { |
| 1767 | struct cfq_io_context *cic = crq->io_context; | 1586 | struct cfq_io_context *cic = RQ_CIC(rq); |
| 1587 | |||
| 1588 | if (rq_is_meta(rq)) | ||
| 1589 | cfqq->meta_pending++; | ||
| 1590 | |||
| 1591 | /* | ||
| 1592 | * check if this request is a better next-serve candidate)) { | ||
| 1593 | */ | ||
| 1594 | cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq); | ||
| 1595 | BUG_ON(!cfqq->next_rq); | ||
| 1768 | 1596 | ||
| 1769 | /* | 1597 | /* |
| 1770 | * we never wait for an async request and we don't allow preemption | 1598 | * we never wait for an async request and we don't allow preemption |
| 1771 | * of an async request. so just return early | 1599 | * of an async request. so just return early |
| 1772 | */ | 1600 | */ |
| 1773 | if (!cfq_crq_is_sync(crq)) { | 1601 | if (!rq_is_sync(rq)) { |
| 1774 | /* | 1602 | /* |
| 1775 | * sync process issued an async request, if it's waiting | 1603 | * sync process issued an async request, if it's waiting |
| 1776 | * then expire it and kick rq handling. | 1604 | * then expire it and kick rq handling. |
| @@ -1778,17 +1606,17 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 1778 | if (cic == cfqd->active_cic && | 1606 | if (cic == cfqd->active_cic && |
| 1779 | del_timer(&cfqd->idle_slice_timer)) { | 1607 | del_timer(&cfqd->idle_slice_timer)) { |
| 1780 | cfq_slice_expired(cfqd, 0); | 1608 | cfq_slice_expired(cfqd, 0); |
| 1781 | cfq_start_queueing(cfqd, cfqq); | 1609 | blk_start_queueing(cfqd->queue); |
| 1782 | } | 1610 | } |
| 1783 | return; | 1611 | return; |
| 1784 | } | 1612 | } |
| 1785 | 1613 | ||
| 1786 | cfq_update_io_thinktime(cfqd, cic); | 1614 | cfq_update_io_thinktime(cfqd, cic); |
| 1787 | cfq_update_io_seektime(cfqd, cic, crq); | 1615 | cfq_update_io_seektime(cfqd, cic, rq); |
| 1788 | cfq_update_idle_window(cfqd, cfqq, cic); | 1616 | cfq_update_idle_window(cfqd, cfqq, cic); |
| 1789 | 1617 | ||
| 1790 | cic->last_queue = jiffies; | 1618 | cic->last_queue = jiffies; |
| 1791 | cic->last_request_pos = crq->request->sector + crq->request->nr_sectors; | 1619 | cic->last_request_pos = rq->sector + rq->nr_sectors; |
| 1792 | 1620 | ||
| 1793 | if (cfqq == cfqd->active_queue) { | 1621 | if (cfqq == cfqd->active_queue) { |
| 1794 | /* | 1622 | /* |
| @@ -1799,9 +1627,9 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 1799 | if (cfq_cfqq_wait_request(cfqq)) { | 1627 | if (cfq_cfqq_wait_request(cfqq)) { |
| 1800 | cfq_mark_cfqq_must_dispatch(cfqq); | 1628 | cfq_mark_cfqq_must_dispatch(cfqq); |
| 1801 | del_timer(&cfqd->idle_slice_timer); | 1629 | del_timer(&cfqd->idle_slice_timer); |
| 1802 | cfq_start_queueing(cfqd, cfqq); | 1630 | blk_start_queueing(cfqd->queue); |
| 1803 | } | 1631 | } |
| 1804 | } else if (cfq_should_preempt(cfqd, cfqq, crq)) { | 1632 | } else if (cfq_should_preempt(cfqd, cfqq, rq)) { |
| 1805 | /* | 1633 | /* |
| 1806 | * not the active queue - expire current slice if it is | 1634 | * not the active queue - expire current slice if it is |
| 1807 | * idle and has expired it's mean thinktime or this new queue | 1635 | * idle and has expired it's mean thinktime or this new queue |
| @@ -1809,34 +1637,32 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 1809 | */ | 1637 | */ |
| 1810 | cfq_preempt_queue(cfqd, cfqq); | 1638 | cfq_preempt_queue(cfqd, cfqq); |
| 1811 | cfq_mark_cfqq_must_dispatch(cfqq); | 1639 | cfq_mark_cfqq_must_dispatch(cfqq); |
| 1812 | cfq_start_queueing(cfqd, cfqq); | 1640 | blk_start_queueing(cfqd->queue); |
| 1813 | } | 1641 | } |
| 1814 | } | 1642 | } |
| 1815 | 1643 | ||
| 1816 | static void cfq_insert_request(request_queue_t *q, struct request *rq) | 1644 | static void cfq_insert_request(request_queue_t *q, struct request *rq) |
| 1817 | { | 1645 | { |
| 1818 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1646 | struct cfq_data *cfqd = q->elevator->elevator_data; |
| 1819 | struct cfq_rq *crq = RQ_DATA(rq); | 1647 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
| 1820 | struct cfq_queue *cfqq = crq->cfq_queue; | ||
| 1821 | 1648 | ||
| 1822 | cfq_init_prio_data(cfqq); | 1649 | cfq_init_prio_data(cfqq); |
| 1823 | 1650 | ||
| 1824 | cfq_add_crq_rb(crq); | 1651 | cfq_add_rq_rb(rq); |
| 1825 | 1652 | ||
| 1826 | list_add_tail(&rq->queuelist, &cfqq->fifo); | 1653 | if (!cfq_cfqq_on_rr(cfqq)) |
| 1654 | cfq_add_cfqq_rr(cfqd, cfqq); | ||
| 1827 | 1655 | ||
| 1828 | if (rq_mergeable(rq)) | 1656 | list_add_tail(&rq->queuelist, &cfqq->fifo); |
| 1829 | cfq_add_crq_hash(cfqd, crq); | ||
| 1830 | 1657 | ||
| 1831 | cfq_crq_enqueued(cfqd, cfqq, crq); | 1658 | cfq_rq_enqueued(cfqd, cfqq, rq); |
| 1832 | } | 1659 | } |
| 1833 | 1660 | ||
| 1834 | static void cfq_completed_request(request_queue_t *q, struct request *rq) | 1661 | static void cfq_completed_request(request_queue_t *q, struct request *rq) |
| 1835 | { | 1662 | { |
| 1836 | struct cfq_rq *crq = RQ_DATA(rq); | 1663 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
| 1837 | struct cfq_queue *cfqq = crq->cfq_queue; | ||
| 1838 | struct cfq_data *cfqd = cfqq->cfqd; | 1664 | struct cfq_data *cfqd = cfqq->cfqd; |
| 1839 | const int sync = cfq_crq_is_sync(crq); | 1665 | const int sync = rq_is_sync(rq); |
| 1840 | unsigned long now; | 1666 | unsigned long now; |
| 1841 | 1667 | ||
| 1842 | now = jiffies; | 1668 | now = jiffies; |
| @@ -1849,15 +1675,11 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) | |||
| 1849 | if (!cfq_class_idle(cfqq)) | 1675 | if (!cfq_class_idle(cfqq)) |
| 1850 | cfqd->last_end_request = now; | 1676 | cfqd->last_end_request = now; |
| 1851 | 1677 | ||
| 1852 | if (!cfq_cfqq_dispatched(cfqq)) { | 1678 | if (!cfq_cfqq_dispatched(cfqq) && cfq_cfqq_on_rr(cfqq)) |
| 1853 | if (cfq_cfqq_on_rr(cfqq)) { | 1679 | cfq_resort_rr_list(cfqq, 0); |
| 1854 | cfqq->service_last = now; | ||
| 1855 | cfq_resort_rr_list(cfqq, 0); | ||
| 1856 | } | ||
| 1857 | } | ||
| 1858 | 1680 | ||
| 1859 | if (sync) | 1681 | if (sync) |
| 1860 | crq->io_context->last_end_request = now; | 1682 | RQ_CIC(rq)->last_end_request = now; |
| 1861 | 1683 | ||
| 1862 | /* | 1684 | /* |
| 1863 | * If this is the active queue, check if it needs to be expired, | 1685 | * If this is the active queue, check if it needs to be expired, |
| @@ -1873,30 +1695,6 @@ static void cfq_completed_request(request_queue_t *q, struct request *rq) | |||
| 1873 | } | 1695 | } |
| 1874 | } | 1696 | } |
| 1875 | 1697 | ||
| 1876 | static struct request * | ||
| 1877 | cfq_former_request(request_queue_t *q, struct request *rq) | ||
| 1878 | { | ||
| 1879 | struct cfq_rq *crq = RQ_DATA(rq); | ||
| 1880 | struct rb_node *rbprev = rb_prev(&crq->rb_node); | ||
| 1881 | |||
| 1882 | if (rbprev) | ||
| 1883 | return rb_entry_crq(rbprev)->request; | ||
| 1884 | |||
| 1885 | return NULL; | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | static struct request * | ||
| 1889 | cfq_latter_request(request_queue_t *q, struct request *rq) | ||
| 1890 | { | ||
| 1891 | struct cfq_rq *crq = RQ_DATA(rq); | ||
| 1892 | struct rb_node *rbnext = rb_next(&crq->rb_node); | ||
| 1893 | |||
| 1894 | if (rbnext) | ||
| 1895 | return rb_entry_crq(rbnext)->request; | ||
| 1896 | |||
| 1897 | return NULL; | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | /* | 1698 | /* |
| 1901 | * we temporarily boost lower priority queues if they are holding fs exclusive | 1699 | * we temporarily boost lower priority queues if they are holding fs exclusive |
| 1902 | * resources. they are boosted to normal prio (CLASS_BE/4) | 1700 | * resources. they are boosted to normal prio (CLASS_BE/4) |
| @@ -1933,9 +1731,7 @@ static void cfq_prio_boost(struct cfq_queue *cfqq) | |||
| 1933 | cfq_resort_rr_list(cfqq, 0); | 1731 | cfq_resort_rr_list(cfqq, 0); |
| 1934 | } | 1732 | } |
| 1935 | 1733 | ||
| 1936 | static inline int | 1734 | static inline int __cfq_may_queue(struct cfq_queue *cfqq) |
| 1937 | __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, | ||
| 1938 | struct task_struct *task, int rw) | ||
| 1939 | { | 1735 | { |
| 1940 | if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && | 1736 | if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && |
| 1941 | !cfq_cfqq_must_alloc_slice(cfqq)) { | 1737 | !cfq_cfqq_must_alloc_slice(cfqq)) { |
| @@ -1946,7 +1742,7 @@ __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 1946 | return ELV_MQUEUE_MAY; | 1742 | return ELV_MQUEUE_MAY; |
| 1947 | } | 1743 | } |
| 1948 | 1744 | ||
| 1949 | static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) | 1745 | static int cfq_may_queue(request_queue_t *q, int rw) |
| 1950 | { | 1746 | { |
| 1951 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1747 | struct cfq_data *cfqd = q->elevator->elevator_data; |
| 1952 | struct task_struct *tsk = current; | 1748 | struct task_struct *tsk = current; |
| @@ -1963,48 +1759,30 @@ static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) | |||
| 1963 | cfq_init_prio_data(cfqq); | 1759 | cfq_init_prio_data(cfqq); |
| 1964 | cfq_prio_boost(cfqq); | 1760 | cfq_prio_boost(cfqq); |
| 1965 | 1761 | ||
| 1966 | return __cfq_may_queue(cfqd, cfqq, tsk, rw); | 1762 | return __cfq_may_queue(cfqq); |
| 1967 | } | 1763 | } |
| 1968 | 1764 | ||
| 1969 | return ELV_MQUEUE_MAY; | 1765 | return ELV_MQUEUE_MAY; |
| 1970 | } | 1766 | } |
| 1971 | 1767 | ||
| 1972 | static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) | ||
| 1973 | { | ||
| 1974 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
| 1975 | |||
| 1976 | if (unlikely(cfqd->rq_starved)) { | ||
| 1977 | struct request_list *rl = &q->rq; | ||
| 1978 | |||
| 1979 | smp_mb(); | ||
| 1980 | if (waitqueue_active(&rl->wait[READ])) | ||
| 1981 | wake_up(&rl->wait[READ]); | ||
| 1982 | if (waitqueue_active(&rl->wait[WRITE])) | ||
| 1983 | wake_up(&rl->wait[WRITE]); | ||
| 1984 | } | ||
| 1985 | } | ||
| 1986 | |||
| 1987 | /* | 1768 | /* |
| 1988 | * queue lock held here | 1769 | * queue lock held here |
| 1989 | */ | 1770 | */ |
| 1990 | static void cfq_put_request(request_queue_t *q, struct request *rq) | 1771 | static void cfq_put_request(request_queue_t *q, struct request *rq) |
| 1991 | { | 1772 | { |
| 1992 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1773 | struct cfq_queue *cfqq = RQ_CFQQ(rq); |
| 1993 | struct cfq_rq *crq = RQ_DATA(rq); | ||
| 1994 | 1774 | ||
| 1995 | if (crq) { | 1775 | if (cfqq) { |
| 1996 | struct cfq_queue *cfqq = crq->cfq_queue; | ||
| 1997 | const int rw = rq_data_dir(rq); | 1776 | const int rw = rq_data_dir(rq); |
| 1998 | 1777 | ||
| 1999 | BUG_ON(!cfqq->allocated[rw]); | 1778 | BUG_ON(!cfqq->allocated[rw]); |
| 2000 | cfqq->allocated[rw]--; | 1779 | cfqq->allocated[rw]--; |
| 2001 | 1780 | ||
| 2002 | put_io_context(crq->io_context->ioc); | 1781 | put_io_context(RQ_CIC(rq)->ioc); |
| 2003 | 1782 | ||
| 2004 | mempool_free(crq, cfqd->crq_pool); | ||
| 2005 | rq->elevator_private = NULL; | 1783 | rq->elevator_private = NULL; |
| 1784 | rq->elevator_private2 = NULL; | ||
| 2006 | 1785 | ||
| 2007 | cfq_check_waiters(q, cfqq); | ||
| 2008 | cfq_put_queue(cfqq); | 1786 | cfq_put_queue(cfqq); |
| 2009 | } | 1787 | } |
| 2010 | } | 1788 | } |
| @@ -2013,8 +1791,7 @@ static void cfq_put_request(request_queue_t *q, struct request *rq) | |||
| 2013 | * Allocate cfq data structures associated with this request. | 1791 | * Allocate cfq data structures associated with this request. |
| 2014 | */ | 1792 | */ |
| 2015 | static int | 1793 | static int |
| 2016 | cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | 1794 | cfq_set_request(request_queue_t *q, struct request *rq, gfp_t gfp_mask) |
| 2017 | gfp_t gfp_mask) | ||
| 2018 | { | 1795 | { |
| 2019 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1796 | struct cfq_data *cfqd = q->elevator->elevator_data; |
| 2020 | struct task_struct *tsk = current; | 1797 | struct task_struct *tsk = current; |
| @@ -2022,7 +1799,6 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | |||
| 2022 | const int rw = rq_data_dir(rq); | 1799 | const int rw = rq_data_dir(rq); |
| 2023 | pid_t key = cfq_queue_pid(tsk, rw); | 1800 | pid_t key = cfq_queue_pid(tsk, rw); |
| 2024 | struct cfq_queue *cfqq; | 1801 | struct cfq_queue *cfqq; |
| 2025 | struct cfq_rq *crq; | ||
| 2026 | unsigned long flags; | 1802 | unsigned long flags; |
| 2027 | int is_sync = key != CFQ_KEY_ASYNC; | 1803 | int is_sync = key != CFQ_KEY_ASYNC; |
| 2028 | 1804 | ||
| @@ -2046,42 +1822,18 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | |||
| 2046 | 1822 | ||
| 2047 | cfqq->allocated[rw]++; | 1823 | cfqq->allocated[rw]++; |
| 2048 | cfq_clear_cfqq_must_alloc(cfqq); | 1824 | cfq_clear_cfqq_must_alloc(cfqq); |
| 2049 | cfqd->rq_starved = 0; | ||
| 2050 | atomic_inc(&cfqq->ref); | 1825 | atomic_inc(&cfqq->ref); |
| 2051 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 2052 | 1826 | ||
| 2053 | crq = mempool_alloc(cfqd->crq_pool, gfp_mask); | 1827 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 2054 | if (crq) { | ||
| 2055 | RB_CLEAR_NODE(&crq->rb_node); | ||
| 2056 | crq->rb_key = 0; | ||
| 2057 | crq->request = rq; | ||
| 2058 | INIT_HLIST_NODE(&crq->hash); | ||
| 2059 | crq->cfq_queue = cfqq; | ||
| 2060 | crq->io_context = cic; | ||
| 2061 | |||
| 2062 | if (is_sync) | ||
| 2063 | cfq_mark_crq_is_sync(crq); | ||
| 2064 | else | ||
| 2065 | cfq_clear_crq_is_sync(crq); | ||
| 2066 | 1828 | ||
| 2067 | rq->elevator_private = crq; | 1829 | rq->elevator_private = cic; |
| 2068 | return 0; | 1830 | rq->elevator_private2 = cfqq; |
| 2069 | } | 1831 | return 0; |
| 2070 | 1832 | ||
| 2071 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 2072 | cfqq->allocated[rw]--; | ||
| 2073 | if (!(cfqq->allocated[0] + cfqq->allocated[1])) | ||
| 2074 | cfq_mark_cfqq_must_alloc(cfqq); | ||
| 2075 | cfq_put_queue(cfqq); | ||
| 2076 | queue_fail: | 1833 | queue_fail: |
| 2077 | if (cic) | 1834 | if (cic) |
| 2078 | put_io_context(cic->ioc); | 1835 | put_io_context(cic->ioc); |
| 2079 | /* | 1836 | |
| 2080 | * mark us rq allocation starved. we need to kickstart the process | ||
| 2081 | * ourselves if there are no pending requests that can do it for us. | ||
| 2082 | * that would be an extremely rare OOM situation | ||
| 2083 | */ | ||
| 2084 | cfqd->rq_starved = 1; | ||
| 2085 | cfq_schedule_dispatch(cfqd); | 1837 | cfq_schedule_dispatch(cfqd); |
| 2086 | spin_unlock_irqrestore(q->queue_lock, flags); | 1838 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 2087 | return 1; | 1839 | return 1; |
| @@ -2090,27 +1842,10 @@ queue_fail: | |||
| 2090 | static void cfq_kick_queue(void *data) | 1842 | static void cfq_kick_queue(void *data) |
| 2091 | { | 1843 | { |
| 2092 | request_queue_t *q = data; | 1844 | request_queue_t *q = data; |
| 2093 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
| 2094 | unsigned long flags; | 1845 | unsigned long flags; |
| 2095 | 1846 | ||
| 2096 | spin_lock_irqsave(q->queue_lock, flags); | 1847 | spin_lock_irqsave(q->queue_lock, flags); |
| 2097 | 1848 | blk_start_queueing(q); | |
| 2098 | if (cfqd->rq_starved) { | ||
| 2099 | struct request_list *rl = &q->rq; | ||
| 2100 | |||
| 2101 | /* | ||
| 2102 | * we aren't guaranteed to get a request after this, but we | ||
| 2103 | * have to be opportunistic | ||
| 2104 | */ | ||
| 2105 | smp_mb(); | ||
| 2106 | if (waitqueue_active(&rl->wait[READ])) | ||
| 2107 | wake_up(&rl->wait[READ]); | ||
| 2108 | if (waitqueue_active(&rl->wait[WRITE])) | ||
| 2109 | wake_up(&rl->wait[WRITE]); | ||
| 2110 | } | ||
| 2111 | |||
| 2112 | blk_remove_plug(q); | ||
| 2113 | q->request_fn(q); | ||
| 2114 | spin_unlock_irqrestore(q->queue_lock, flags); | 1849 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 2115 | } | 1850 | } |
| 2116 | 1851 | ||
| @@ -2193,7 +1928,6 @@ static void cfq_exit_queue(elevator_t *e) | |||
| 2193 | 1928 | ||
| 2194 | cfq_shutdown_timer_wq(cfqd); | 1929 | cfq_shutdown_timer_wq(cfqd); |
| 2195 | 1930 | ||
| 2196 | spin_lock(&cfq_exit_lock); | ||
| 2197 | spin_lock_irq(q->queue_lock); | 1931 | spin_lock_irq(q->queue_lock); |
| 2198 | 1932 | ||
| 2199 | if (cfqd->active_queue) | 1933 | if (cfqd->active_queue) |
| @@ -2203,25 +1937,14 @@ static void cfq_exit_queue(elevator_t *e) | |||
| 2203 | struct cfq_io_context *cic = list_entry(cfqd->cic_list.next, | 1937 | struct cfq_io_context *cic = list_entry(cfqd->cic_list.next, |
| 2204 | struct cfq_io_context, | 1938 | struct cfq_io_context, |
| 2205 | queue_list); | 1939 | queue_list); |
| 2206 | if (cic->cfqq[ASYNC]) { | 1940 | |
| 2207 | cfq_put_queue(cic->cfqq[ASYNC]); | 1941 | __cfq_exit_single_io_context(cfqd, cic); |
| 2208 | cic->cfqq[ASYNC] = NULL; | ||
| 2209 | } | ||
| 2210 | if (cic->cfqq[SYNC]) { | ||
| 2211 | cfq_put_queue(cic->cfqq[SYNC]); | ||
| 2212 | cic->cfqq[SYNC] = NULL; | ||
| 2213 | } | ||
| 2214 | cic->key = NULL; | ||
| 2215 | list_del_init(&cic->queue_list); | ||
| 2216 | } | 1942 | } |
| 2217 | 1943 | ||
| 2218 | spin_unlock_irq(q->queue_lock); | 1944 | spin_unlock_irq(q->queue_lock); |
| 2219 | spin_unlock(&cfq_exit_lock); | ||
| 2220 | 1945 | ||
| 2221 | cfq_shutdown_timer_wq(cfqd); | 1946 | cfq_shutdown_timer_wq(cfqd); |
| 2222 | 1947 | ||
| 2223 | mempool_destroy(cfqd->crq_pool); | ||
| 2224 | kfree(cfqd->crq_hash); | ||
| 2225 | kfree(cfqd->cfq_hash); | 1948 | kfree(cfqd->cfq_hash); |
| 2226 | kfree(cfqd); | 1949 | kfree(cfqd); |
| 2227 | } | 1950 | } |
| @@ -2231,7 +1954,7 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
| 2231 | struct cfq_data *cfqd; | 1954 | struct cfq_data *cfqd; |
| 2232 | int i; | 1955 | int i; |
| 2233 | 1956 | ||
| 2234 | cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL); | 1957 | cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL, q->node); |
| 2235 | if (!cfqd) | 1958 | if (!cfqd) |
| 2236 | return NULL; | 1959 | return NULL; |
| 2237 | 1960 | ||
| @@ -2243,23 +1966,12 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
| 2243 | INIT_LIST_HEAD(&cfqd->busy_rr); | 1966 | INIT_LIST_HEAD(&cfqd->busy_rr); |
| 2244 | INIT_LIST_HEAD(&cfqd->cur_rr); | 1967 | INIT_LIST_HEAD(&cfqd->cur_rr); |
| 2245 | INIT_LIST_HEAD(&cfqd->idle_rr); | 1968 | INIT_LIST_HEAD(&cfqd->idle_rr); |
| 2246 | INIT_LIST_HEAD(&cfqd->empty_list); | ||
| 2247 | INIT_LIST_HEAD(&cfqd->cic_list); | 1969 | INIT_LIST_HEAD(&cfqd->cic_list); |
| 2248 | 1970 | ||
| 2249 | cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); | 1971 | cfqd->cfq_hash = kmalloc_node(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL, q->node); |
| 2250 | if (!cfqd->crq_hash) | ||
| 2251 | goto out_crqhash; | ||
| 2252 | |||
| 2253 | cfqd->cfq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL); | ||
| 2254 | if (!cfqd->cfq_hash) | 1972 | if (!cfqd->cfq_hash) |
| 2255 | goto out_cfqhash; | 1973 | goto out_free; |
| 2256 | |||
| 2257 | cfqd->crq_pool = mempool_create_slab_pool(BLKDEV_MIN_RQ, crq_pool); | ||
| 2258 | if (!cfqd->crq_pool) | ||
| 2259 | goto out_crqpool; | ||
| 2260 | 1974 | ||
| 2261 | for (i = 0; i < CFQ_MHASH_ENTRIES; i++) | ||
| 2262 | INIT_HLIST_HEAD(&cfqd->crq_hash[i]); | ||
| 2263 | for (i = 0; i < CFQ_QHASH_ENTRIES; i++) | 1975 | for (i = 0; i < CFQ_QHASH_ENTRIES; i++) |
| 2264 | INIT_HLIST_HEAD(&cfqd->cfq_hash[i]); | 1976 | INIT_HLIST_HEAD(&cfqd->cfq_hash[i]); |
| 2265 | 1977 | ||
| @@ -2275,7 +1987,6 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
| 2275 | 1987 | ||
| 2276 | INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); | 1988 | INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); |
| 2277 | 1989 | ||
| 2278 | cfqd->cfq_queued = cfq_queued; | ||
| 2279 | cfqd->cfq_quantum = cfq_quantum; | 1990 | cfqd->cfq_quantum = cfq_quantum; |
| 2280 | cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; | 1991 | cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; |
| 2281 | cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1]; | 1992 | cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1]; |
| @@ -2287,19 +1998,13 @@ static void *cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
| 2287 | cfqd->cfq_slice_idle = cfq_slice_idle; | 1998 | cfqd->cfq_slice_idle = cfq_slice_idle; |
| 2288 | 1999 | ||
| 2289 | return cfqd; | 2000 | return cfqd; |
| 2290 | out_crqpool: | 2001 | out_free: |
| 2291 | kfree(cfqd->cfq_hash); | ||
| 2292 | out_cfqhash: | ||
| 2293 | kfree(cfqd->crq_hash); | ||
| 2294 | out_crqhash: | ||
| 2295 | kfree(cfqd); | 2002 | kfree(cfqd); |
| 2296 | return NULL; | 2003 | return NULL; |
| 2297 | } | 2004 | } |
| 2298 | 2005 | ||
| 2299 | static void cfq_slab_kill(void) | 2006 | static void cfq_slab_kill(void) |
| 2300 | { | 2007 | { |
| 2301 | if (crq_pool) | ||
| 2302 | kmem_cache_destroy(crq_pool); | ||
| 2303 | if (cfq_pool) | 2008 | if (cfq_pool) |
| 2304 | kmem_cache_destroy(cfq_pool); | 2009 | kmem_cache_destroy(cfq_pool); |
| 2305 | if (cfq_ioc_pool) | 2010 | if (cfq_ioc_pool) |
| @@ -2308,11 +2013,6 @@ static void cfq_slab_kill(void) | |||
| 2308 | 2013 | ||
| 2309 | static int __init cfq_slab_setup(void) | 2014 | static int __init cfq_slab_setup(void) |
| 2310 | { | 2015 | { |
| 2311 | crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0, | ||
| 2312 | NULL, NULL); | ||
| 2313 | if (!crq_pool) | ||
| 2314 | goto fail; | ||
| 2315 | |||
| 2316 | cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0, | 2016 | cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0, |
| 2317 | NULL, NULL); | 2017 | NULL, NULL); |
| 2318 | if (!cfq_pool) | 2018 | if (!cfq_pool) |
| @@ -2358,7 +2058,6 @@ static ssize_t __FUNC(elevator_t *e, char *page) \ | |||
| 2358 | return cfq_var_show(__data, (page)); \ | 2058 | return cfq_var_show(__data, (page)); \ |
| 2359 | } | 2059 | } |
| 2360 | SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); | 2060 | SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); |
| 2361 | SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); | ||
| 2362 | SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1); | 2061 | SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1); |
| 2363 | SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); | 2062 | SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); |
| 2364 | SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0); | 2063 | SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0); |
| @@ -2386,7 +2085,6 @@ static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \ | |||
| 2386 | return ret; \ | 2085 | return ret; \ |
| 2387 | } | 2086 | } |
| 2388 | STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); | 2087 | STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); |
| 2389 | STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); | ||
| 2390 | STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1); | 2088 | STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1); |
| 2391 | STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1); | 2089 | STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1); |
| 2392 | STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); | 2090 | STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); |
| @@ -2402,7 +2100,6 @@ STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, | |||
| 2402 | 2100 | ||
| 2403 | static struct elv_fs_entry cfq_attrs[] = { | 2101 | static struct elv_fs_entry cfq_attrs[] = { |
| 2404 | CFQ_ATTR(quantum), | 2102 | CFQ_ATTR(quantum), |
| 2405 | CFQ_ATTR(queued), | ||
| 2406 | CFQ_ATTR(fifo_expire_sync), | 2103 | CFQ_ATTR(fifo_expire_sync), |
| 2407 | CFQ_ATTR(fifo_expire_async), | 2104 | CFQ_ATTR(fifo_expire_async), |
| 2408 | CFQ_ATTR(back_seek_max), | 2105 | CFQ_ATTR(back_seek_max), |
| @@ -2425,14 +2122,14 @@ static struct elevator_type iosched_cfq = { | |||
| 2425 | .elevator_deactivate_req_fn = cfq_deactivate_request, | 2122 | .elevator_deactivate_req_fn = cfq_deactivate_request, |
| 2426 | .elevator_queue_empty_fn = cfq_queue_empty, | 2123 | .elevator_queue_empty_fn = cfq_queue_empty, |
| 2427 | .elevator_completed_req_fn = cfq_completed_request, | 2124 | .elevator_completed_req_fn = cfq_completed_request, |
| 2428 | .elevator_former_req_fn = cfq_former_request, | 2125 | .elevator_former_req_fn = elv_rb_former_request, |
| 2429 | .elevator_latter_req_fn = cfq_latter_request, | 2126 | .elevator_latter_req_fn = elv_rb_latter_request, |
| 2430 | .elevator_set_req_fn = cfq_set_request, | 2127 | .elevator_set_req_fn = cfq_set_request, |
| 2431 | .elevator_put_req_fn = cfq_put_request, | 2128 | .elevator_put_req_fn = cfq_put_request, |
| 2432 | .elevator_may_queue_fn = cfq_may_queue, | 2129 | .elevator_may_queue_fn = cfq_may_queue, |
| 2433 | .elevator_init_fn = cfq_init_queue, | 2130 | .elevator_init_fn = cfq_init_queue, |
| 2434 | .elevator_exit_fn = cfq_exit_queue, | 2131 | .elevator_exit_fn = cfq_exit_queue, |
| 2435 | .trim = cfq_trim, | 2132 | .trim = cfq_free_io_context, |
| 2436 | }, | 2133 | }, |
| 2437 | .elevator_attrs = cfq_attrs, | 2134 | .elevator_attrs = cfq_attrs, |
| 2438 | .elevator_name = "cfq", | 2135 | .elevator_name = "cfq", |
| @@ -2468,7 +2165,7 @@ static void __exit cfq_exit(void) | |||
| 2468 | ioc_gone = &all_gone; | 2165 | ioc_gone = &all_gone; |
| 2469 | /* ioc_gone's update must be visible before reading ioc_count */ | 2166 | /* ioc_gone's update must be visible before reading ioc_count */ |
| 2470 | smp_wmb(); | 2167 | smp_wmb(); |
| 2471 | if (atomic_read(&ioc_count)) | 2168 | if (elv_ioc_count_read(ioc_count)) |
| 2472 | wait_for_completion(ioc_gone); | 2169 | wait_for_completion(ioc_gone); |
| 2473 | synchronize_rcu(); | 2170 | synchronize_rcu(); |
| 2474 | cfq_slab_kill(); | 2171 | cfq_slab_kill(); |
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index c7ca9f0b6498..b7c5b34cb7b4 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Deadline i/o scheduler. | 2 | * Deadline i/o scheduler. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2002 Jens Axboe <axboe@suse.de> | 4 | * Copyright (C) 2002 Jens Axboe <axboe@kernel.dk> |
| 5 | */ | 5 | */ |
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/compiler.h> | 14 | #include <linux/compiler.h> |
| 15 | #include <linux/hash.h> | ||
| 16 | #include <linux/rbtree.h> | 15 | #include <linux/rbtree.h> |
| 17 | 16 | ||
| 18 | /* | 17 | /* |
| @@ -24,13 +23,6 @@ static const int writes_starved = 2; /* max times reads can starve a write */ | |||
| 24 | static const int fifo_batch = 16; /* # of sequential requests treated as one | 23 | static const int fifo_batch = 16; /* # of sequential requests treated as one |
| 25 | by the above parameters. For throughput. */ | 24 | by the above parameters. For throughput. */ |
| 26 | 25 | ||
| 27 | static const int deadline_hash_shift = 5; | ||
| 28 | #define DL_HASH_BLOCK(sec) ((sec) >> 3) | ||
| 29 | #define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift)) | ||
| 30 | #define DL_HASH_ENTRIES (1 << deadline_hash_shift) | ||
| 31 | #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) | ||
| 32 | #define ON_HASH(drq) (!hlist_unhashed(&(drq)->hash)) | ||
| 33 | |||
| 34 | struct deadline_data { | 26 | struct deadline_data { |
| 35 | /* | 27 | /* |
| 36 | * run time data | 28 | * run time data |
| @@ -45,8 +37,7 @@ struct deadline_data { | |||
| 45 | /* | 37 | /* |
| 46 | * next in sort order. read, write or both are NULL | 38 | * next in sort order. read, write or both are NULL |
| 47 | */ | 39 | */ |
| 48 | struct deadline_rq *next_drq[2]; | 40 | struct request *next_rq[2]; |
| 49 | struct hlist_head *hash; /* request hash */ | ||
| 50 | unsigned int batching; /* number of sequential requests made */ | 41 | unsigned int batching; /* number of sequential requests made */ |
| 51 | sector_t last_sector; /* head position */ | 42 | sector_t last_sector; /* head position */ |
| 52 | unsigned int starved; /* times reads have starved writes */ | 43 | unsigned int starved; /* times reads have starved writes */ |
| @@ -58,240 +49,69 @@ struct deadline_data { | |||
| 58 | int fifo_batch; | 49 | int fifo_batch; |
| 59 | int writes_starved; | 50 | int writes_starved; |
| 60 | int front_merges; | 51 | int front_merges; |
| 61 | |||
| 62 | mempool_t *drq_pool; | ||
| 63 | }; | 52 | }; |
| 64 | 53 | ||
| 65 | /* | 54 | static void deadline_move_request(struct deadline_data *, struct request *); |
| 66 | * pre-request data. | ||
| 67 | */ | ||
| 68 | struct deadline_rq { | ||
| 69 | /* | ||
| 70 | * rbtree index, key is the starting offset | ||
| 71 | */ | ||
| 72 | struct rb_node rb_node; | ||
| 73 | sector_t rb_key; | ||
| 74 | |||
| 75 | struct request *request; | ||
| 76 | |||
| 77 | /* | ||
| 78 | * request hash, key is the ending offset (for back merge lookup) | ||
| 79 | */ | ||
| 80 | struct hlist_node hash; | ||
| 81 | |||
| 82 | /* | ||
| 83 | * expire fifo | ||
| 84 | */ | ||
| 85 | struct list_head fifo; | ||
| 86 | unsigned long expires; | ||
| 87 | }; | ||
| 88 | |||
| 89 | static void deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq); | ||
| 90 | |||
| 91 | static kmem_cache_t *drq_pool; | ||
| 92 | |||
| 93 | #define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) | ||
| 94 | 55 | ||
| 95 | /* | 56 | #define RQ_RB_ROOT(dd, rq) (&(dd)->sort_list[rq_data_dir((rq))]) |
| 96 | * the back merge hash support functions | ||
| 97 | */ | ||
| 98 | static inline void __deadline_del_drq_hash(struct deadline_rq *drq) | ||
| 99 | { | ||
| 100 | hlist_del_init(&drq->hash); | ||
| 101 | } | ||
| 102 | |||
| 103 | static inline void deadline_del_drq_hash(struct deadline_rq *drq) | ||
| 104 | { | ||
| 105 | if (ON_HASH(drq)) | ||
| 106 | __deadline_del_drq_hash(drq); | ||
| 107 | } | ||
| 108 | |||
| 109 | static inline void | ||
| 110 | deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) | ||
| 111 | { | ||
| 112 | struct request *rq = drq->request; | ||
| 113 | |||
| 114 | BUG_ON(ON_HASH(drq)); | ||
| 115 | |||
| 116 | hlist_add_head(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); | ||
| 117 | } | ||
| 118 | |||
| 119 | /* | ||
| 120 | * move hot entry to front of chain | ||
| 121 | */ | ||
| 122 | static inline void | ||
| 123 | deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) | ||
| 124 | { | ||
| 125 | struct request *rq = drq->request; | ||
| 126 | struct hlist_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; | ||
| 127 | |||
| 128 | if (ON_HASH(drq) && &drq->hash != head->first) { | ||
| 129 | hlist_del(&drq->hash); | ||
| 130 | hlist_add_head(&drq->hash, head); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | static struct request * | ||
| 135 | deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) | ||
| 136 | { | ||
| 137 | struct hlist_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; | ||
| 138 | struct hlist_node *entry, *next; | ||
| 139 | struct deadline_rq *drq; | ||
| 140 | |||
| 141 | hlist_for_each_entry_safe(drq, entry, next, hash_list, hash) { | ||
| 142 | struct request *__rq = drq->request; | ||
| 143 | |||
| 144 | BUG_ON(!ON_HASH(drq)); | ||
| 145 | |||
| 146 | if (!rq_mergeable(__rq)) { | ||
| 147 | __deadline_del_drq_hash(drq); | ||
| 148 | continue; | ||
| 149 | } | ||
| 150 | |||
| 151 | if (rq_hash_key(__rq) == offset) | ||
| 152 | return __rq; | ||
| 153 | } | ||
| 154 | |||
| 155 | return NULL; | ||
| 156 | } | ||
| 157 | |||
| 158 | /* | ||
| 159 | * rb tree support functions | ||
| 160 | */ | ||
| 161 | #define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node) | ||
| 162 | #define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)]) | ||
| 163 | #define rq_rb_key(rq) (rq)->sector | ||
| 164 | |||
| 165 | static struct deadline_rq * | ||
| 166 | __deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) | ||
| 167 | { | ||
| 168 | struct rb_node **p = &DRQ_RB_ROOT(dd, drq)->rb_node; | ||
| 169 | struct rb_node *parent = NULL; | ||
| 170 | struct deadline_rq *__drq; | ||
| 171 | |||
| 172 | while (*p) { | ||
| 173 | parent = *p; | ||
| 174 | __drq = rb_entry_drq(parent); | ||
| 175 | |||
| 176 | if (drq->rb_key < __drq->rb_key) | ||
| 177 | p = &(*p)->rb_left; | ||
| 178 | else if (drq->rb_key > __drq->rb_key) | ||
| 179 | p = &(*p)->rb_right; | ||
| 180 | else | ||
| 181 | return __drq; | ||
| 182 | } | ||
| 183 | |||
| 184 | rb_link_node(&drq->rb_node, parent, p); | ||
| 185 | return NULL; | ||
| 186 | } | ||
| 187 | 57 | ||
| 188 | static void | 58 | static void |
| 189 | deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) | 59 | deadline_add_rq_rb(struct deadline_data *dd, struct request *rq) |
| 190 | { | 60 | { |
| 191 | struct deadline_rq *__alias; | 61 | struct rb_root *root = RQ_RB_ROOT(dd, rq); |
| 192 | 62 | struct request *__alias; | |
| 193 | drq->rb_key = rq_rb_key(drq->request); | ||
| 194 | 63 | ||
| 195 | retry: | 64 | retry: |
| 196 | __alias = __deadline_add_drq_rb(dd, drq); | 65 | __alias = elv_rb_add(root, rq); |
| 197 | if (!__alias) { | 66 | if (unlikely(__alias)) { |
| 198 | rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); | 67 | deadline_move_request(dd, __alias); |
| 199 | return; | 68 | goto retry; |
| 200 | } | 69 | } |
| 201 | |||
| 202 | deadline_move_request(dd, __alias); | ||
| 203 | goto retry; | ||
| 204 | } | 70 | } |
| 205 | 71 | ||
| 206 | static inline void | 72 | static inline void |
| 207 | deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) | 73 | deadline_del_rq_rb(struct deadline_data *dd, struct request *rq) |
| 208 | { | 74 | { |
| 209 | const int data_dir = rq_data_dir(drq->request); | 75 | const int data_dir = rq_data_dir(rq); |
| 210 | 76 | ||
| 211 | if (dd->next_drq[data_dir] == drq) { | 77 | if (dd->next_rq[data_dir] == rq) { |
| 212 | struct rb_node *rbnext = rb_next(&drq->rb_node); | 78 | struct rb_node *rbnext = rb_next(&rq->rb_node); |
| 213 | 79 | ||
| 214 | dd->next_drq[data_dir] = NULL; | 80 | dd->next_rq[data_dir] = NULL; |
| 215 | if (rbnext) | 81 | if (rbnext) |
| 216 | dd->next_drq[data_dir] = rb_entry_drq(rbnext); | 82 | dd->next_rq[data_dir] = rb_entry_rq(rbnext); |
| 217 | } | ||
| 218 | |||
| 219 | BUG_ON(!RB_EMPTY_NODE(&drq->rb_node)); | ||
| 220 | rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); | ||
| 221 | RB_CLEAR_NODE(&drq->rb_node); | ||
| 222 | } | ||
| 223 | |||
| 224 | static struct request * | ||
| 225 | deadline_find_drq_rb(struct deadline_data *dd, sector_t sector, int data_dir) | ||
| 226 | { | ||
| 227 | struct rb_node *n = dd->sort_list[data_dir].rb_node; | ||
| 228 | struct deadline_rq *drq; | ||
| 229 | |||
| 230 | while (n) { | ||
| 231 | drq = rb_entry_drq(n); | ||
| 232 | |||
| 233 | if (sector < drq->rb_key) | ||
| 234 | n = n->rb_left; | ||
| 235 | else if (sector > drq->rb_key) | ||
| 236 | n = n->rb_right; | ||
| 237 | else | ||
| 238 | return drq->request; | ||
| 239 | } | 83 | } |
| 240 | 84 | ||
| 241 | return NULL; | 85 | elv_rb_del(RQ_RB_ROOT(dd, rq), rq); |
| 242 | } | 86 | } |
| 243 | 87 | ||
| 244 | /* | 88 | /* |
| 245 | * deadline_find_first_drq finds the first (lowest sector numbered) request | 89 | * add rq to rbtree and fifo |
| 246 | * for the specified data_dir. Used to sweep back to the start of the disk | ||
| 247 | * (1-way elevator) after we process the last (highest sector) request. | ||
| 248 | */ | ||
| 249 | static struct deadline_rq * | ||
| 250 | deadline_find_first_drq(struct deadline_data *dd, int data_dir) | ||
| 251 | { | ||
| 252 | struct rb_node *n = dd->sort_list[data_dir].rb_node; | ||
| 253 | |||
| 254 | for (;;) { | ||
| 255 | if (n->rb_left == NULL) | ||
| 256 | return rb_entry_drq(n); | ||
| 257 | |||
| 258 | n = n->rb_left; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | /* | ||
| 263 | * add drq to rbtree and fifo | ||
| 264 | */ | 90 | */ |
| 265 | static void | 91 | static void |
| 266 | deadline_add_request(struct request_queue *q, struct request *rq) | 92 | deadline_add_request(struct request_queue *q, struct request *rq) |
| 267 | { | 93 | { |
| 268 | struct deadline_data *dd = q->elevator->elevator_data; | 94 | struct deadline_data *dd = q->elevator->elevator_data; |
| 269 | struct deadline_rq *drq = RQ_DATA(rq); | 95 | const int data_dir = rq_data_dir(rq); |
| 270 | 96 | ||
| 271 | const int data_dir = rq_data_dir(drq->request); | 97 | deadline_add_rq_rb(dd, rq); |
| 272 | 98 | ||
| 273 | deadline_add_drq_rb(dd, drq); | ||
| 274 | /* | 99 | /* |
| 275 | * set expire time (only used for reads) and add to fifo list | 100 | * set expire time (only used for reads) and add to fifo list |
| 276 | */ | 101 | */ |
| 277 | drq->expires = jiffies + dd->fifo_expire[data_dir]; | 102 | rq_set_fifo_time(rq, jiffies + dd->fifo_expire[data_dir]); |
| 278 | list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); | 103 | list_add_tail(&rq->queuelist, &dd->fifo_list[data_dir]); |
| 279 | |||
| 280 | if (rq_mergeable(rq)) | ||
| 281 | deadline_add_drq_hash(dd, drq); | ||
| 282 | } | 104 | } |
| 283 | 105 | ||
| 284 | /* | 106 | /* |
| 285 | * remove rq from rbtree, fifo, and hash | 107 | * remove rq from rbtree and fifo. |
| 286 | */ | 108 | */ |
| 287 | static void deadline_remove_request(request_queue_t *q, struct request *rq) | 109 | static void deadline_remove_request(request_queue_t *q, struct request *rq) |
| 288 | { | 110 | { |
| 289 | struct deadline_rq *drq = RQ_DATA(rq); | ||
| 290 | struct deadline_data *dd = q->elevator->elevator_data; | 111 | struct deadline_data *dd = q->elevator->elevator_data; |
| 291 | 112 | ||
| 292 | list_del_init(&drq->fifo); | 113 | rq_fifo_clear(rq); |
| 293 | deadline_del_drq_rb(dd, drq); | 114 | deadline_del_rq_rb(dd, rq); |
| 294 | deadline_del_drq_hash(drq); | ||
| 295 | } | 115 | } |
| 296 | 116 | ||
| 297 | static int | 117 | static int |
| @@ -302,27 +122,14 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) | |||
| 302 | int ret; | 122 | int ret; |
| 303 | 123 | ||
| 304 | /* | 124 | /* |
| 305 | * see if the merge hash can satisfy a back merge | ||
| 306 | */ | ||
| 307 | __rq = deadline_find_drq_hash(dd, bio->bi_sector); | ||
| 308 | if (__rq) { | ||
| 309 | BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); | ||
| 310 | |||
| 311 | if (elv_rq_merge_ok(__rq, bio)) { | ||
| 312 | ret = ELEVATOR_BACK_MERGE; | ||
| 313 | goto out; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | /* | ||
| 318 | * check for front merge | 125 | * check for front merge |
| 319 | */ | 126 | */ |
| 320 | if (dd->front_merges) { | 127 | if (dd->front_merges) { |
| 321 | sector_t rb_key = bio->bi_sector + bio_sectors(bio); | 128 | sector_t sector = bio->bi_sector + bio_sectors(bio); |
| 322 | 129 | ||
| 323 | __rq = deadline_find_drq_rb(dd, rb_key, bio_data_dir(bio)); | 130 | __rq = elv_rb_find(&dd->sort_list[bio_data_dir(bio)], sector); |
| 324 | if (__rq) { | 131 | if (__rq) { |
| 325 | BUG_ON(rb_key != rq_rb_key(__rq)); | 132 | BUG_ON(sector != __rq->sector); |
| 326 | 133 | ||
| 327 | if (elv_rq_merge_ok(__rq, bio)) { | 134 | if (elv_rq_merge_ok(__rq, bio)) { |
| 328 | ret = ELEVATOR_FRONT_MERGE; | 135 | ret = ELEVATOR_FRONT_MERGE; |
| @@ -333,29 +140,21 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) | |||
| 333 | 140 | ||
| 334 | return ELEVATOR_NO_MERGE; | 141 | return ELEVATOR_NO_MERGE; |
| 335 | out: | 142 | out: |
| 336 | if (ret) | ||
| 337 | deadline_hot_drq_hash(dd, RQ_DATA(__rq)); | ||
| 338 | *req = __rq; | 143 | *req = __rq; |
| 339 | return ret; | 144 | return ret; |
| 340 | } | 145 | } |
| 341 | 146 | ||
| 342 | static void deadline_merged_request(request_queue_t *q, struct request *req) | 147 | static void deadline_merged_request(request_queue_t *q, struct request *req, |
| 148 | int type) | ||
| 343 | { | 149 | { |
| 344 | struct deadline_data *dd = q->elevator->elevator_data; | 150 | struct deadline_data *dd = q->elevator->elevator_data; |
| 345 | struct deadline_rq *drq = RQ_DATA(req); | ||
| 346 | |||
| 347 | /* | ||
| 348 | * hash always needs to be repositioned, key is end sector | ||
| 349 | */ | ||
| 350 | deadline_del_drq_hash(drq); | ||
| 351 | deadline_add_drq_hash(dd, drq); | ||
| 352 | 151 | ||
| 353 | /* | 152 | /* |
| 354 | * if the merge was a front merge, we need to reposition request | 153 | * if the merge was a front merge, we need to reposition request |
| 355 | */ | 154 | */ |
| 356 | if (rq_rb_key(req) != drq->rb_key) { | 155 | if (type == ELEVATOR_FRONT_MERGE) { |
| 357 | deadline_del_drq_rb(dd, drq); | 156 | elv_rb_del(RQ_RB_ROOT(dd, req), req); |
| 358 | deadline_add_drq_rb(dd, drq); | 157 | deadline_add_rq_rb(dd, req); |
| 359 | } | 158 | } |
| 360 | } | 159 | } |
| 361 | 160 | ||
| @@ -363,33 +162,14 @@ static void | |||
| 363 | deadline_merged_requests(request_queue_t *q, struct request *req, | 162 | deadline_merged_requests(request_queue_t *q, struct request *req, |
| 364 | struct request *next) | 163 | struct request *next) |
| 365 | { | 164 | { |
| 366 | struct deadline_data *dd = q->elevator->elevator_data; | ||
| 367 | struct deadline_rq *drq = RQ_DATA(req); | ||
| 368 | struct deadline_rq *dnext = RQ_DATA(next); | ||
| 369 | |||
| 370 | BUG_ON(!drq); | ||
| 371 | BUG_ON(!dnext); | ||
| 372 | |||
| 373 | /* | 165 | /* |
| 374 | * reposition drq (this is the merged request) in hash, and in rbtree | 166 | * if next expires before rq, assign its expire time to rq |
| 375 | * in case of a front merge | 167 | * and move into next position (next will be deleted) in fifo |
| 376 | */ | 168 | */ |
| 377 | deadline_del_drq_hash(drq); | 169 | if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) { |
| 378 | deadline_add_drq_hash(dd, drq); | 170 | if (time_before(rq_fifo_time(next), rq_fifo_time(req))) { |
| 379 | 171 | list_move(&req->queuelist, &next->queuelist); | |
| 380 | if (rq_rb_key(req) != drq->rb_key) { | 172 | rq_set_fifo_time(req, rq_fifo_time(next)); |
| 381 | deadline_del_drq_rb(dd, drq); | ||
| 382 | deadline_add_drq_rb(dd, drq); | ||
| 383 | } | ||
| 384 | |||
| 385 | /* | ||
| 386 | * if dnext expires before drq, assign its expire time to drq | ||
| 387 | * and move into dnext position (dnext will be deleted) in fifo | ||
| 388 | */ | ||
| 389 | if (!list_empty(&drq->fifo) && !list_empty(&dnext->fifo)) { | ||
| 390 | if (time_before(dnext->expires, drq->expires)) { | ||
| 391 | list_move(&drq->fifo, &dnext->fifo); | ||
| 392 | drq->expires = dnext->expires; | ||
| 393 | } | 173 | } |
| 394 | } | 174 | } |
| 395 | 175 | ||
| @@ -403,52 +183,50 @@ deadline_merged_requests(request_queue_t *q, struct request *req, | |||
| 403 | * move request from sort list to dispatch queue. | 183 | * move request from sort list to dispatch queue. |
| 404 | */ | 184 | */ |
| 405 | static inline void | 185 | static inline void |
| 406 | deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq) | 186 | deadline_move_to_dispatch(struct deadline_data *dd, struct request *rq) |
| 407 | { | 187 | { |
| 408 | request_queue_t *q = drq->request->q; | 188 | request_queue_t *q = rq->q; |
| 409 | 189 | ||
| 410 | deadline_remove_request(q, drq->request); | 190 | deadline_remove_request(q, rq); |
| 411 | elv_dispatch_add_tail(q, drq->request); | 191 | elv_dispatch_add_tail(q, rq); |
| 412 | } | 192 | } |
| 413 | 193 | ||
| 414 | /* | 194 | /* |
| 415 | * move an entry to dispatch queue | 195 | * move an entry to dispatch queue |
| 416 | */ | 196 | */ |
| 417 | static void | 197 | static void |
| 418 | deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq) | 198 | deadline_move_request(struct deadline_data *dd, struct request *rq) |
| 419 | { | 199 | { |
| 420 | const int data_dir = rq_data_dir(drq->request); | 200 | const int data_dir = rq_data_dir(rq); |
| 421 | struct rb_node *rbnext = rb_next(&drq->rb_node); | 201 | struct rb_node *rbnext = rb_next(&rq->rb_node); |
| 422 | 202 | ||
| 423 | dd->next_drq[READ] = NULL; | 203 | dd->next_rq[READ] = NULL; |
| 424 | dd->next_drq[WRITE] = NULL; | 204 | dd->next_rq[WRITE] = NULL; |
| 425 | 205 | ||
| 426 | if (rbnext) | 206 | if (rbnext) |
| 427 | dd->next_drq[data_dir] = rb_entry_drq(rbnext); | 207 | dd->next_rq[data_dir] = rb_entry_rq(rbnext); |
| 428 | 208 | ||
| 429 | dd->last_sector = drq->request->sector + drq->request->nr_sectors; | 209 | dd->last_sector = rq->sector + rq->nr_sectors; |
| 430 | 210 | ||
| 431 | /* | 211 | /* |
| 432 | * take it off the sort and fifo list, move | 212 | * take it off the sort and fifo list, move |
| 433 | * to dispatch queue | 213 | * to dispatch queue |
| 434 | */ | 214 | */ |
| 435 | deadline_move_to_dispatch(dd, drq); | 215 | deadline_move_to_dispatch(dd, rq); |
| 436 | } | 216 | } |
| 437 | 217 | ||
| 438 | #define list_entry_fifo(ptr) list_entry((ptr), struct deadline_rq, fifo) | ||
| 439 | |||
| 440 | /* | 218 | /* |
| 441 | * deadline_check_fifo returns 0 if there are no expired reads on the fifo, | 219 | * deadline_check_fifo returns 0 if there are no expired reads on the fifo, |
| 442 | * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir]) | 220 | * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir]) |
| 443 | */ | 221 | */ |
| 444 | static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) | 222 | static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) |
| 445 | { | 223 | { |
| 446 | struct deadline_rq *drq = list_entry_fifo(dd->fifo_list[ddir].next); | 224 | struct request *rq = rq_entry_fifo(dd->fifo_list[ddir].next); |
| 447 | 225 | ||
| 448 | /* | 226 | /* |
| 449 | * drq is expired! | 227 | * rq is expired! |
| 450 | */ | 228 | */ |
| 451 | if (time_after(jiffies, drq->expires)) | 229 | if (time_after(jiffies, rq_fifo_time(rq))) |
| 452 | return 1; | 230 | return 1; |
| 453 | 231 | ||
| 454 | return 0; | 232 | return 0; |
| @@ -463,21 +241,21 @@ static int deadline_dispatch_requests(request_queue_t *q, int force) | |||
| 463 | struct deadline_data *dd = q->elevator->elevator_data; | 241 | struct deadline_data *dd = q->elevator->elevator_data; |
| 464 | const int reads = !list_empty(&dd->fifo_list[READ]); | 242 | const int reads = !list_empty(&dd->fifo_list[READ]); |
| 465 | const int writes = !list_empty(&dd->fifo_list[WRITE]); | 243 | const int writes = !list_empty(&dd->fifo_list[WRITE]); |
| 466 | struct deadline_rq *drq; | 244 | struct request *rq; |
| 467 | int data_dir; | 245 | int data_dir; |
| 468 | 246 | ||
| 469 | /* | 247 | /* |
| 470 | * batches are currently reads XOR writes | 248 | * batches are currently reads XOR writes |
| 471 | */ | 249 | */ |
| 472 | if (dd->next_drq[WRITE]) | 250 | if (dd->next_rq[WRITE]) |
| 473 | drq = dd->next_drq[WRITE]; | 251 | rq = dd->next_rq[WRITE]; |
| 474 | else | 252 | else |
| 475 | drq = dd->next_drq[READ]; | 253 | rq = dd->next_rq[READ]; |
| 476 | 254 | ||
| 477 | if (drq) { | 255 | if (rq) { |
| 478 | /* we have a "next request" */ | 256 | /* we have a "next request" */ |
| 479 | 257 | ||
| 480 | if (dd->last_sector != drq->request->sector) | 258 | if (dd->last_sector != rq->sector) |
| 481 | /* end the batch on a non sequential request */ | 259 | /* end the batch on a non sequential request */ |
| 482 | dd->batching += dd->fifo_batch; | 260 | dd->batching += dd->fifo_batch; |
| 483 | 261 | ||
| @@ -526,30 +304,33 @@ dispatch_find_request: | |||
| 526 | if (deadline_check_fifo(dd, data_dir)) { | 304 | if (deadline_check_fifo(dd, data_dir)) { |
| 527 | /* An expired request exists - satisfy it */ | 305 | /* An expired request exists - satisfy it */ |
| 528 | dd->batching = 0; | 306 | dd->batching = 0; |
| 529 | drq = list_entry_fifo(dd->fifo_list[data_dir].next); | 307 | rq = rq_entry_fifo(dd->fifo_list[data_dir].next); |
| 530 | 308 | ||
| 531 | } else if (dd->next_drq[data_dir]) { | 309 | } else if (dd->next_rq[data_dir]) { |
| 532 | /* | 310 | /* |
| 533 | * The last req was the same dir and we have a next request in | 311 | * The last req was the same dir and we have a next request in |
| 534 | * sort order. No expired requests so continue on from here. | 312 | * sort order. No expired requests so continue on from here. |
| 535 | */ | 313 | */ |
| 536 | drq = dd->next_drq[data_dir]; | 314 | rq = dd->next_rq[data_dir]; |
| 537 | } else { | 315 | } else { |
| 316 | struct rb_node *node; | ||
| 538 | /* | 317 | /* |
| 539 | * The last req was the other direction or we have run out of | 318 | * The last req was the other direction or we have run out of |
| 540 | * higher-sectored requests. Go back to the lowest sectored | 319 | * higher-sectored requests. Go back to the lowest sectored |
| 541 | * request (1 way elevator) and start a new batch. | 320 | * request (1 way elevator) and start a new batch. |
| 542 | */ | 321 | */ |
| 543 | dd->batching = 0; | 322 | dd->batching = 0; |
| 544 | drq = deadline_find_first_drq(dd, data_dir); | 323 | node = rb_first(&dd->sort_list[data_dir]); |
| 324 | if (node) | ||
| 325 | rq = rb_entry_rq(node); | ||
| 545 | } | 326 | } |
| 546 | 327 | ||
| 547 | dispatch_request: | 328 | dispatch_request: |
| 548 | /* | 329 | /* |
| 549 | * drq is the selected appropriate request. | 330 | * rq is the selected appropriate request. |
| 550 | */ | 331 | */ |
| 551 | dd->batching++; | 332 | dd->batching++; |
| 552 | deadline_move_request(dd, drq); | 333 | deadline_move_request(dd, rq); |
| 553 | 334 | ||
| 554 | return 1; | 335 | return 1; |
| 555 | } | 336 | } |
| @@ -562,30 +343,6 @@ static int deadline_queue_empty(request_queue_t *q) | |||
| 562 | && list_empty(&dd->fifo_list[READ]); | 343 | && list_empty(&dd->fifo_list[READ]); |
| 563 | } | 344 | } |
| 564 | 345 | ||
| 565 | static struct request * | ||
| 566 | deadline_former_request(request_queue_t *q, struct request *rq) | ||
| 567 | { | ||
| 568 | struct deadline_rq *drq = RQ_DATA(rq); | ||
| 569 | struct rb_node *rbprev = rb_prev(&drq->rb_node); | ||
| 570 | |||
| 571 | if (rbprev) | ||
| 572 | return rb_entry_drq(rbprev)->request; | ||
| 573 | |||
| 574 | return NULL; | ||
| 575 | } | ||
| 576 | |||
| 577 | static struct request * | ||
| 578 | deadline_latter_request(request_queue_t *q, struct request *rq) | ||
| 579 | { | ||
| 580 | struct deadline_rq *drq = RQ_DATA(rq); | ||
| 581 | struct rb_node *rbnext = rb_next(&drq->rb_node); | ||
| 582 | |||
| 583 | if (rbnext) | ||
| 584 | return rb_entry_drq(rbnext)->request; | ||
| 585 | |||
| 586 | return NULL; | ||
| 587 | } | ||
| 588 | |||
| 589 | static void deadline_exit_queue(elevator_t *e) | 346 | static void deadline_exit_queue(elevator_t *e) |
| 590 | { | 347 | { |
| 591 | struct deadline_data *dd = e->elevator_data; | 348 | struct deadline_data *dd = e->elevator_data; |
| @@ -593,46 +350,21 @@ static void deadline_exit_queue(elevator_t *e) | |||
| 593 | BUG_ON(!list_empty(&dd->fifo_list[READ])); | 350 | BUG_ON(!list_empty(&dd->fifo_list[READ])); |
| 594 | BUG_ON(!list_empty(&dd->fifo_list[WRITE])); | 351 | BUG_ON(!list_empty(&dd->fifo_list[WRITE])); |
| 595 | 352 | ||
| 596 | mempool_destroy(dd->drq_pool); | ||
| 597 | kfree(dd->hash); | ||
| 598 | kfree(dd); | 353 | kfree(dd); |
| 599 | } | 354 | } |
| 600 | 355 | ||
| 601 | /* | 356 | /* |
| 602 | * initialize elevator private data (deadline_data), and alloc a drq for | 357 | * initialize elevator private data (deadline_data). |
| 603 | * each request on the free lists | ||
| 604 | */ | 358 | */ |
| 605 | static void *deadline_init_queue(request_queue_t *q, elevator_t *e) | 359 | static void *deadline_init_queue(request_queue_t *q, elevator_t *e) |
| 606 | { | 360 | { |
| 607 | struct deadline_data *dd; | 361 | struct deadline_data *dd; |
| 608 | int i; | ||
| 609 | |||
| 610 | if (!drq_pool) | ||
| 611 | return NULL; | ||
| 612 | 362 | ||
| 613 | dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node); | 363 | dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node); |
| 614 | if (!dd) | 364 | if (!dd) |
| 615 | return NULL; | 365 | return NULL; |
| 616 | memset(dd, 0, sizeof(*dd)); | 366 | memset(dd, 0, sizeof(*dd)); |
| 617 | 367 | ||
| 618 | dd->hash = kmalloc_node(sizeof(struct hlist_head)*DL_HASH_ENTRIES, | ||
| 619 | GFP_KERNEL, q->node); | ||
| 620 | if (!dd->hash) { | ||
| 621 | kfree(dd); | ||
| 622 | return NULL; | ||
| 623 | } | ||
| 624 | |||
| 625 | dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, | ||
| 626 | mempool_free_slab, drq_pool, q->node); | ||
| 627 | if (!dd->drq_pool) { | ||
| 628 | kfree(dd->hash); | ||
| 629 | kfree(dd); | ||
| 630 | return NULL; | ||
| 631 | } | ||
| 632 | |||
| 633 | for (i = 0; i < DL_HASH_ENTRIES; i++) | ||
| 634 | INIT_HLIST_HEAD(&dd->hash[i]); | ||
| 635 | |||
| 636 | INIT_LIST_HEAD(&dd->fifo_list[READ]); | 368 | INIT_LIST_HEAD(&dd->fifo_list[READ]); |
| 637 | INIT_LIST_HEAD(&dd->fifo_list[WRITE]); | 369 | INIT_LIST_HEAD(&dd->fifo_list[WRITE]); |
| 638 | dd->sort_list[READ] = RB_ROOT; | 370 | dd->sort_list[READ] = RB_ROOT; |
| @@ -645,39 +377,6 @@ static void *deadline_init_queue(request_queue_t *q, elevator_t *e) | |||
| 645 | return dd; | 377 | return dd; |
| 646 | } | 378 | } |
| 647 | 379 | ||
| 648 | static void deadline_put_request(request_queue_t *q, struct request *rq) | ||
| 649 | { | ||
| 650 | struct deadline_data *dd = q->elevator->elevator_data; | ||
| 651 | struct deadline_rq *drq = RQ_DATA(rq); | ||
| 652 | |||
| 653 | mempool_free(drq, dd->drq_pool); | ||
| 654 | rq->elevator_private = NULL; | ||
| 655 | } | ||
| 656 | |||
| 657 | static int | ||
| 658 | deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | ||
| 659 | gfp_t gfp_mask) | ||
| 660 | { | ||
| 661 | struct deadline_data *dd = q->elevator->elevator_data; | ||
| 662 | struct deadline_rq *drq; | ||
| 663 | |||
| 664 | drq = mempool_alloc(dd->drq_pool, gfp_mask); | ||
| 665 | if (drq) { | ||
| 666 | memset(drq, 0, sizeof(*drq)); | ||
| 667 | RB_CLEAR_NODE(&drq->rb_node); | ||
| 668 | drq->request = rq; | ||
| 669 | |||
| 670 | INIT_HLIST_NODE(&drq->hash); | ||
| 671 | |||
| 672 | INIT_LIST_HEAD(&drq->fifo); | ||
| 673 | |||
| 674 | rq->elevator_private = drq; | ||
| 675 | return 0; | ||
| 676 | } | ||
| 677 | |||
| 678 | return 1; | ||
| 679 | } | ||
| 680 | |||
| 681 | /* | 380 | /* |
| 682 | * sysfs parts below | 381 | * sysfs parts below |
| 683 | */ | 382 | */ |
| @@ -757,10 +456,8 @@ static struct elevator_type iosched_deadline = { | |||
| 757 | .elevator_dispatch_fn = deadline_dispatch_requests, | 456 | .elevator_dispatch_fn = deadline_dispatch_requests, |
| 758 | .elevator_add_req_fn = deadline_add_request, | 457 | .elevator_add_req_fn = deadline_add_request, |
| 759 | .elevator_queue_empty_fn = deadline_queue_empty, | 458 | .elevator_queue_empty_fn = deadline_queue_empty, |
| 760 | .elevator_former_req_fn = deadline_former_request, | 459 | .elevator_former_req_fn = elv_rb_former_request, |
| 761 | .elevator_latter_req_fn = deadline_latter_request, | 460 | .elevator_latter_req_fn = elv_rb_latter_request, |
| 762 | .elevator_set_req_fn = deadline_set_request, | ||
| 763 | .elevator_put_req_fn = deadline_put_request, | ||
| 764 | .elevator_init_fn = deadline_init_queue, | 461 | .elevator_init_fn = deadline_init_queue, |
| 765 | .elevator_exit_fn = deadline_exit_queue, | 462 | .elevator_exit_fn = deadline_exit_queue, |
| 766 | }, | 463 | }, |
| @@ -772,24 +469,11 @@ static struct elevator_type iosched_deadline = { | |||
| 772 | 469 | ||
| 773 | static int __init deadline_init(void) | 470 | static int __init deadline_init(void) |
| 774 | { | 471 | { |
| 775 | int ret; | 472 | return elv_register(&iosched_deadline); |
| 776 | |||
| 777 | drq_pool = kmem_cache_create("deadline_drq", sizeof(struct deadline_rq), | ||
| 778 | 0, 0, NULL, NULL); | ||
| 779 | |||
| 780 | if (!drq_pool) | ||
| 781 | return -ENOMEM; | ||
| 782 | |||
| 783 | ret = elv_register(&iosched_deadline); | ||
| 784 | if (ret) | ||
| 785 | kmem_cache_destroy(drq_pool); | ||
| 786 | |||
| 787 | return ret; | ||
| 788 | } | 473 | } |
| 789 | 474 | ||
| 790 | static void __exit deadline_exit(void) | 475 | static void __exit deadline_exit(void) |
| 791 | { | 476 | { |
| 792 | kmem_cache_destroy(drq_pool); | ||
| 793 | elv_unregister(&iosched_deadline); | 477 | elv_unregister(&iosched_deadline); |
| 794 | } | 478 | } |
| 795 | 479 | ||
diff --git a/block/elevator.c b/block/elevator.c index 9b72dc7c8a5c..487dd3da8853 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE | 4 | * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE |
| 5 | * | 5 | * |
| 6 | * 30042000 Jens Axboe <axboe@suse.de> : | 6 | * 30042000 Jens Axboe <axboe@kernel.dk> : |
| 7 | * | 7 | * |
| 8 | * Split the elevator a bit so that it is possible to choose a different | 8 | * Split the elevator a bit so that it is possible to choose a different |
| 9 | * one or even write a new "plug in". There are three pieces: | 9 | * one or even write a new "plug in". There are three pieces: |
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/compiler.h> | 33 | #include <linux/compiler.h> |
| 34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
| 35 | #include <linux/blktrace_api.h> | 35 | #include <linux/blktrace_api.h> |
| 36 | #include <linux/hash.h> | ||
| 36 | 37 | ||
| 37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
| 38 | 39 | ||
| @@ -40,6 +41,16 @@ static DEFINE_SPINLOCK(elv_list_lock); | |||
| 40 | static LIST_HEAD(elv_list); | 41 | static LIST_HEAD(elv_list); |
| 41 | 42 | ||
| 42 | /* | 43 | /* |
| 44 | * Merge hash stuff. | ||
| 45 | */ | ||
| 46 | static const int elv_hash_shift = 6; | ||
| 47 | #define ELV_HASH_BLOCK(sec) ((sec) >> 3) | ||
| 48 | #define ELV_HASH_FN(sec) (hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift)) | ||
| 49 | #define ELV_HASH_ENTRIES (1 << elv_hash_shift) | ||
| 50 | #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) | ||
| 51 | #define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash)) | ||
| 52 | |||
| 53 | /* | ||
| 43 | * can we safely merge with this request? | 54 | * can we safely merge with this request? |
| 44 | */ | 55 | */ |
| 45 | inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) | 56 | inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) |
| @@ -56,8 +67,7 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) | |||
| 56 | /* | 67 | /* |
| 57 | * same device and no special stuff set, merge is ok | 68 | * same device and no special stuff set, merge is ok |
| 58 | */ | 69 | */ |
| 59 | if (rq->rq_disk == bio->bi_bdev->bd_disk && | 70 | if (rq->rq_disk == bio->bi_bdev->bd_disk && !rq->special) |
| 60 | !rq->waiting && !rq->special) | ||
| 61 | return 1; | 71 | return 1; |
| 62 | 72 | ||
| 63 | return 0; | 73 | return 0; |
| @@ -151,27 +161,44 @@ __setup("elevator=", elevator_setup); | |||
| 151 | 161 | ||
| 152 | static struct kobj_type elv_ktype; | 162 | static struct kobj_type elv_ktype; |
| 153 | 163 | ||
| 154 | static elevator_t *elevator_alloc(struct elevator_type *e) | 164 | static elevator_t *elevator_alloc(request_queue_t *q, struct elevator_type *e) |
| 155 | { | 165 | { |
| 156 | elevator_t *eq = kmalloc(sizeof(elevator_t), GFP_KERNEL); | 166 | elevator_t *eq; |
| 157 | if (eq) { | 167 | int i; |
| 158 | memset(eq, 0, sizeof(*eq)); | 168 | |
| 159 | eq->ops = &e->ops; | 169 | eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL, q->node); |
| 160 | eq->elevator_type = e; | 170 | if (unlikely(!eq)) |
| 161 | kobject_init(&eq->kobj); | 171 | goto err; |
| 162 | snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); | 172 | |
| 163 | eq->kobj.ktype = &elv_ktype; | 173 | memset(eq, 0, sizeof(*eq)); |
| 164 | mutex_init(&eq->sysfs_lock); | 174 | eq->ops = &e->ops; |
| 165 | } else { | 175 | eq->elevator_type = e; |
| 166 | elevator_put(e); | 176 | kobject_init(&eq->kobj); |
| 167 | } | 177 | snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); |
| 178 | eq->kobj.ktype = &elv_ktype; | ||
| 179 | mutex_init(&eq->sysfs_lock); | ||
| 180 | |||
| 181 | eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES, | ||
| 182 | GFP_KERNEL, q->node); | ||
| 183 | if (!eq->hash) | ||
| 184 | goto err; | ||
| 185 | |||
| 186 | for (i = 0; i < ELV_HASH_ENTRIES; i++) | ||
| 187 | INIT_HLIST_HEAD(&eq->hash[i]); | ||
| 188 | |||
| 168 | return eq; | 189 | return eq; |
| 190 | err: | ||
| 191 | kfree(eq); | ||
| 192 | elevator_put(e); | ||
| 193 | return NULL; | ||
| 169 | } | 194 | } |
| 170 | 195 | ||
| 171 | static void elevator_release(struct kobject *kobj) | 196 | static void elevator_release(struct kobject *kobj) |
| 172 | { | 197 | { |
| 173 | elevator_t *e = container_of(kobj, elevator_t, kobj); | 198 | elevator_t *e = container_of(kobj, elevator_t, kobj); |
| 199 | |||
| 174 | elevator_put(e->elevator_type); | 200 | elevator_put(e->elevator_type); |
| 201 | kfree(e->hash); | ||
| 175 | kfree(e); | 202 | kfree(e); |
| 176 | } | 203 | } |
| 177 | 204 | ||
| @@ -198,7 +225,7 @@ int elevator_init(request_queue_t *q, char *name) | |||
| 198 | e = elevator_get("noop"); | 225 | e = elevator_get("noop"); |
| 199 | } | 226 | } |
| 200 | 227 | ||
| 201 | eq = elevator_alloc(e); | 228 | eq = elevator_alloc(q, e); |
| 202 | if (!eq) | 229 | if (!eq) |
| 203 | return -ENOMEM; | 230 | return -ENOMEM; |
| 204 | 231 | ||
| @@ -212,6 +239,8 @@ int elevator_init(request_queue_t *q, char *name) | |||
| 212 | return ret; | 239 | return ret; |
| 213 | } | 240 | } |
| 214 | 241 | ||
| 242 | EXPORT_SYMBOL(elevator_init); | ||
| 243 | |||
| 215 | void elevator_exit(elevator_t *e) | 244 | void elevator_exit(elevator_t *e) |
| 216 | { | 245 | { |
| 217 | mutex_lock(&e->sysfs_lock); | 246 | mutex_lock(&e->sysfs_lock); |
| @@ -223,10 +252,118 @@ void elevator_exit(elevator_t *e) | |||
| 223 | kobject_put(&e->kobj); | 252 | kobject_put(&e->kobj); |
| 224 | } | 253 | } |
| 225 | 254 | ||
| 255 | EXPORT_SYMBOL(elevator_exit); | ||
| 256 | |||
| 257 | static inline void __elv_rqhash_del(struct request *rq) | ||
| 258 | { | ||
| 259 | hlist_del_init(&rq->hash); | ||
| 260 | } | ||
| 261 | |||
| 262 | static void elv_rqhash_del(request_queue_t *q, struct request *rq) | ||
| 263 | { | ||
| 264 | if (ELV_ON_HASH(rq)) | ||
| 265 | __elv_rqhash_del(rq); | ||
| 266 | } | ||
| 267 | |||
| 268 | static void elv_rqhash_add(request_queue_t *q, struct request *rq) | ||
| 269 | { | ||
| 270 | elevator_t *e = q->elevator; | ||
| 271 | |||
| 272 | BUG_ON(ELV_ON_HASH(rq)); | ||
| 273 | hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]); | ||
| 274 | } | ||
| 275 | |||
| 276 | static void elv_rqhash_reposition(request_queue_t *q, struct request *rq) | ||
| 277 | { | ||
| 278 | __elv_rqhash_del(rq); | ||
| 279 | elv_rqhash_add(q, rq); | ||
| 280 | } | ||
| 281 | |||
| 282 | static struct request *elv_rqhash_find(request_queue_t *q, sector_t offset) | ||
| 283 | { | ||
| 284 | elevator_t *e = q->elevator; | ||
| 285 | struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)]; | ||
| 286 | struct hlist_node *entry, *next; | ||
| 287 | struct request *rq; | ||
| 288 | |||
| 289 | hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) { | ||
| 290 | BUG_ON(!ELV_ON_HASH(rq)); | ||
| 291 | |||
| 292 | if (unlikely(!rq_mergeable(rq))) { | ||
| 293 | __elv_rqhash_del(rq); | ||
| 294 | continue; | ||
| 295 | } | ||
| 296 | |||
| 297 | if (rq_hash_key(rq) == offset) | ||
| 298 | return rq; | ||
| 299 | } | ||
| 300 | |||
| 301 | return NULL; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * RB-tree support functions for inserting/lookup/removal of requests | ||
| 306 | * in a sorted RB tree. | ||
| 307 | */ | ||
| 308 | struct request *elv_rb_add(struct rb_root *root, struct request *rq) | ||
| 309 | { | ||
| 310 | struct rb_node **p = &root->rb_node; | ||
| 311 | struct rb_node *parent = NULL; | ||
| 312 | struct request *__rq; | ||
| 313 | |||
| 314 | while (*p) { | ||
| 315 | parent = *p; | ||
| 316 | __rq = rb_entry(parent, struct request, rb_node); | ||
| 317 | |||
| 318 | if (rq->sector < __rq->sector) | ||
| 319 | p = &(*p)->rb_left; | ||
| 320 | else if (rq->sector > __rq->sector) | ||
| 321 | p = &(*p)->rb_right; | ||
| 322 | else | ||
| 323 | return __rq; | ||
| 324 | } | ||
| 325 | |||
| 326 | rb_link_node(&rq->rb_node, parent, p); | ||
| 327 | rb_insert_color(&rq->rb_node, root); | ||
| 328 | return NULL; | ||
| 329 | } | ||
| 330 | |||
| 331 | EXPORT_SYMBOL(elv_rb_add); | ||
| 332 | |||
| 333 | void elv_rb_del(struct rb_root *root, struct request *rq) | ||
| 334 | { | ||
| 335 | BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); | ||
| 336 | rb_erase(&rq->rb_node, root); | ||
| 337 | RB_CLEAR_NODE(&rq->rb_node); | ||
| 338 | } | ||
| 339 | |||
| 340 | EXPORT_SYMBOL(elv_rb_del); | ||
| 341 | |||
| 342 | struct request *elv_rb_find(struct rb_root *root, sector_t sector) | ||
| 343 | { | ||
| 344 | struct rb_node *n = root->rb_node; | ||
| 345 | struct request *rq; | ||
| 346 | |||
| 347 | while (n) { | ||
| 348 | rq = rb_entry(n, struct request, rb_node); | ||
| 349 | |||
| 350 | if (sector < rq->sector) | ||
| 351 | n = n->rb_left; | ||
| 352 | else if (sector > rq->sector) | ||
| 353 | n = n->rb_right; | ||
| 354 | else | ||
| 355 | return rq; | ||
| 356 | } | ||
| 357 | |||
| 358 | return NULL; | ||
| 359 | } | ||
| 360 | |||
| 361 | EXPORT_SYMBOL(elv_rb_find); | ||
| 362 | |||
| 226 | /* | 363 | /* |
| 227 | * Insert rq into dispatch queue of q. Queue lock must be held on | 364 | * Insert rq into dispatch queue of q. Queue lock must be held on |
| 228 | * entry. If sort != 0, rq is sort-inserted; otherwise, rq will be | 365 | * entry. rq is sort insted into the dispatch queue. To be used by |
| 229 | * appended to the dispatch queue. To be used by specific elevators. | 366 | * specific elevators. |
| 230 | */ | 367 | */ |
| 231 | void elv_dispatch_sort(request_queue_t *q, struct request *rq) | 368 | void elv_dispatch_sort(request_queue_t *q, struct request *rq) |
| 232 | { | 369 | { |
| @@ -235,6 +372,9 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq) | |||
| 235 | 372 | ||
| 236 | if (q->last_merge == rq) | 373 | if (q->last_merge == rq) |
| 237 | q->last_merge = NULL; | 374 | q->last_merge = NULL; |
| 375 | |||
| 376 | elv_rqhash_del(q, rq); | ||
| 377 | |||
| 238 | q->nr_sorted--; | 378 | q->nr_sorted--; |
| 239 | 379 | ||
| 240 | boundary = q->end_sector; | 380 | boundary = q->end_sector; |
| @@ -242,7 +382,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq) | |||
| 242 | list_for_each_prev(entry, &q->queue_head) { | 382 | list_for_each_prev(entry, &q->queue_head) { |
| 243 | struct request *pos = list_entry_rq(entry); | 383 | struct request *pos = list_entry_rq(entry); |
| 244 | 384 | ||
| 245 | if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED)) | 385 | if (pos->cmd_flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED)) |
| 246 | break; | 386 | break; |
| 247 | if (rq->sector >= boundary) { | 387 | if (rq->sector >= boundary) { |
| 248 | if (pos->sector < boundary) | 388 | if (pos->sector < boundary) |
| @@ -258,11 +398,38 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq) | |||
| 258 | list_add(&rq->queuelist, entry); | 398 | list_add(&rq->queuelist, entry); |
| 259 | } | 399 | } |
| 260 | 400 | ||
| 401 | EXPORT_SYMBOL(elv_dispatch_sort); | ||
| 402 | |||
| 403 | /* | ||
| 404 | * Insert rq into dispatch queue of q. Queue lock must be held on | ||
| 405 | * entry. rq is added to the back of the dispatch queue. To be used by | ||
| 406 | * specific elevators. | ||
| 407 | */ | ||
| 408 | void elv_dispatch_add_tail(struct request_queue *q, struct request *rq) | ||
| 409 | { | ||
| 410 | if (q->last_merge == rq) | ||
| 411 | q->last_merge = NULL; | ||
| 412 | |||
| 413 | elv_rqhash_del(q, rq); | ||
| 414 | |||
| 415 | q->nr_sorted--; | ||
| 416 | |||
| 417 | q->end_sector = rq_end_sector(rq); | ||
| 418 | q->boundary_rq = rq; | ||
| 419 | list_add_tail(&rq->queuelist, &q->queue_head); | ||
| 420 | } | ||
| 421 | |||
| 422 | EXPORT_SYMBOL(elv_dispatch_add_tail); | ||
| 423 | |||
| 261 | int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) | 424 | int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) |
| 262 | { | 425 | { |
| 263 | elevator_t *e = q->elevator; | 426 | elevator_t *e = q->elevator; |
| 427 | struct request *__rq; | ||
| 264 | int ret; | 428 | int ret; |
| 265 | 429 | ||
| 430 | /* | ||
| 431 | * First try one-hit cache. | ||
| 432 | */ | ||
| 266 | if (q->last_merge) { | 433 | if (q->last_merge) { |
| 267 | ret = elv_try_merge(q->last_merge, bio); | 434 | ret = elv_try_merge(q->last_merge, bio); |
| 268 | if (ret != ELEVATOR_NO_MERGE) { | 435 | if (ret != ELEVATOR_NO_MERGE) { |
| @@ -271,18 +438,30 @@ int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) | |||
| 271 | } | 438 | } |
| 272 | } | 439 | } |
| 273 | 440 | ||
| 441 | /* | ||
| 442 | * See if our hash lookup can find a potential backmerge. | ||
| 443 | */ | ||
| 444 | __rq = elv_rqhash_find(q, bio->bi_sector); | ||
| 445 | if (__rq && elv_rq_merge_ok(__rq, bio)) { | ||
| 446 | *req = __rq; | ||
| 447 | return ELEVATOR_BACK_MERGE; | ||
| 448 | } | ||
| 449 | |||
| 274 | if (e->ops->elevator_merge_fn) | 450 | if (e->ops->elevator_merge_fn) |
| 275 | return e->ops->elevator_merge_fn(q, req, bio); | 451 | return e->ops->elevator_merge_fn(q, req, bio); |
| 276 | 452 | ||
| 277 | return ELEVATOR_NO_MERGE; | 453 | return ELEVATOR_NO_MERGE; |
| 278 | } | 454 | } |
| 279 | 455 | ||
| 280 | void elv_merged_request(request_queue_t *q, struct request *rq) | 456 | void elv_merged_request(request_queue_t *q, struct request *rq, int type) |
| 281 | { | 457 | { |
| 282 | elevator_t *e = q->elevator; | 458 | elevator_t *e = q->elevator; |
| 283 | 459 | ||
| 284 | if (e->ops->elevator_merged_fn) | 460 | if (e->ops->elevator_merged_fn) |
| 285 | e->ops->elevator_merged_fn(q, rq); | 461 | e->ops->elevator_merged_fn(q, rq, type); |
| 462 | |||
| 463 | if (type == ELEVATOR_BACK_MERGE) | ||
| 464 | elv_rqhash_reposition(q, rq); | ||
| 286 | 465 | ||
| 287 | q->last_merge = rq; | 466 | q->last_merge = rq; |
| 288 | } | 467 | } |
| @@ -294,8 +473,11 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, | |||
| 294 | 473 | ||
| 295 | if (e->ops->elevator_merge_req_fn) | 474 | if (e->ops->elevator_merge_req_fn) |
| 296 | e->ops->elevator_merge_req_fn(q, rq, next); | 475 | e->ops->elevator_merge_req_fn(q, rq, next); |
| 297 | q->nr_sorted--; | ||
| 298 | 476 | ||
| 477 | elv_rqhash_reposition(q, rq); | ||
| 478 | elv_rqhash_del(q, next); | ||
| 479 | |||
| 480 | q->nr_sorted--; | ||
| 299 | q->last_merge = rq; | 481 | q->last_merge = rq; |
| 300 | } | 482 | } |
| 301 | 483 | ||
| @@ -313,7 +495,7 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) | |||
| 313 | e->ops->elevator_deactivate_req_fn(q, rq); | 495 | e->ops->elevator_deactivate_req_fn(q, rq); |
| 314 | } | 496 | } |
| 315 | 497 | ||
| 316 | rq->flags &= ~REQ_STARTED; | 498 | rq->cmd_flags &= ~REQ_STARTED; |
| 317 | 499 | ||
| 318 | elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE); | 500 | elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE); |
| 319 | } | 501 | } |
| @@ -344,13 +526,13 @@ void elv_insert(request_queue_t *q, struct request *rq, int where) | |||
| 344 | 526 | ||
| 345 | switch (where) { | 527 | switch (where) { |
| 346 | case ELEVATOR_INSERT_FRONT: | 528 | case ELEVATOR_INSERT_FRONT: |
| 347 | rq->flags |= REQ_SOFTBARRIER; | 529 | rq->cmd_flags |= REQ_SOFTBARRIER; |
| 348 | 530 | ||
| 349 | list_add(&rq->queuelist, &q->queue_head); | 531 | list_add(&rq->queuelist, &q->queue_head); |
| 350 | break; | 532 | break; |
| 351 | 533 | ||
| 352 | case ELEVATOR_INSERT_BACK: | 534 | case ELEVATOR_INSERT_BACK: |
| 353 | rq->flags |= REQ_SOFTBARRIER; | 535 | rq->cmd_flags |= REQ_SOFTBARRIER; |
| 354 | elv_drain_elevator(q); | 536 | elv_drain_elevator(q); |
| 355 | list_add_tail(&rq->queuelist, &q->queue_head); | 537 | list_add_tail(&rq->queuelist, &q->queue_head); |
| 356 | /* | 538 | /* |
| @@ -369,10 +551,14 @@ void elv_insert(request_queue_t *q, struct request *rq, int where) | |||
| 369 | 551 | ||
| 370 | case ELEVATOR_INSERT_SORT: | 552 | case ELEVATOR_INSERT_SORT: |
| 371 | BUG_ON(!blk_fs_request(rq)); | 553 | BUG_ON(!blk_fs_request(rq)); |
| 372 | rq->flags |= REQ_SORTED; | 554 | rq->cmd_flags |= REQ_SORTED; |
| 373 | q->nr_sorted++; | 555 | q->nr_sorted++; |
| 374 | if (q->last_merge == NULL && rq_mergeable(rq)) | 556 | if (rq_mergeable(rq)) { |
| 375 | q->last_merge = rq; | 557 | elv_rqhash_add(q, rq); |
| 558 | if (!q->last_merge) | ||
| 559 | q->last_merge = rq; | ||
| 560 | } | ||
| 561 | |||
| 376 | /* | 562 | /* |
| 377 | * Some ioscheds (cfq) run q->request_fn directly, so | 563 | * Some ioscheds (cfq) run q->request_fn directly, so |
| 378 | * rq cannot be accessed after calling | 564 | * rq cannot be accessed after calling |
| @@ -387,7 +573,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where) | |||
| 387 | * insertion; otherwise, requests should be requeued | 573 | * insertion; otherwise, requests should be requeued |
| 388 | * in ordseq order. | 574 | * in ordseq order. |
| 389 | */ | 575 | */ |
| 390 | rq->flags |= REQ_SOFTBARRIER; | 576 | rq->cmd_flags |= REQ_SOFTBARRIER; |
| 391 | 577 | ||
| 392 | if (q->ordseq == 0) { | 578 | if (q->ordseq == 0) { |
| 393 | list_add(&rq->queuelist, &q->queue_head); | 579 | list_add(&rq->queuelist, &q->queue_head); |
| @@ -429,9 +615,9 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, | |||
| 429 | int plug) | 615 | int plug) |
| 430 | { | 616 | { |
| 431 | if (q->ordcolor) | 617 | if (q->ordcolor) |
| 432 | rq->flags |= REQ_ORDERED_COLOR; | 618 | rq->cmd_flags |= REQ_ORDERED_COLOR; |
| 433 | 619 | ||
| 434 | if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { | 620 | if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { |
| 435 | /* | 621 | /* |
| 436 | * toggle ordered color | 622 | * toggle ordered color |
| 437 | */ | 623 | */ |
| @@ -452,7 +638,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, | |||
| 452 | q->end_sector = rq_end_sector(rq); | 638 | q->end_sector = rq_end_sector(rq); |
| 453 | q->boundary_rq = rq; | 639 | q->boundary_rq = rq; |
| 454 | } | 640 | } |
| 455 | } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT) | 641 | } else if (!(rq->cmd_flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT) |
| 456 | where = ELEVATOR_INSERT_BACK; | 642 | where = ELEVATOR_INSERT_BACK; |
| 457 | 643 | ||
| 458 | if (plug) | 644 | if (plug) |
| @@ -461,6 +647,8 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, | |||
| 461 | elv_insert(q, rq, where); | 647 | elv_insert(q, rq, where); |
| 462 | } | 648 | } |
| 463 | 649 | ||
| 650 | EXPORT_SYMBOL(__elv_add_request); | ||
| 651 | |||
| 464 | void elv_add_request(request_queue_t *q, struct request *rq, int where, | 652 | void elv_add_request(request_queue_t *q, struct request *rq, int where, |
| 465 | int plug) | 653 | int plug) |
| 466 | { | 654 | { |
| @@ -471,6 +659,8 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where, | |||
| 471 | spin_unlock_irqrestore(q->queue_lock, flags); | 659 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 472 | } | 660 | } |
| 473 | 661 | ||
| 662 | EXPORT_SYMBOL(elv_add_request); | ||
| 663 | |||
| 474 | static inline struct request *__elv_next_request(request_queue_t *q) | 664 | static inline struct request *__elv_next_request(request_queue_t *q) |
| 475 | { | 665 | { |
| 476 | struct request *rq; | 666 | struct request *rq; |
| @@ -493,7 +683,7 @@ struct request *elv_next_request(request_queue_t *q) | |||
| 493 | int ret; | 683 | int ret; |
| 494 | 684 | ||
| 495 | while ((rq = __elv_next_request(q)) != NULL) { | 685 | while ((rq = __elv_next_request(q)) != NULL) { |
| 496 | if (!(rq->flags & REQ_STARTED)) { | 686 | if (!(rq->cmd_flags & REQ_STARTED)) { |
| 497 | elevator_t *e = q->elevator; | 687 | elevator_t *e = q->elevator; |
| 498 | 688 | ||
| 499 | /* | 689 | /* |
| @@ -510,7 +700,7 @@ struct request *elv_next_request(request_queue_t *q) | |||
| 510 | * it, a request that has been delayed should | 700 | * it, a request that has been delayed should |
| 511 | * not be passed by new incoming requests | 701 | * not be passed by new incoming requests |
| 512 | */ | 702 | */ |
| 513 | rq->flags |= REQ_STARTED; | 703 | rq->cmd_flags |= REQ_STARTED; |
| 514 | blk_add_trace_rq(q, rq, BLK_TA_ISSUE); | 704 | blk_add_trace_rq(q, rq, BLK_TA_ISSUE); |
| 515 | } | 705 | } |
| 516 | 706 | ||
| @@ -519,7 +709,7 @@ struct request *elv_next_request(request_queue_t *q) | |||
| 519 | q->boundary_rq = NULL; | 709 | q->boundary_rq = NULL; |
| 520 | } | 710 | } |
| 521 | 711 | ||
| 522 | if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn) | 712 | if ((rq->cmd_flags & REQ_DONTPREP) || !q->prep_rq_fn) |
| 523 | break; | 713 | break; |
| 524 | 714 | ||
| 525 | ret = q->prep_rq_fn(q, rq); | 715 | ret = q->prep_rq_fn(q, rq); |
| @@ -541,7 +731,7 @@ struct request *elv_next_request(request_queue_t *q) | |||
| 541 | nr_bytes = rq->data_len; | 731 | nr_bytes = rq->data_len; |
| 542 | 732 | ||
| 543 | blkdev_dequeue_request(rq); | 733 | blkdev_dequeue_request(rq); |
| 544 | rq->flags |= REQ_QUIET; | 734 | rq->cmd_flags |= REQ_QUIET; |
| 545 | end_that_request_chunk(rq, 0, nr_bytes); | 735 | end_that_request_chunk(rq, 0, nr_bytes); |
| 546 | end_that_request_last(rq, 0); | 736 | end_that_request_last(rq, 0); |
| 547 | } else { | 737 | } else { |
| @@ -554,9 +744,12 @@ struct request *elv_next_request(request_queue_t *q) | |||
| 554 | return rq; | 744 | return rq; |
| 555 | } | 745 | } |
| 556 | 746 | ||
| 747 | EXPORT_SYMBOL(elv_next_request); | ||
| 748 | |||
| 557 | void elv_dequeue_request(request_queue_t *q, struct request *rq) | 749 | void elv_dequeue_request(request_queue_t *q, struct request *rq) |
| 558 | { | 750 | { |
| 559 | BUG_ON(list_empty(&rq->queuelist)); | 751 | BUG_ON(list_empty(&rq->queuelist)); |
| 752 | BUG_ON(ELV_ON_HASH(rq)); | ||
| 560 | 753 | ||
| 561 | list_del_init(&rq->queuelist); | 754 | list_del_init(&rq->queuelist); |
| 562 | 755 | ||
| @@ -569,6 +762,8 @@ void elv_dequeue_request(request_queue_t *q, struct request *rq) | |||
| 569 | q->in_flight++; | 762 | q->in_flight++; |
| 570 | } | 763 | } |
| 571 | 764 | ||
| 765 | EXPORT_SYMBOL(elv_dequeue_request); | ||
| 766 | |||
| 572 | int elv_queue_empty(request_queue_t *q) | 767 | int elv_queue_empty(request_queue_t *q) |
| 573 | { | 768 | { |
| 574 | elevator_t *e = q->elevator; | 769 | elevator_t *e = q->elevator; |
| @@ -582,6 +777,8 @@ int elv_queue_empty(request_queue_t *q) | |||
| 582 | return 1; | 777 | return 1; |
| 583 | } | 778 | } |
| 584 | 779 | ||
| 780 | EXPORT_SYMBOL(elv_queue_empty); | ||
| 781 | |||
| 585 | struct request *elv_latter_request(request_queue_t *q, struct request *rq) | 782 | struct request *elv_latter_request(request_queue_t *q, struct request *rq) |
| 586 | { | 783 | { |
| 587 | elevator_t *e = q->elevator; | 784 | elevator_t *e = q->elevator; |
| @@ -600,13 +797,12 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq) | |||
| 600 | return NULL; | 797 | return NULL; |
| 601 | } | 798 | } |
| 602 | 799 | ||
| 603 | int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | 800 | int elv_set_request(request_queue_t *q, struct request *rq, gfp_t gfp_mask) |
| 604 | gfp_t gfp_mask) | ||
| 605 | { | 801 | { |
| 606 | elevator_t *e = q->elevator; | 802 | elevator_t *e = q->elevator; |
| 607 | 803 | ||
| 608 | if (e->ops->elevator_set_req_fn) | 804 | if (e->ops->elevator_set_req_fn) |
| 609 | return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask); | 805 | return e->ops->elevator_set_req_fn(q, rq, gfp_mask); |
| 610 | 806 | ||
| 611 | rq->elevator_private = NULL; | 807 | rq->elevator_private = NULL; |
| 612 | return 0; | 808 | return 0; |
| @@ -620,12 +816,12 @@ void elv_put_request(request_queue_t *q, struct request *rq) | |||
| 620 | e->ops->elevator_put_req_fn(q, rq); | 816 | e->ops->elevator_put_req_fn(q, rq); |
| 621 | } | 817 | } |
| 622 | 818 | ||
| 623 | int elv_may_queue(request_queue_t *q, int rw, struct bio *bio) | 819 | int elv_may_queue(request_queue_t *q, int rw) |
| 624 | { | 820 | { |
| 625 | elevator_t *e = q->elevator; | 821 | elevator_t *e = q->elevator; |
| 626 | 822 | ||
| 627 | if (e->ops->elevator_may_queue_fn) | 823 | if (e->ops->elevator_may_queue_fn) |
| 628 | return e->ops->elevator_may_queue_fn(q, rw, bio); | 824 | return e->ops->elevator_may_queue_fn(q, rw); |
| 629 | 825 | ||
| 630 | return ELV_MQUEUE_MAY; | 826 | return ELV_MQUEUE_MAY; |
| 631 | } | 827 | } |
| @@ -792,7 +988,7 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e) | |||
| 792 | /* | 988 | /* |
| 793 | * Allocate new elevator | 989 | * Allocate new elevator |
| 794 | */ | 990 | */ |
| 795 | e = elevator_alloc(new_e); | 991 | e = elevator_alloc(q, new_e); |
| 796 | if (!e) | 992 | if (!e) |
| 797 | return 0; | 993 | return 0; |
| 798 | 994 | ||
| @@ -908,11 +1104,26 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name) | |||
| 908 | return len; | 1104 | return len; |
| 909 | } | 1105 | } |
| 910 | 1106 | ||
| 911 | EXPORT_SYMBOL(elv_dispatch_sort); | 1107 | struct request *elv_rb_former_request(request_queue_t *q, struct request *rq) |
| 912 | EXPORT_SYMBOL(elv_add_request); | 1108 | { |
| 913 | EXPORT_SYMBOL(__elv_add_request); | 1109 | struct rb_node *rbprev = rb_prev(&rq->rb_node); |
| 914 | EXPORT_SYMBOL(elv_next_request); | 1110 | |
| 915 | EXPORT_SYMBOL(elv_dequeue_request); | 1111 | if (rbprev) |
| 916 | EXPORT_SYMBOL(elv_queue_empty); | 1112 | return rb_entry_rq(rbprev); |
| 917 | EXPORT_SYMBOL(elevator_exit); | 1113 | |
| 918 | EXPORT_SYMBOL(elevator_init); | 1114 | return NULL; |
| 1115 | } | ||
| 1116 | |||
| 1117 | EXPORT_SYMBOL(elv_rb_former_request); | ||
| 1118 | |||
| 1119 | struct request *elv_rb_latter_request(request_queue_t *q, struct request *rq) | ||
| 1120 | { | ||
| 1121 | struct rb_node *rbnext = rb_next(&rq->rb_node); | ||
| 1122 | |||
| 1123 | if (rbnext) | ||
| 1124 | return rb_entry_rq(rbnext); | ||
| 1125 | |||
| 1126 | return NULL; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | EXPORT_SYMBOL(elv_rb_latter_request); | ||
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 51dc0edf76e0..83425fb3c8db 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
| @@ -39,6 +39,7 @@ static void blk_unplug_timeout(unsigned long data); | |||
| 39 | static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); | 39 | static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); |
| 40 | static void init_request_from_bio(struct request *req, struct bio *bio); | 40 | static void init_request_from_bio(struct request *req, struct bio *bio); |
| 41 | static int __make_request(request_queue_t *q, struct bio *bio); | 41 | static int __make_request(request_queue_t *q, struct bio *bio); |
| 42 | static struct io_context *current_io_context(gfp_t gfp_flags, int node); | ||
| 42 | 43 | ||
| 43 | /* | 44 | /* |
| 44 | * For the allocated request tables | 45 | * For the allocated request tables |
| @@ -277,19 +278,19 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) | |||
| 277 | 278 | ||
| 278 | EXPORT_SYMBOL(blk_queue_make_request); | 279 | EXPORT_SYMBOL(blk_queue_make_request); |
| 279 | 280 | ||
| 280 | static inline void rq_init(request_queue_t *q, struct request *rq) | 281 | static void rq_init(request_queue_t *q, struct request *rq) |
| 281 | { | 282 | { |
| 282 | INIT_LIST_HEAD(&rq->queuelist); | 283 | INIT_LIST_HEAD(&rq->queuelist); |
| 283 | INIT_LIST_HEAD(&rq->donelist); | 284 | INIT_LIST_HEAD(&rq->donelist); |
| 284 | 285 | ||
| 285 | rq->errors = 0; | 286 | rq->errors = 0; |
| 286 | rq->rq_status = RQ_ACTIVE; | ||
| 287 | rq->bio = rq->biotail = NULL; | 287 | rq->bio = rq->biotail = NULL; |
| 288 | INIT_HLIST_NODE(&rq->hash); | ||
| 289 | RB_CLEAR_NODE(&rq->rb_node); | ||
| 288 | rq->ioprio = 0; | 290 | rq->ioprio = 0; |
| 289 | rq->buffer = NULL; | 291 | rq->buffer = NULL; |
| 290 | rq->ref_count = 1; | 292 | rq->ref_count = 1; |
| 291 | rq->q = q; | 293 | rq->q = q; |
| 292 | rq->waiting = NULL; | ||
| 293 | rq->special = NULL; | 294 | rq->special = NULL; |
| 294 | rq->data_len = 0; | 295 | rq->data_len = 0; |
| 295 | rq->data = NULL; | 296 | rq->data = NULL; |
| @@ -382,8 +383,8 @@ unsigned blk_ordered_req_seq(struct request *rq) | |||
| 382 | if (rq == &q->post_flush_rq) | 383 | if (rq == &q->post_flush_rq) |
| 383 | return QUEUE_ORDSEQ_POSTFLUSH; | 384 | return QUEUE_ORDSEQ_POSTFLUSH; |
| 384 | 385 | ||
| 385 | if ((rq->flags & REQ_ORDERED_COLOR) == | 386 | if ((rq->cmd_flags & REQ_ORDERED_COLOR) == |
| 386 | (q->orig_bar_rq->flags & REQ_ORDERED_COLOR)) | 387 | (q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR)) |
| 387 | return QUEUE_ORDSEQ_DRAIN; | 388 | return QUEUE_ORDSEQ_DRAIN; |
| 388 | else | 389 | else |
| 389 | return QUEUE_ORDSEQ_DONE; | 390 | return QUEUE_ORDSEQ_DONE; |
| @@ -446,11 +447,11 @@ static void queue_flush(request_queue_t *q, unsigned which) | |||
| 446 | end_io = post_flush_end_io; | 447 | end_io = post_flush_end_io; |
| 447 | } | 448 | } |
| 448 | 449 | ||
| 450 | rq->cmd_flags = REQ_HARDBARRIER; | ||
| 449 | rq_init(q, rq); | 451 | rq_init(q, rq); |
| 450 | rq->flags = REQ_HARDBARRIER; | ||
| 451 | rq->elevator_private = NULL; | 452 | rq->elevator_private = NULL; |
| 453 | rq->elevator_private2 = NULL; | ||
| 452 | rq->rq_disk = q->bar_rq.rq_disk; | 454 | rq->rq_disk = q->bar_rq.rq_disk; |
| 453 | rq->rl = NULL; | ||
| 454 | rq->end_io = end_io; | 455 | rq->end_io = end_io; |
| 455 | q->prepare_flush_fn(q, rq); | 456 | q->prepare_flush_fn(q, rq); |
| 456 | 457 | ||
| @@ -471,11 +472,13 @@ static inline struct request *start_ordered(request_queue_t *q, | |||
| 471 | blkdev_dequeue_request(rq); | 472 | blkdev_dequeue_request(rq); |
| 472 | q->orig_bar_rq = rq; | 473 | q->orig_bar_rq = rq; |
| 473 | rq = &q->bar_rq; | 474 | rq = &q->bar_rq; |
| 475 | rq->cmd_flags = 0; | ||
| 474 | rq_init(q, rq); | 476 | rq_init(q, rq); |
| 475 | rq->flags = bio_data_dir(q->orig_bar_rq->bio); | 477 | if (bio_data_dir(q->orig_bar_rq->bio) == WRITE) |
| 476 | rq->flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0; | 478 | rq->cmd_flags |= REQ_RW; |
| 479 | rq->cmd_flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0; | ||
| 477 | rq->elevator_private = NULL; | 480 | rq->elevator_private = NULL; |
| 478 | rq->rl = NULL; | 481 | rq->elevator_private2 = NULL; |
| 479 | init_request_from_bio(rq, q->orig_bar_rq->bio); | 482 | init_request_from_bio(rq, q->orig_bar_rq->bio); |
| 480 | rq->end_io = bar_end_io; | 483 | rq->end_io = bar_end_io; |
| 481 | 484 | ||
| @@ -587,8 +590,8 @@ static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error) | |||
| 587 | return 0; | 590 | return 0; |
| 588 | } | 591 | } |
| 589 | 592 | ||
| 590 | static inline int ordered_bio_endio(struct request *rq, struct bio *bio, | 593 | static int ordered_bio_endio(struct request *rq, struct bio *bio, |
| 591 | unsigned int nbytes, int error) | 594 | unsigned int nbytes, int error) |
| 592 | { | 595 | { |
| 593 | request_queue_t *q = rq->q; | 596 | request_queue_t *q = rq->q; |
| 594 | bio_end_io_t *endio; | 597 | bio_end_io_t *endio; |
| @@ -1124,7 +1127,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) | |||
| 1124 | } | 1127 | } |
| 1125 | 1128 | ||
| 1126 | list_del_init(&rq->queuelist); | 1129 | list_del_init(&rq->queuelist); |
| 1127 | rq->flags &= ~REQ_QUEUED; | 1130 | rq->cmd_flags &= ~REQ_QUEUED; |
| 1128 | rq->tag = -1; | 1131 | rq->tag = -1; |
| 1129 | 1132 | ||
| 1130 | if (unlikely(bqt->tag_index[tag] == NULL)) | 1133 | if (unlikely(bqt->tag_index[tag] == NULL)) |
| @@ -1160,7 +1163,7 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq) | |||
| 1160 | struct blk_queue_tag *bqt = q->queue_tags; | 1163 | struct blk_queue_tag *bqt = q->queue_tags; |
| 1161 | int tag; | 1164 | int tag; |
| 1162 | 1165 | ||
| 1163 | if (unlikely((rq->flags & REQ_QUEUED))) { | 1166 | if (unlikely((rq->cmd_flags & REQ_QUEUED))) { |
| 1164 | printk(KERN_ERR | 1167 | printk(KERN_ERR |
| 1165 | "%s: request %p for device [%s] already tagged %d", | 1168 | "%s: request %p for device [%s] already tagged %d", |
| 1166 | __FUNCTION__, rq, | 1169 | __FUNCTION__, rq, |
| @@ -1168,13 +1171,18 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq) | |||
| 1168 | BUG(); | 1171 | BUG(); |
| 1169 | } | 1172 | } |
| 1170 | 1173 | ||
| 1171 | tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); | 1174 | /* |
| 1172 | if (tag >= bqt->max_depth) | 1175 | * Protect against shared tag maps, as we may not have exclusive |
| 1173 | return 1; | 1176 | * access to the tag map. |
| 1177 | */ | ||
| 1178 | do { | ||
| 1179 | tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); | ||
| 1180 | if (tag >= bqt->max_depth) | ||
| 1181 | return 1; | ||
| 1174 | 1182 | ||
| 1175 | __set_bit(tag, bqt->tag_map); | 1183 | } while (test_and_set_bit(tag, bqt->tag_map)); |
| 1176 | 1184 | ||
| 1177 | rq->flags |= REQ_QUEUED; | 1185 | rq->cmd_flags |= REQ_QUEUED; |
| 1178 | rq->tag = tag; | 1186 | rq->tag = tag; |
| 1179 | bqt->tag_index[tag] = rq; | 1187 | bqt->tag_index[tag] = rq; |
| 1180 | blkdev_dequeue_request(rq); | 1188 | blkdev_dequeue_request(rq); |
| @@ -1210,65 +1218,31 @@ void blk_queue_invalidate_tags(request_queue_t *q) | |||
| 1210 | printk(KERN_ERR | 1218 | printk(KERN_ERR |
| 1211 | "%s: bad tag found on list\n", __FUNCTION__); | 1219 | "%s: bad tag found on list\n", __FUNCTION__); |
| 1212 | list_del_init(&rq->queuelist); | 1220 | list_del_init(&rq->queuelist); |
| 1213 | rq->flags &= ~REQ_QUEUED; | 1221 | rq->cmd_flags &= ~REQ_QUEUED; |
| 1214 | } else | 1222 | } else |
| 1215 | blk_queue_end_tag(q, rq); | 1223 | blk_queue_end_tag(q, rq); |
| 1216 | 1224 | ||
| 1217 | rq->flags &= ~REQ_STARTED; | 1225 | rq->cmd_flags &= ~REQ_STARTED; |
| 1218 | __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); | 1226 | __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); |
| 1219 | } | 1227 | } |
| 1220 | } | 1228 | } |
| 1221 | 1229 | ||
| 1222 | EXPORT_SYMBOL(blk_queue_invalidate_tags); | 1230 | EXPORT_SYMBOL(blk_queue_invalidate_tags); |
| 1223 | 1231 | ||
| 1224 | static const char * const rq_flags[] = { | ||
| 1225 | "REQ_RW", | ||
| 1226 | "REQ_FAILFAST", | ||
| 1227 | "REQ_SORTED", | ||
| 1228 | "REQ_SOFTBARRIER", | ||
| 1229 | "REQ_HARDBARRIER", | ||
| 1230 | "REQ_FUA", | ||
| 1231 | "REQ_CMD", | ||
| 1232 | "REQ_NOMERGE", | ||
| 1233 | "REQ_STARTED", | ||
| 1234 | "REQ_DONTPREP", | ||
| 1235 | "REQ_QUEUED", | ||
| 1236 | "REQ_ELVPRIV", | ||
| 1237 | "REQ_PC", | ||
| 1238 | "REQ_BLOCK_PC", | ||
| 1239 | "REQ_SENSE", | ||
| 1240 | "REQ_FAILED", | ||
| 1241 | "REQ_QUIET", | ||
| 1242 | "REQ_SPECIAL", | ||
| 1243 | "REQ_DRIVE_CMD", | ||
| 1244 | "REQ_DRIVE_TASK", | ||
| 1245 | "REQ_DRIVE_TASKFILE", | ||
| 1246 | "REQ_PREEMPT", | ||
| 1247 | "REQ_PM_SUSPEND", | ||
| 1248 | "REQ_PM_RESUME", | ||
| 1249 | "REQ_PM_SHUTDOWN", | ||
| 1250 | "REQ_ORDERED_COLOR", | ||
| 1251 | }; | ||
| 1252 | |||
| 1253 | void blk_dump_rq_flags(struct request *rq, char *msg) | 1232 | void blk_dump_rq_flags(struct request *rq, char *msg) |
| 1254 | { | 1233 | { |
| 1255 | int bit; | 1234 | int bit; |
| 1256 | 1235 | ||
| 1257 | printk("%s: dev %s: flags = ", msg, | 1236 | printk("%s: dev %s: type=%x, flags=%x\n", msg, |
| 1258 | rq->rq_disk ? rq->rq_disk->disk_name : "?"); | 1237 | rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->cmd_type, |
| 1259 | bit = 0; | 1238 | rq->cmd_flags); |
| 1260 | do { | ||
| 1261 | if (rq->flags & (1 << bit)) | ||
| 1262 | printk("%s ", rq_flags[bit]); | ||
| 1263 | bit++; | ||
| 1264 | } while (bit < __REQ_NR_BITS); | ||
| 1265 | 1239 | ||
| 1266 | printk("\nsector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector, | 1240 | printk("\nsector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector, |
| 1267 | rq->nr_sectors, | 1241 | rq->nr_sectors, |
| 1268 | rq->current_nr_sectors); | 1242 | rq->current_nr_sectors); |
| 1269 | printk("bio %p, biotail %p, buffer %p, data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->data, rq->data_len); | 1243 | printk("bio %p, biotail %p, buffer %p, data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->data, rq->data_len); |
| 1270 | 1244 | ||
| 1271 | if (rq->flags & (REQ_BLOCK_PC | REQ_PC)) { | 1245 | if (blk_pc_request(rq)) { |
| 1272 | printk("cdb: "); | 1246 | printk("cdb: "); |
| 1273 | for (bit = 0; bit < sizeof(rq->cmd); bit++) | 1247 | for (bit = 0; bit < sizeof(rq->cmd); bit++) |
| 1274 | printk("%02x ", rq->cmd[bit]); | 1248 | printk("%02x ", rq->cmd[bit]); |
| @@ -1441,7 +1415,7 @@ static inline int ll_new_mergeable(request_queue_t *q, | |||
| 1441 | int nr_phys_segs = bio_phys_segments(q, bio); | 1415 | int nr_phys_segs = bio_phys_segments(q, bio); |
| 1442 | 1416 | ||
| 1443 | if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { | 1417 | if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { |
| 1444 | req->flags |= REQ_NOMERGE; | 1418 | req->cmd_flags |= REQ_NOMERGE; |
| 1445 | if (req == q->last_merge) | 1419 | if (req == q->last_merge) |
| 1446 | q->last_merge = NULL; | 1420 | q->last_merge = NULL; |
| 1447 | return 0; | 1421 | return 0; |
| @@ -1464,7 +1438,7 @@ static inline int ll_new_hw_segment(request_queue_t *q, | |||
| 1464 | 1438 | ||
| 1465 | if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments | 1439 | if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments |
| 1466 | || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { | 1440 | || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { |
| 1467 | req->flags |= REQ_NOMERGE; | 1441 | req->cmd_flags |= REQ_NOMERGE; |
| 1468 | if (req == q->last_merge) | 1442 | if (req == q->last_merge) |
| 1469 | q->last_merge = NULL; | 1443 | q->last_merge = NULL; |
| 1470 | return 0; | 1444 | return 0; |
| @@ -1491,7 +1465,7 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req, | |||
| 1491 | max_sectors = q->max_sectors; | 1465 | max_sectors = q->max_sectors; |
| 1492 | 1466 | ||
| 1493 | if (req->nr_sectors + bio_sectors(bio) > max_sectors) { | 1467 | if (req->nr_sectors + bio_sectors(bio) > max_sectors) { |
| 1494 | req->flags |= REQ_NOMERGE; | 1468 | req->cmd_flags |= REQ_NOMERGE; |
| 1495 | if (req == q->last_merge) | 1469 | if (req == q->last_merge) |
| 1496 | q->last_merge = NULL; | 1470 | q->last_merge = NULL; |
| 1497 | return 0; | 1471 | return 0; |
| @@ -1530,7 +1504,7 @@ static int ll_front_merge_fn(request_queue_t *q, struct request *req, | |||
| 1530 | 1504 | ||
| 1531 | 1505 | ||
| 1532 | if (req->nr_sectors + bio_sectors(bio) > max_sectors) { | 1506 | if (req->nr_sectors + bio_sectors(bio) > max_sectors) { |
| 1533 | req->flags |= REQ_NOMERGE; | 1507 | req->cmd_flags |= REQ_NOMERGE; |
| 1534 | if (req == q->last_merge) | 1508 | if (req == q->last_merge) |
| 1535 | q->last_merge = NULL; | 1509 | q->last_merge = NULL; |
| 1536 | return 0; | 1510 | return 0; |
| @@ -2029,14 +2003,13 @@ EXPORT_SYMBOL(blk_get_queue); | |||
| 2029 | 2003 | ||
| 2030 | static inline void blk_free_request(request_queue_t *q, struct request *rq) | 2004 | static inline void blk_free_request(request_queue_t *q, struct request *rq) |
| 2031 | { | 2005 | { |
| 2032 | if (rq->flags & REQ_ELVPRIV) | 2006 | if (rq->cmd_flags & REQ_ELVPRIV) |
| 2033 | elv_put_request(q, rq); | 2007 | elv_put_request(q, rq); |
| 2034 | mempool_free(rq, q->rq.rq_pool); | 2008 | mempool_free(rq, q->rq.rq_pool); |
| 2035 | } | 2009 | } |
| 2036 | 2010 | ||
| 2037 | static inline struct request * | 2011 | static struct request * |
| 2038 | blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, | 2012 | blk_alloc_request(request_queue_t *q, int rw, int priv, gfp_t gfp_mask) |
| 2039 | int priv, gfp_t gfp_mask) | ||
| 2040 | { | 2013 | { |
| 2041 | struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); | 2014 | struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); |
| 2042 | 2015 | ||
| @@ -2044,17 +2017,17 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, | |||
| 2044 | return NULL; | 2017 | return NULL; |
| 2045 | 2018 | ||
| 2046 | /* | 2019 | /* |
| 2047 | * first three bits are identical in rq->flags and bio->bi_rw, | 2020 | * first three bits are identical in rq->cmd_flags and bio->bi_rw, |
| 2048 | * see bio.h and blkdev.h | 2021 | * see bio.h and blkdev.h |
| 2049 | */ | 2022 | */ |
| 2050 | rq->flags = rw; | 2023 | rq->cmd_flags = rw | REQ_ALLOCED; |
| 2051 | 2024 | ||
| 2052 | if (priv) { | 2025 | if (priv) { |
| 2053 | if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) { | 2026 | if (unlikely(elv_set_request(q, rq, gfp_mask))) { |
| 2054 | mempool_free(rq, q->rq.rq_pool); | 2027 | mempool_free(rq, q->rq.rq_pool); |
| 2055 | return NULL; | 2028 | return NULL; |
| 2056 | } | 2029 | } |
| 2057 | rq->flags |= REQ_ELVPRIV; | 2030 | rq->cmd_flags |= REQ_ELVPRIV; |
| 2058 | } | 2031 | } |
| 2059 | 2032 | ||
| 2060 | return rq; | 2033 | return rq; |
| @@ -2141,13 +2114,13 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, | |||
| 2141 | struct io_context *ioc = NULL; | 2114 | struct io_context *ioc = NULL; |
| 2142 | int may_queue, priv; | 2115 | int may_queue, priv; |
| 2143 | 2116 | ||
| 2144 | may_queue = elv_may_queue(q, rw, bio); | 2117 | may_queue = elv_may_queue(q, rw); |
| 2145 | if (may_queue == ELV_MQUEUE_NO) | 2118 | if (may_queue == ELV_MQUEUE_NO) |
| 2146 | goto rq_starved; | 2119 | goto rq_starved; |
| 2147 | 2120 | ||
| 2148 | if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) { | 2121 | if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) { |
| 2149 | if (rl->count[rw]+1 >= q->nr_requests) { | 2122 | if (rl->count[rw]+1 >= q->nr_requests) { |
| 2150 | ioc = current_io_context(GFP_ATOMIC); | 2123 | ioc = current_io_context(GFP_ATOMIC, q->node); |
| 2151 | /* | 2124 | /* |
| 2152 | * The queue will fill after this allocation, so set | 2125 | * The queue will fill after this allocation, so set |
| 2153 | * it as full, and mark this process as "batching". | 2126 | * it as full, and mark this process as "batching". |
| @@ -2189,7 +2162,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, | |||
| 2189 | 2162 | ||
| 2190 | spin_unlock_irq(q->queue_lock); | 2163 | spin_unlock_irq(q->queue_lock); |
| 2191 | 2164 | ||
| 2192 | rq = blk_alloc_request(q, rw, bio, priv, gfp_mask); | 2165 | rq = blk_alloc_request(q, rw, priv, gfp_mask); |
| 2193 | if (unlikely(!rq)) { | 2166 | if (unlikely(!rq)) { |
| 2194 | /* | 2167 | /* |
| 2195 | * Allocation failed presumably due to memory. Undo anything | 2168 | * Allocation failed presumably due to memory. Undo anything |
| @@ -2225,7 +2198,6 @@ rq_starved: | |||
| 2225 | ioc->nr_batch_requests--; | 2198 | ioc->nr_batch_requests--; |
| 2226 | 2199 | ||
| 2227 | rq_init(q, rq); | 2200 | rq_init(q, rq); |
| 2228 | rq->rl = rl; | ||
| 2229 | 2201 | ||
| 2230 | blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ); | 2202 | blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ); |
| 2231 | out: | 2203 | out: |
| @@ -2268,7 +2240,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw, | |||
| 2268 | * up to a big batch of them for a small period time. | 2240 | * up to a big batch of them for a small period time. |
| 2269 | * See ioc_batching, ioc_set_batching | 2241 | * See ioc_batching, ioc_set_batching |
| 2270 | */ | 2242 | */ |
| 2271 | ioc = current_io_context(GFP_NOIO); | 2243 | ioc = current_io_context(GFP_NOIO, q->node); |
| 2272 | ioc_set_batching(q, ioc); | 2244 | ioc_set_batching(q, ioc); |
| 2273 | 2245 | ||
| 2274 | spin_lock_irq(q->queue_lock); | 2246 | spin_lock_irq(q->queue_lock); |
| @@ -2300,6 +2272,25 @@ struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask) | |||
| 2300 | EXPORT_SYMBOL(blk_get_request); | 2272 | EXPORT_SYMBOL(blk_get_request); |
| 2301 | 2273 | ||
| 2302 | /** | 2274 | /** |
| 2275 | * blk_start_queueing - initiate dispatch of requests to device | ||
| 2276 | * @q: request queue to kick into gear | ||
| 2277 | * | ||
| 2278 | * This is basically a helper to remove the need to know whether a queue | ||
| 2279 | * is plugged or not if someone just wants to initiate dispatch of requests | ||
| 2280 | * for this queue. | ||
| 2281 | * | ||
| 2282 | * The queue lock must be held with interrupts disabled. | ||
| 2283 | */ | ||
| 2284 | void blk_start_queueing(request_queue_t *q) | ||
| 2285 | { | ||
| 2286 | if (!blk_queue_plugged(q)) | ||
| 2287 | q->request_fn(q); | ||
| 2288 | else | ||
| 2289 | __generic_unplug_device(q); | ||
| 2290 | } | ||
| 2291 | EXPORT_SYMBOL(blk_start_queueing); | ||
| 2292 | |||
| 2293 | /** | ||
| 2303 | * blk_requeue_request - put a request back on queue | 2294 | * blk_requeue_request - put a request back on queue |
| 2304 | * @q: request queue where request should be inserted | 2295 | * @q: request queue where request should be inserted |
| 2305 | * @rq: request to be inserted | 2296 | * @rq: request to be inserted |
| @@ -2351,7 +2342,8 @@ void blk_insert_request(request_queue_t *q, struct request *rq, | |||
| 2351 | * must not attempt merges on this) and that it acts as a soft | 2342 | * must not attempt merges on this) and that it acts as a soft |
| 2352 | * barrier | 2343 | * barrier |
| 2353 | */ | 2344 | */ |
| 2354 | rq->flags |= REQ_SPECIAL | REQ_SOFTBARRIER; | 2345 | rq->cmd_type = REQ_TYPE_SPECIAL; |
| 2346 | rq->cmd_flags |= REQ_SOFTBARRIER; | ||
| 2355 | 2347 | ||
| 2356 | rq->special = data; | 2348 | rq->special = data; |
| 2357 | 2349 | ||
| @@ -2365,11 +2357,7 @@ void blk_insert_request(request_queue_t *q, struct request *rq, | |||
| 2365 | 2357 | ||
| 2366 | drive_stat_acct(rq, rq->nr_sectors, 1); | 2358 | drive_stat_acct(rq, rq->nr_sectors, 1); |
| 2367 | __elv_add_request(q, rq, where, 0); | 2359 | __elv_add_request(q, rq, where, 0); |
| 2368 | 2360 | blk_start_queueing(q); | |
| 2369 | if (blk_queue_plugged(q)) | ||
| 2370 | __generic_unplug_device(q); | ||
| 2371 | else | ||
| 2372 | q->request_fn(q); | ||
| 2373 | spin_unlock_irqrestore(q->queue_lock, flags); | 2361 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 2374 | } | 2362 | } |
| 2375 | 2363 | ||
| @@ -2558,7 +2546,7 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk, | |||
| 2558 | int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; | 2546 | int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; |
| 2559 | 2547 | ||
| 2560 | rq->rq_disk = bd_disk; | 2548 | rq->rq_disk = bd_disk; |
| 2561 | rq->flags |= REQ_NOMERGE; | 2549 | rq->cmd_flags |= REQ_NOMERGE; |
| 2562 | rq->end_io = done; | 2550 | rq->end_io = done; |
| 2563 | WARN_ON(irqs_disabled()); | 2551 | WARN_ON(irqs_disabled()); |
| 2564 | spin_lock_irq(q->queue_lock); | 2552 | spin_lock_irq(q->queue_lock); |
| @@ -2598,10 +2586,9 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk, | |||
| 2598 | rq->sense_len = 0; | 2586 | rq->sense_len = 0; |
| 2599 | } | 2587 | } |
| 2600 | 2588 | ||
| 2601 | rq->waiting = &wait; | 2589 | rq->end_io_data = &wait; |
| 2602 | blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); | 2590 | blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); |
| 2603 | wait_for_completion(&wait); | 2591 | wait_for_completion(&wait); |
| 2604 | rq->waiting = NULL; | ||
| 2605 | 2592 | ||
| 2606 | if (rq->errors) | 2593 | if (rq->errors) |
| 2607 | err = -EIO; | 2594 | err = -EIO; |
| @@ -2710,8 +2697,6 @@ EXPORT_SYMBOL_GPL(disk_round_stats); | |||
| 2710 | */ | 2697 | */ |
| 2711 | void __blk_put_request(request_queue_t *q, struct request *req) | 2698 | void __blk_put_request(request_queue_t *q, struct request *req) |
| 2712 | { | 2699 | { |
| 2713 | struct request_list *rl = req->rl; | ||
| 2714 | |||
| 2715 | if (unlikely(!q)) | 2700 | if (unlikely(!q)) |
| 2716 | return; | 2701 | return; |
| 2717 | if (unlikely(--req->ref_count)) | 2702 | if (unlikely(--req->ref_count)) |
| @@ -2719,18 +2704,16 @@ void __blk_put_request(request_queue_t *q, struct request *req) | |||
| 2719 | 2704 | ||
| 2720 | elv_completed_request(q, req); | 2705 | elv_completed_request(q, req); |
| 2721 | 2706 | ||
| 2722 | req->rq_status = RQ_INACTIVE; | ||
| 2723 | req->rl = NULL; | ||
| 2724 | |||
| 2725 | /* | 2707 | /* |
| 2726 | * Request may not have originated from ll_rw_blk. if not, | 2708 | * Request may not have originated from ll_rw_blk. if not, |
| 2727 | * it didn't come out of our reserved rq pools | 2709 | * it didn't come out of our reserved rq pools |
| 2728 | */ | 2710 | */ |
| 2729 | if (rl) { | 2711 | if (req->cmd_flags & REQ_ALLOCED) { |
| 2730 | int rw = rq_data_dir(req); | 2712 | int rw = rq_data_dir(req); |
| 2731 | int priv = req->flags & REQ_ELVPRIV; | 2713 | int priv = req->cmd_flags & REQ_ELVPRIV; |
| 2732 | 2714 | ||
| 2733 | BUG_ON(!list_empty(&req->queuelist)); | 2715 | BUG_ON(!list_empty(&req->queuelist)); |
| 2716 | BUG_ON(!hlist_unhashed(&req->hash)); | ||
| 2734 | 2717 | ||
| 2735 | blk_free_request(q, req); | 2718 | blk_free_request(q, req); |
| 2736 | freed_request(q, rw, priv); | 2719 | freed_request(q, rw, priv); |
| @@ -2764,9 +2747,9 @@ EXPORT_SYMBOL(blk_put_request); | |||
| 2764 | */ | 2747 | */ |
| 2765 | void blk_end_sync_rq(struct request *rq, int error) | 2748 | void blk_end_sync_rq(struct request *rq, int error) |
| 2766 | { | 2749 | { |
| 2767 | struct completion *waiting = rq->waiting; | 2750 | struct completion *waiting = rq->end_io_data; |
| 2768 | 2751 | ||
| 2769 | rq->waiting = NULL; | 2752 | rq->end_io_data = NULL; |
| 2770 | __blk_put_request(rq->q, rq); | 2753 | __blk_put_request(rq->q, rq); |
| 2771 | 2754 | ||
| 2772 | /* | 2755 | /* |
| @@ -2829,7 +2812,7 @@ static int attempt_merge(request_queue_t *q, struct request *req, | |||
| 2829 | 2812 | ||
| 2830 | if (rq_data_dir(req) != rq_data_dir(next) | 2813 | if (rq_data_dir(req) != rq_data_dir(next) |
| 2831 | || req->rq_disk != next->rq_disk | 2814 | || req->rq_disk != next->rq_disk |
| 2832 | || next->waiting || next->special) | 2815 | || next->special) |
| 2833 | return 0; | 2816 | return 0; |
| 2834 | 2817 | ||
| 2835 | /* | 2818 | /* |
| @@ -2890,22 +2873,24 @@ static inline int attempt_front_merge(request_queue_t *q, struct request *rq) | |||
| 2890 | 2873 | ||
| 2891 | static void init_request_from_bio(struct request *req, struct bio *bio) | 2874 | static void init_request_from_bio(struct request *req, struct bio *bio) |
| 2892 | { | 2875 | { |
| 2893 | req->flags |= REQ_CMD; | 2876 | req->cmd_type = REQ_TYPE_FS; |
| 2894 | 2877 | ||
| 2895 | /* | 2878 | /* |
| 2896 | * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) | 2879 | * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) |
| 2897 | */ | 2880 | */ |
| 2898 | if (bio_rw_ahead(bio) || bio_failfast(bio)) | 2881 | if (bio_rw_ahead(bio) || bio_failfast(bio)) |
| 2899 | req->flags |= REQ_FAILFAST; | 2882 | req->cmd_flags |= REQ_FAILFAST; |
| 2900 | 2883 | ||
| 2901 | /* | 2884 | /* |
| 2902 | * REQ_BARRIER implies no merging, but lets make it explicit | 2885 | * REQ_BARRIER implies no merging, but lets make it explicit |
| 2903 | */ | 2886 | */ |
| 2904 | if (unlikely(bio_barrier(bio))) | 2887 | if (unlikely(bio_barrier(bio))) |
| 2905 | req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); | 2888 | req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE); |
| 2906 | 2889 | ||
| 2907 | if (bio_sync(bio)) | 2890 | if (bio_sync(bio)) |
| 2908 | req->flags |= REQ_RW_SYNC; | 2891 | req->cmd_flags |= REQ_RW_SYNC; |
| 2892 | if (bio_rw_meta(bio)) | ||
| 2893 | req->cmd_flags |= REQ_RW_META; | ||
| 2909 | 2894 | ||
| 2910 | req->errors = 0; | 2895 | req->errors = 0; |
| 2911 | req->hard_sector = req->sector = bio->bi_sector; | 2896 | req->hard_sector = req->sector = bio->bi_sector; |
| @@ -2914,7 +2899,6 @@ static void init_request_from_bio(struct request *req, struct bio *bio) | |||
| 2914 | req->nr_phys_segments = bio_phys_segments(req->q, bio); | 2899 | req->nr_phys_segments = bio_phys_segments(req->q, bio); |
| 2915 | req->nr_hw_segments = bio_hw_segments(req->q, bio); | 2900 | req->nr_hw_segments = bio_hw_segments(req->q, bio); |
| 2916 | req->buffer = bio_data(bio); /* see ->buffer comment above */ | 2901 | req->buffer = bio_data(bio); /* see ->buffer comment above */ |
| 2917 | req->waiting = NULL; | ||
| 2918 | req->bio = req->biotail = bio; | 2902 | req->bio = req->biotail = bio; |
| 2919 | req->ioprio = bio_prio(bio); | 2903 | req->ioprio = bio_prio(bio); |
| 2920 | req->rq_disk = bio->bi_bdev->bd_disk; | 2904 | req->rq_disk = bio->bi_bdev->bd_disk; |
| @@ -2924,17 +2908,11 @@ static void init_request_from_bio(struct request *req, struct bio *bio) | |||
| 2924 | static int __make_request(request_queue_t *q, struct bio *bio) | 2908 | static int __make_request(request_queue_t *q, struct bio *bio) |
| 2925 | { | 2909 | { |
| 2926 | struct request *req; | 2910 | struct request *req; |
| 2927 | int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync; | 2911 | int el_ret, nr_sectors, barrier, err; |
| 2928 | unsigned short prio; | 2912 | const unsigned short prio = bio_prio(bio); |
| 2929 | sector_t sector; | 2913 | const int sync = bio_sync(bio); |
| 2930 | 2914 | ||
| 2931 | sector = bio->bi_sector; | ||
| 2932 | nr_sectors = bio_sectors(bio); | 2915 | nr_sectors = bio_sectors(bio); |
| 2933 | cur_nr_sectors = bio_cur_sectors(bio); | ||
| 2934 | prio = bio_prio(bio); | ||
| 2935 | |||
| 2936 | rw = bio_data_dir(bio); | ||
| 2937 | sync = bio_sync(bio); | ||
| 2938 | 2916 | ||
| 2939 | /* | 2917 | /* |
| 2940 | * low level driver can indicate that it wants pages above a | 2918 | * low level driver can indicate that it wants pages above a |
| @@ -2943,8 +2921,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) | |||
| 2943 | */ | 2921 | */ |
| 2944 | blk_queue_bounce(q, &bio); | 2922 | blk_queue_bounce(q, &bio); |
| 2945 | 2923 | ||
| 2946 | spin_lock_prefetch(q->queue_lock); | ||
| 2947 | |||
| 2948 | barrier = bio_barrier(bio); | 2924 | barrier = bio_barrier(bio); |
| 2949 | if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) { | 2925 | if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) { |
| 2950 | err = -EOPNOTSUPP; | 2926 | err = -EOPNOTSUPP; |
| @@ -2972,7 +2948,7 @@ static int __make_request(request_queue_t *q, struct bio *bio) | |||
| 2972 | req->ioprio = ioprio_best(req->ioprio, prio); | 2948 | req->ioprio = ioprio_best(req->ioprio, prio); |
| 2973 | drive_stat_acct(req, nr_sectors, 0); | 2949 | drive_stat_acct(req, nr_sectors, 0); |
| 2974 | if (!attempt_back_merge(q, req)) | 2950 | if (!attempt_back_merge(q, req)) |
| 2975 | elv_merged_request(q, req); | 2951 | elv_merged_request(q, req, el_ret); |
| 2976 | goto out; | 2952 | goto out; |
| 2977 | 2953 | ||
| 2978 | case ELEVATOR_FRONT_MERGE: | 2954 | case ELEVATOR_FRONT_MERGE: |
| @@ -2992,14 +2968,14 @@ static int __make_request(request_queue_t *q, struct bio *bio) | |||
| 2992 | * not touch req->buffer either... | 2968 | * not touch req->buffer either... |
| 2993 | */ | 2969 | */ |
| 2994 | req->buffer = bio_data(bio); | 2970 | req->buffer = bio_data(bio); |
| 2995 | req->current_nr_sectors = cur_nr_sectors; | 2971 | req->current_nr_sectors = bio_cur_sectors(bio); |
| 2996 | req->hard_cur_sectors = cur_nr_sectors; | 2972 | req->hard_cur_sectors = req->current_nr_sectors; |
| 2997 | req->sector = req->hard_sector = sector; | 2973 | req->sector = req->hard_sector = bio->bi_sector; |
| 2998 | req->nr_sectors = req->hard_nr_sectors += nr_sectors; | 2974 | req->nr_sectors = req->hard_nr_sectors += nr_sectors; |
| 2999 | req->ioprio = ioprio_best(req->ioprio, prio); | 2975 | req->ioprio = ioprio_best(req->ioprio, prio); |
| 3000 | drive_stat_acct(req, nr_sectors, 0); | 2976 | drive_stat_acct(req, nr_sectors, 0); |
| 3001 | if (!attempt_front_merge(q, req)) | 2977 | if (!attempt_front_merge(q, req)) |
| 3002 | elv_merged_request(q, req); | 2978 | elv_merged_request(q, req, el_ret); |
| 3003 | goto out; | 2979 | goto out; |
| 3004 | 2980 | ||
| 3005 | /* ELV_NO_MERGE: elevator says don't/can't merge. */ | 2981 | /* ELV_NO_MERGE: elevator says don't/can't merge. */ |
| @@ -3012,7 +2988,7 @@ get_rq: | |||
| 3012 | * Grab a free request. This is might sleep but can not fail. | 2988 | * Grab a free request. This is might sleep but can not fail. |
| 3013 | * Returns with the queue unlocked. | 2989 | * Returns with the queue unlocked. |
| 3014 | */ | 2990 | */ |
| 3015 | req = get_request_wait(q, rw, bio); | 2991 | req = get_request_wait(q, bio_data_dir(bio), bio); |
| 3016 | 2992 | ||
| 3017 | /* | 2993 | /* |
| 3018 | * After dropping the lock and possibly sleeping here, our request | 2994 | * After dropping the lock and possibly sleeping here, our request |
| @@ -3306,7 +3282,7 @@ static int __end_that_request_first(struct request *req, int uptodate, | |||
| 3306 | req->errors = 0; | 3282 | req->errors = 0; |
| 3307 | 3283 | ||
| 3308 | if (!uptodate) { | 3284 | if (!uptodate) { |
| 3309 | if (blk_fs_request(req) && !(req->flags & REQ_QUIET)) | 3285 | if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET)) |
| 3310 | printk("end_request: I/O error, dev %s, sector %llu\n", | 3286 | printk("end_request: I/O error, dev %s, sector %llu\n", |
| 3311 | req->rq_disk ? req->rq_disk->disk_name : "?", | 3287 | req->rq_disk ? req->rq_disk->disk_name : "?", |
| 3312 | (unsigned long long)req->sector); | 3288 | (unsigned long long)req->sector); |
| @@ -3569,8 +3545,8 @@ EXPORT_SYMBOL(end_request); | |||
| 3569 | 3545 | ||
| 3570 | void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) | 3546 | void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) |
| 3571 | { | 3547 | { |
| 3572 | /* first two bits are identical in rq->flags and bio->bi_rw */ | 3548 | /* first two bits are identical in rq->cmd_flags and bio->bi_rw */ |
| 3573 | rq->flags |= (bio->bi_rw & 3); | 3549 | rq->cmd_flags |= (bio->bi_rw & 3); |
| 3574 | 3550 | ||
| 3575 | rq->nr_phys_segments = bio_phys_segments(q, bio); | 3551 | rq->nr_phys_segments = bio_phys_segments(q, bio); |
| 3576 | rq->nr_hw_segments = bio_hw_segments(q, bio); | 3552 | rq->nr_hw_segments = bio_hw_segments(q, bio); |
| @@ -3658,25 +3634,22 @@ EXPORT_SYMBOL(put_io_context); | |||
| 3658 | /* Called by the exitting task */ | 3634 | /* Called by the exitting task */ |
| 3659 | void exit_io_context(void) | 3635 | void exit_io_context(void) |
| 3660 | { | 3636 | { |
| 3661 | unsigned long flags; | ||
| 3662 | struct io_context *ioc; | 3637 | struct io_context *ioc; |
| 3663 | struct cfq_io_context *cic; | 3638 | struct cfq_io_context *cic; |
| 3664 | 3639 | ||
| 3665 | local_irq_save(flags); | ||
| 3666 | task_lock(current); | 3640 | task_lock(current); |
| 3667 | ioc = current->io_context; | 3641 | ioc = current->io_context; |
| 3668 | current->io_context = NULL; | 3642 | current->io_context = NULL; |
| 3669 | ioc->task = NULL; | ||
| 3670 | task_unlock(current); | 3643 | task_unlock(current); |
| 3671 | local_irq_restore(flags); | ||
| 3672 | 3644 | ||
| 3645 | ioc->task = NULL; | ||
| 3673 | if (ioc->aic && ioc->aic->exit) | 3646 | if (ioc->aic && ioc->aic->exit) |
| 3674 | ioc->aic->exit(ioc->aic); | 3647 | ioc->aic->exit(ioc->aic); |
| 3675 | if (ioc->cic_root.rb_node != NULL) { | 3648 | if (ioc->cic_root.rb_node != NULL) { |
| 3676 | cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node); | 3649 | cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node); |
| 3677 | cic->exit(ioc); | 3650 | cic->exit(ioc); |
| 3678 | } | 3651 | } |
| 3679 | 3652 | ||
| 3680 | put_io_context(ioc); | 3653 | put_io_context(ioc); |
| 3681 | } | 3654 | } |
| 3682 | 3655 | ||
| @@ -3688,7 +3661,7 @@ void exit_io_context(void) | |||
| 3688 | * but since the current task itself holds a reference, the context can be | 3661 | * but since the current task itself holds a reference, the context can be |
| 3689 | * used in general code, so long as it stays within `current` context. | 3662 | * used in general code, so long as it stays within `current` context. |
| 3690 | */ | 3663 | */ |
| 3691 | struct io_context *current_io_context(gfp_t gfp_flags) | 3664 | static struct io_context *current_io_context(gfp_t gfp_flags, int node) |
| 3692 | { | 3665 | { |
| 3693 | struct task_struct *tsk = current; | 3666 | struct task_struct *tsk = current; |
| 3694 | struct io_context *ret; | 3667 | struct io_context *ret; |
| @@ -3697,11 +3670,11 @@ struct io_context *current_io_context(gfp_t gfp_flags) | |||
| 3697 | if (likely(ret)) | 3670 | if (likely(ret)) |
| 3698 | return ret; | 3671 | return ret; |
| 3699 | 3672 | ||
| 3700 | ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); | 3673 | ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node); |
| 3701 | if (ret) { | 3674 | if (ret) { |
| 3702 | atomic_set(&ret->refcount, 1); | 3675 | atomic_set(&ret->refcount, 1); |
| 3703 | ret->task = current; | 3676 | ret->task = current; |
| 3704 | ret->set_ioprio = NULL; | 3677 | ret->ioprio_changed = 0; |
| 3705 | ret->last_waited = jiffies; /* doesn't matter... */ | 3678 | ret->last_waited = jiffies; /* doesn't matter... */ |
| 3706 | ret->nr_batch_requests = 0; /* because this is 0 */ | 3679 | ret->nr_batch_requests = 0; /* because this is 0 */ |
| 3707 | ret->aic = NULL; | 3680 | ret->aic = NULL; |
| @@ -3721,10 +3694,10 @@ EXPORT_SYMBOL(current_io_context); | |||
| 3721 | * | 3694 | * |
| 3722 | * This is always called in the context of the task which submitted the I/O. | 3695 | * This is always called in the context of the task which submitted the I/O. |
| 3723 | */ | 3696 | */ |
| 3724 | struct io_context *get_io_context(gfp_t gfp_flags) | 3697 | struct io_context *get_io_context(gfp_t gfp_flags, int node) |
| 3725 | { | 3698 | { |
| 3726 | struct io_context *ret; | 3699 | struct io_context *ret; |
| 3727 | ret = current_io_context(gfp_flags); | 3700 | ret = current_io_context(gfp_flags, node); |
| 3728 | if (likely(ret)) | 3701 | if (likely(ret)) |
| 3729 | atomic_inc(&ret->refcount); | 3702 | atomic_inc(&ret->refcount); |
| 3730 | return ret; | 3703 | return ret; |
| @@ -3837,9 +3810,6 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count) | |||
| 3837 | ssize_t ret = queue_var_store(&ra_kb, page, count); | 3810 | ssize_t ret = queue_var_store(&ra_kb, page, count); |
| 3838 | 3811 | ||
| 3839 | spin_lock_irq(q->queue_lock); | 3812 | spin_lock_irq(q->queue_lock); |
| 3840 | if (ra_kb > (q->max_sectors >> 1)) | ||
| 3841 | ra_kb = (q->max_sectors >> 1); | ||
| 3842 | |||
| 3843 | q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10); | 3813 | q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10); |
| 3844 | spin_unlock_irq(q->queue_lock); | 3814 | spin_unlock_irq(q->queue_lock); |
| 3845 | 3815 | ||
diff --git a/block/noop-iosched.c b/block/noop-iosched.c index 56a7c620574f..79af43179421 100644 --- a/block/noop-iosched.c +++ b/block/noop-iosched.c | |||
| @@ -69,7 +69,7 @@ static void *noop_init_queue(request_queue_t *q, elevator_t *e) | |||
| 69 | { | 69 | { |
| 70 | struct noop_data *nd; | 70 | struct noop_data *nd; |
| 71 | 71 | ||
| 72 | nd = kmalloc(sizeof(*nd), GFP_KERNEL); | 72 | nd = kmalloc_node(sizeof(*nd), GFP_KERNEL, q->node); |
| 73 | if (!nd) | 73 | if (!nd) |
| 74 | return NULL; | 74 | return NULL; |
| 75 | INIT_LIST_HEAD(&nd->queue); | 75 | INIT_LIST_HEAD(&nd->queue); |
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index b33eda26e205..2dc326421a24 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
| @@ -294,7 +294,7 @@ static int sg_io(struct file *file, request_queue_t *q, | |||
| 294 | rq->sense = sense; | 294 | rq->sense = sense; |
| 295 | rq->sense_len = 0; | 295 | rq->sense_len = 0; |
| 296 | 296 | ||
| 297 | rq->flags |= REQ_BLOCK_PC; | 297 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 298 | bio = rq->bio; | 298 | bio = rq->bio; |
| 299 | 299 | ||
| 300 | /* | 300 | /* |
| @@ -470,7 +470,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, | |||
| 470 | memset(sense, 0, sizeof(sense)); | 470 | memset(sense, 0, sizeof(sense)); |
| 471 | rq->sense = sense; | 471 | rq->sense = sense; |
| 472 | rq->sense_len = 0; | 472 | rq->sense_len = 0; |
| 473 | rq->flags |= REQ_BLOCK_PC; | 473 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 474 | 474 | ||
| 475 | blk_execute_rq(q, disk, rq, 0); | 475 | blk_execute_rq(q, disk, rq, 0); |
| 476 | 476 | ||
| @@ -502,7 +502,7 @@ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int c | |||
| 502 | int err; | 502 | int err; |
| 503 | 503 | ||
| 504 | rq = blk_get_request(q, WRITE, __GFP_WAIT); | 504 | rq = blk_get_request(q, WRITE, __GFP_WAIT); |
| 505 | rq->flags |= REQ_BLOCK_PC; | 505 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 506 | rq->data = NULL; | 506 | rq->data = NULL; |
| 507 | rq->data_len = 0; | 507 | rq->data_len = 0; |
| 508 | rq->timeout = BLK_DEFAULT_TIMEOUT; | 508 | rq->timeout = BLK_DEFAULT_TIMEOUT; |
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index a360215dbce7..2568640430fb 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
| @@ -3331,7 +3331,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_ | |||
| 3331 | Command->DmaDirection = PCI_DMA_TODEVICE; | 3331 | Command->DmaDirection = PCI_DMA_TODEVICE; |
| 3332 | Command->CommandType = DAC960_WriteCommand; | 3332 | Command->CommandType = DAC960_WriteCommand; |
| 3333 | } | 3333 | } |
| 3334 | Command->Completion = Request->waiting; | 3334 | Command->Completion = Request->end_io_data; |
| 3335 | Command->LogicalDriveNumber = (long)Request->rq_disk->private_data; | 3335 | Command->LogicalDriveNumber = (long)Request->rq_disk->private_data; |
| 3336 | Command->BlockNumber = Request->sector; | 3336 | Command->BlockNumber = Request->sector; |
| 3337 | Command->BlockCount = Request->nr_sectors; | 3337 | Command->BlockCount = Request->nr_sectors; |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index b5382cedf0c0..422e31d5f8e5 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | # Block device driver configuration | 2 | # Block device driver configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | if BLOCK | ||
| 6 | |||
| 5 | menu "Block devices" | 7 | menu "Block devices" |
| 6 | 8 | ||
| 7 | config BLK_DEV_FD | 9 | config BLK_DEV_FD |
| @@ -468,3 +470,5 @@ config ATA_OVER_ETH | |||
| 468 | devices like the Coraid EtherDrive (R) Storage Blade. | 470 | devices like the Coraid EtherDrive (R) Storage Blade. |
| 469 | 471 | ||
| 470 | endmenu | 472 | endmenu |
| 473 | |||
| 474 | endif | ||
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 2cd3391ff878..c211065ad829 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -1229,7 +1229,6 @@ static inline void complete_buffers(struct bio *bio, int status) | |||
| 1229 | int nr_sectors = bio_sectors(bio); | 1229 | int nr_sectors = bio_sectors(bio); |
| 1230 | 1230 | ||
| 1231 | bio->bi_next = NULL; | 1231 | bio->bi_next = NULL; |
| 1232 | blk_finished_io(len); | ||
| 1233 | bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO); | 1232 | bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO); |
| 1234 | bio = xbh; | 1233 | bio = xbh; |
| 1235 | } | 1234 | } |
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 78082edc14b4..4abc193314ee 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c | |||
| @@ -989,7 +989,6 @@ static inline void complete_buffers(struct bio *bio, int ok) | |||
| 989 | xbh = bio->bi_next; | 989 | xbh = bio->bi_next; |
| 990 | bio->bi_next = NULL; | 990 | bio->bi_next = NULL; |
| 991 | 991 | ||
| 992 | blk_finished_io(nr_sectors); | ||
| 993 | bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO); | 992 | bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO); |
| 994 | 993 | ||
| 995 | bio = xbh; | 994 | bio = xbh; |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index ad1d7065a1b2..629c5769d994 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
| @@ -2991,8 +2991,8 @@ static void do_fd_request(request_queue_t * q) | |||
| 2991 | if (usage_count == 0) { | 2991 | if (usage_count == 0) { |
| 2992 | printk("warning: usage count=0, current_req=%p exiting\n", | 2992 | printk("warning: usage count=0, current_req=%p exiting\n", |
| 2993 | current_req); | 2993 | current_req); |
| 2994 | printk("sect=%ld flags=%lx\n", (long)current_req->sector, | 2994 | printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector, |
| 2995 | current_req->flags); | 2995 | current_req->cmd_type, current_req->cmd_flags); |
| 2996 | return; | 2996 | return; |
| 2997 | } | 2997 | } |
| 2998 | if (test_bit(0, &fdc_busy)) { | 2998 | if (test_bit(0, &fdc_busy)) { |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 68b0471ad5a6..d6bb8da955a2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #include <linux/swap.h> | 66 | #include <linux/swap.h> |
| 67 | #include <linux/slab.h> | 67 | #include <linux/slab.h> |
| 68 | #include <linux/loop.h> | 68 | #include <linux/loop.h> |
| 69 | #include <linux/compat.h> | ||
| 69 | #include <linux/suspend.h> | 70 | #include <linux/suspend.h> |
| 70 | #include <linux/writeback.h> | 71 | #include <linux/writeback.h> |
| 71 | #include <linux/buffer_head.h> /* for invalidate_bdev() */ | 72 | #include <linux/buffer_head.h> /* for invalidate_bdev() */ |
| @@ -1165,6 +1166,162 @@ static int lo_ioctl(struct inode * inode, struct file * file, | |||
| 1165 | return err; | 1166 | return err; |
| 1166 | } | 1167 | } |
| 1167 | 1168 | ||
| 1169 | #ifdef CONFIG_COMPAT | ||
| 1170 | struct compat_loop_info { | ||
| 1171 | compat_int_t lo_number; /* ioctl r/o */ | ||
| 1172 | compat_dev_t lo_device; /* ioctl r/o */ | ||
| 1173 | compat_ulong_t lo_inode; /* ioctl r/o */ | ||
| 1174 | compat_dev_t lo_rdevice; /* ioctl r/o */ | ||
| 1175 | compat_int_t lo_offset; | ||
| 1176 | compat_int_t lo_encrypt_type; | ||
| 1177 | compat_int_t lo_encrypt_key_size; /* ioctl w/o */ | ||
| 1178 | compat_int_t lo_flags; /* ioctl r/o */ | ||
| 1179 | char lo_name[LO_NAME_SIZE]; | ||
| 1180 | unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ | ||
| 1181 | compat_ulong_t lo_init[2]; | ||
| 1182 | char reserved[4]; | ||
| 1183 | }; | ||
| 1184 | |||
| 1185 | /* | ||
| 1186 | * Transfer 32-bit compatibility structure in userspace to 64-bit loop info | ||
| 1187 | * - noinlined to reduce stack space usage in main part of driver | ||
| 1188 | */ | ||
| 1189 | static noinline int | ||
| 1190 | loop_info64_from_compat(const struct compat_loop_info *arg, | ||
| 1191 | struct loop_info64 *info64) | ||
| 1192 | { | ||
| 1193 | struct compat_loop_info info; | ||
| 1194 | |||
| 1195 | if (copy_from_user(&info, arg, sizeof(info))) | ||
| 1196 | return -EFAULT; | ||
| 1197 | |||
| 1198 | memset(info64, 0, sizeof(*info64)); | ||
| 1199 | info64->lo_number = info.lo_number; | ||
| 1200 | info64->lo_device = info.lo_device; | ||
| 1201 | info64->lo_inode = info.lo_inode; | ||
| 1202 | info64->lo_rdevice = info.lo_rdevice; | ||
| 1203 | info64->lo_offset = info.lo_offset; | ||
| 1204 | info64->lo_sizelimit = 0; | ||
| 1205 | info64->lo_encrypt_type = info.lo_encrypt_type; | ||
| 1206 | info64->lo_encrypt_key_size = info.lo_encrypt_key_size; | ||
| 1207 | info64->lo_flags = info.lo_flags; | ||
| 1208 | info64->lo_init[0] = info.lo_init[0]; | ||
| 1209 | info64->lo_init[1] = info.lo_init[1]; | ||
| 1210 | if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI) | ||
| 1211 | memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE); | ||
| 1212 | else | ||
| 1213 | memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE); | ||
| 1214 | memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE); | ||
| 1215 | return 0; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | /* | ||
| 1219 | * Transfer 64-bit loop info to 32-bit compatibility structure in userspace | ||
| 1220 | * - noinlined to reduce stack space usage in main part of driver | ||
| 1221 | */ | ||
| 1222 | static noinline int | ||
| 1223 | loop_info64_to_compat(const struct loop_info64 *info64, | ||
| 1224 | struct compat_loop_info __user *arg) | ||
| 1225 | { | ||
| 1226 | struct compat_loop_info info; | ||
| 1227 | |||
| 1228 | memset(&info, 0, sizeof(info)); | ||
| 1229 | info.lo_number = info64->lo_number; | ||
| 1230 | info.lo_device = info64->lo_device; | ||
| 1231 | info.lo_inode = info64->lo_inode; | ||
| 1232 | info.lo_rdevice = info64->lo_rdevice; | ||
| 1233 | info.lo_offset = info64->lo_offset; | ||
| 1234 | info.lo_encrypt_type = info64->lo_encrypt_type; | ||
| 1235 | info.lo_encrypt_key_size = info64->lo_encrypt_key_size; | ||
| 1236 | info.lo_flags = info64->lo_flags; | ||
| 1237 | info.lo_init[0] = info64->lo_init[0]; | ||
| 1238 | info.lo_init[1] = info64->lo_init[1]; | ||
| 1239 | if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI) | ||
| 1240 | memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE); | ||
| 1241 | else | ||
| 1242 | memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE); | ||
| 1243 | memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE); | ||
| 1244 | |||
| 1245 | /* error in case values were truncated */ | ||
| 1246 | if (info.lo_device != info64->lo_device || | ||
| 1247 | info.lo_rdevice != info64->lo_rdevice || | ||
| 1248 | info.lo_inode != info64->lo_inode || | ||
| 1249 | info.lo_offset != info64->lo_offset || | ||
| 1250 | info.lo_init[0] != info64->lo_init[0] || | ||
| 1251 | info.lo_init[1] != info64->lo_init[1]) | ||
| 1252 | return -EOVERFLOW; | ||
| 1253 | |||
| 1254 | if (copy_to_user(arg, &info, sizeof(info))) | ||
| 1255 | return -EFAULT; | ||
| 1256 | return 0; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | static int | ||
| 1260 | loop_set_status_compat(struct loop_device *lo, | ||
| 1261 | const struct compat_loop_info __user *arg) | ||
| 1262 | { | ||
| 1263 | struct loop_info64 info64; | ||
| 1264 | int ret; | ||
| 1265 | |||
| 1266 | ret = loop_info64_from_compat(arg, &info64); | ||
| 1267 | if (ret < 0) | ||
| 1268 | return ret; | ||
| 1269 | return loop_set_status(lo, &info64); | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | static int | ||
| 1273 | loop_get_status_compat(struct loop_device *lo, | ||
| 1274 | struct compat_loop_info __user *arg) | ||
| 1275 | { | ||
| 1276 | struct loop_info64 info64; | ||
| 1277 | int err = 0; | ||
| 1278 | |||
| 1279 | if (!arg) | ||
| 1280 | err = -EINVAL; | ||
| 1281 | if (!err) | ||
| 1282 | err = loop_get_status(lo, &info64); | ||
| 1283 | if (!err) | ||
| 1284 | err = loop_info64_to_compat(&info64, arg); | ||
| 1285 | return err; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 1289 | { | ||
| 1290 | struct inode *inode = file->f_dentry->d_inode; | ||
| 1291 | struct loop_device *lo = inode->i_bdev->bd_disk->private_data; | ||
| 1292 | int err; | ||
| 1293 | |||
| 1294 | lock_kernel(); | ||
| 1295 | switch(cmd) { | ||
| 1296 | case LOOP_SET_STATUS: | ||
| 1297 | mutex_lock(&lo->lo_ctl_mutex); | ||
| 1298 | err = loop_set_status_compat( | ||
| 1299 | lo, (const struct compat_loop_info __user *) arg); | ||
| 1300 | mutex_unlock(&lo->lo_ctl_mutex); | ||
| 1301 | break; | ||
| 1302 | case LOOP_GET_STATUS: | ||
| 1303 | mutex_lock(&lo->lo_ctl_mutex); | ||
| 1304 | err = loop_get_status_compat( | ||
| 1305 | lo, (struct compat_loop_info __user *) arg); | ||
| 1306 | mutex_unlock(&lo->lo_ctl_mutex); | ||
| 1307 | break; | ||
| 1308 | case LOOP_CLR_FD: | ||
| 1309 | case LOOP_GET_STATUS64: | ||
| 1310 | case LOOP_SET_STATUS64: | ||
| 1311 | arg = (unsigned long) compat_ptr(arg); | ||
| 1312 | case LOOP_SET_FD: | ||
| 1313 | case LOOP_CHANGE_FD: | ||
| 1314 | err = lo_ioctl(inode, file, cmd, arg); | ||
| 1315 | break; | ||
| 1316 | default: | ||
| 1317 | err = -ENOIOCTLCMD; | ||
| 1318 | break; | ||
| 1319 | } | ||
| 1320 | unlock_kernel(); | ||
| 1321 | return err; | ||
| 1322 | } | ||
| 1323 | #endif | ||
| 1324 | |||
| 1168 | static int lo_open(struct inode *inode, struct file *file) | 1325 | static int lo_open(struct inode *inode, struct file *file) |
| 1169 | { | 1326 | { |
| 1170 | struct loop_device *lo = inode->i_bdev->bd_disk->private_data; | 1327 | struct loop_device *lo = inode->i_bdev->bd_disk->private_data; |
| @@ -1192,6 +1349,9 @@ static struct block_device_operations lo_fops = { | |||
| 1192 | .open = lo_open, | 1349 | .open = lo_open, |
| 1193 | .release = lo_release, | 1350 | .release = lo_release, |
| 1194 | .ioctl = lo_ioctl, | 1351 | .ioctl = lo_ioctl, |
| 1352 | #ifdef CONFIG_COMPAT | ||
| 1353 | .compat_ioctl = lo_compat_ioctl, | ||
| 1354 | #endif | ||
| 1195 | }; | 1355 | }; |
| 1196 | 1356 | ||
| 1197 | /* | 1357 | /* |
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index bdbade9a5cf5..9d1035e8d9d8 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
| @@ -407,10 +407,10 @@ static void do_nbd_request(request_queue_t * q) | |||
| 407 | struct nbd_device *lo; | 407 | struct nbd_device *lo; |
| 408 | 408 | ||
| 409 | blkdev_dequeue_request(req); | 409 | blkdev_dequeue_request(req); |
| 410 | dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n", | 410 | dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", |
| 411 | req->rq_disk->disk_name, req, req->flags); | 411 | req->rq_disk->disk_name, req, req->cmd_type); |
| 412 | 412 | ||
| 413 | if (!(req->flags & REQ_CMD)) | 413 | if (!blk_fs_request(req)) |
| 414 | goto error_out; | 414 | goto error_out; |
| 415 | 415 | ||
| 416 | lo = req->rq_disk->private_data; | 416 | lo = req->rq_disk->private_data; |
| @@ -489,7 +489,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, | |||
| 489 | switch (cmd) { | 489 | switch (cmd) { |
| 490 | case NBD_DISCONNECT: | 490 | case NBD_DISCONNECT: |
| 491 | printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name); | 491 | printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name); |
| 492 | sreq.flags = REQ_SPECIAL; | 492 | sreq.cmd_type = REQ_TYPE_SPECIAL; |
| 493 | nbd_cmd(&sreq) = NBD_CMD_DISC; | 493 | nbd_cmd(&sreq) = NBD_CMD_DISC; |
| 494 | /* | 494 | /* |
| 495 | * Set these to sane values in case server implementation | 495 | * Set these to sane values in case server implementation |
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 2403721f9db1..38578b9dbfd1 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c | |||
| @@ -437,7 +437,7 @@ static char *pd_buf; /* buffer for request in progress */ | |||
| 437 | 437 | ||
| 438 | static enum action do_pd_io_start(void) | 438 | static enum action do_pd_io_start(void) |
| 439 | { | 439 | { |
| 440 | if (pd_req->flags & REQ_SPECIAL) { | 440 | if (blk_special_request(pd_req)) { |
| 441 | phase = pd_special; | 441 | phase = pd_special; |
| 442 | return pd_special(); | 442 | return pd_special(); |
| 443 | } | 443 | } |
| @@ -719,14 +719,12 @@ static int pd_special_command(struct pd_unit *disk, | |||
| 719 | 719 | ||
| 720 | memset(&rq, 0, sizeof(rq)); | 720 | memset(&rq, 0, sizeof(rq)); |
| 721 | rq.errors = 0; | 721 | rq.errors = 0; |
| 722 | rq.rq_status = RQ_ACTIVE; | ||
| 723 | rq.rq_disk = disk->gd; | 722 | rq.rq_disk = disk->gd; |
| 724 | rq.ref_count = 1; | 723 | rq.ref_count = 1; |
| 725 | rq.waiting = &wait; | 724 | rq.end_io_data = &wait; |
| 726 | rq.end_io = blk_end_sync_rq; | 725 | rq.end_io = blk_end_sync_rq; |
| 727 | blk_insert_request(disk->gd->queue, &rq, 0, func); | 726 | blk_insert_request(disk->gd->queue, &rq, 0, func); |
| 728 | wait_for_completion(&wait); | 727 | wait_for_completion(&wait); |
| 729 | rq.waiting = NULL; | ||
| 730 | if (rq.errors) | 728 | if (rq.errors) |
| 731 | err = -EIO; | 729 | err = -EIO; |
| 732 | blk_put_request(&rq); | 730 | blk_put_request(&rq); |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 451b996bba91..888d1aceeeff 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
| @@ -365,17 +365,17 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * | |||
| 365 | rq->sense = sense; | 365 | rq->sense = sense; |
| 366 | memset(sense, 0, sizeof(sense)); | 366 | memset(sense, 0, sizeof(sense)); |
| 367 | rq->sense_len = 0; | 367 | rq->sense_len = 0; |
| 368 | rq->flags |= REQ_BLOCK_PC | REQ_HARDBARRIER; | 368 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 369 | rq->cmd_flags |= REQ_HARDBARRIER; | ||
| 369 | if (cgc->quiet) | 370 | if (cgc->quiet) |
| 370 | rq->flags |= REQ_QUIET; | 371 | rq->cmd_flags |= REQ_QUIET; |
| 371 | memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); | 372 | memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE); |
| 372 | if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) | 373 | if (sizeof(rq->cmd) > CDROM_PACKET_SIZE) |
| 373 | memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); | 374 | memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE); |
| 374 | rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); | 375 | rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); |
| 375 | 376 | ||
| 376 | rq->ref_count++; | 377 | rq->ref_count++; |
| 377 | rq->flags |= REQ_NOMERGE; | 378 | rq->end_io_data = &wait; |
| 378 | rq->waiting = &wait; | ||
| 379 | rq->end_io = blk_end_sync_rq; | 379 | rq->end_io = blk_end_sync_rq; |
| 380 | elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); | 380 | elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); |
| 381 | generic_unplug_device(q); | 381 | generic_unplug_device(q); |
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index cc42e762396f..f2305ee792a1 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c | |||
| @@ -319,8 +319,8 @@ static void start_request(struct floppy_state *fs) | |||
| 319 | printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", | 319 | printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", |
| 320 | req->rq_disk->disk_name, req->cmd, | 320 | req->rq_disk->disk_name, req->cmd, |
| 321 | (long)req->sector, req->nr_sectors, req->buffer); | 321 | (long)req->sector, req->nr_sectors, req->buffer); |
| 322 | printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n", | 322 | printk(" errors=%d current_nr_sectors=%ld\n", |
| 323 | req->rq_status, req->errors, req->current_nr_sectors); | 323 | req->errors, req->current_nr_sectors); |
| 324 | #endif | 324 | #endif |
| 325 | 325 | ||
| 326 | if (req->sector < 0 || req->sector >= fs->total_secs) { | 326 | if (req->sector < 0 || req->sector >= fs->total_secs) { |
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c index 89e3c2f8b776..dfda796eba56 100644 --- a/drivers/block/swim_iop.c +++ b/drivers/block/swim_iop.c | |||
| @@ -529,8 +529,8 @@ static void start_request(struct floppy_state *fs) | |||
| 529 | printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", | 529 | printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", |
| 530 | CURRENT->rq_disk->disk_name, CURRENT->cmd, | 530 | CURRENT->rq_disk->disk_name, CURRENT->cmd, |
| 531 | CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer); | 531 | CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer); |
| 532 | printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n", | 532 | printk(" errors=%d current_nr_sectors=%ld\n", |
| 533 | CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors); | 533 | CURRENT->errors, CURRENT->current_nr_sectors); |
| 534 | #endif | 534 | #endif |
| 535 | 535 | ||
| 536 | if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) { | 536 | if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) { |
diff --git a/drivers/block/xd.c b/drivers/block/xd.c index e828e4cbd3e1..ebf3025721d1 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c | |||
| @@ -313,7 +313,7 @@ static void do_xd_request (request_queue_t * q) | |||
| 313 | int res = 0; | 313 | int res = 0; |
| 314 | int retry; | 314 | int retry; |
| 315 | 315 | ||
| 316 | if (!(req->flags & REQ_CMD)) { | 316 | if (!blk_fs_request(req)) { |
| 317 | end_request(req, 0); | 317 | end_request(req, 0); |
| 318 | continue; | 318 | continue; |
| 319 | } | 319 | } |
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig index ff5652d40619..4b12e9031fb3 100644 --- a/drivers/cdrom/Kconfig +++ b/drivers/cdrom/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | menu "Old CD-ROM drivers (not SCSI, not IDE)" | 5 | menu "Old CD-ROM drivers (not SCSI, not IDE)" |
| 6 | depends on ISA | 6 | depends on ISA && BLOCK |
| 7 | 7 | ||
| 8 | config CD_NO_IDESCSI | 8 | config CD_NO_IDESCSI |
| 9 | bool "Support non-SCSI/IDE/ATAPI CDROM drives" | 9 | bool "Support non-SCSI/IDE/ATAPI CDROM drives" |
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d239cf8b20bd..b38c84a7a8e3 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
| @@ -2129,7 +2129,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, | |||
| 2129 | rq->cmd[9] = 0xf8; | 2129 | rq->cmd[9] = 0xf8; |
| 2130 | 2130 | ||
| 2131 | rq->cmd_len = 12; | 2131 | rq->cmd_len = 12; |
| 2132 | rq->flags |= REQ_BLOCK_PC; | 2132 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 2133 | rq->timeout = 60 * HZ; | 2133 | rq->timeout = 60 * HZ; |
| 2134 | bio = rq->bio; | 2134 | bio = rq->bio; |
| 2135 | 2135 | ||
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 37bdb0163f0d..ccd91c1a84bd 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c | |||
| @@ -1338,8 +1338,10 @@ static void do_cdu31a_request(request_queue_t * q) | |||
| 1338 | } | 1338 | } |
| 1339 | 1339 | ||
| 1340 | /* WTF??? */ | 1340 | /* WTF??? */ |
| 1341 | if (!(req->flags & REQ_CMD)) | 1341 | if (!blk_fs_request(req)) { |
| 1342 | end_request(req, 0); | ||
| 1342 | continue; | 1343 | continue; |
| 1344 | } | ||
| 1343 | if (rq_data_dir(req) == WRITE) { | 1345 | if (rq_data_dir(req) == WRITE) { |
| 1344 | end_request(req, 0); | 1346 | end_request(req, 0); |
| 1345 | continue; | 1347 | continue; |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 4cc619edf424..bde1c665d9f4 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -1006,6 +1006,7 @@ config GPIO_VR41XX | |||
| 1006 | 1006 | ||
| 1007 | config RAW_DRIVER | 1007 | config RAW_DRIVER |
| 1008 | tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" | 1008 | tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" |
| 1009 | depends on BLOCK | ||
| 1009 | help | 1010 | help |
| 1010 | The raw driver permits block devices to be bound to /dev/raw/rawN. | 1011 | The raw driver permits block devices to be bound to /dev/raw/rawN. |
| 1011 | Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. | 1012 | Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 4c3a5ca9d8f7..b430a12eb819 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -655,6 +655,7 @@ void add_interrupt_randomness(int irq) | |||
| 655 | add_timer_randomness(irq_timer_state[irq], 0x100 + irq); | 655 | add_timer_randomness(irq_timer_state[irq], 0x100 + irq); |
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | #ifdef CONFIG_BLOCK | ||
| 658 | void add_disk_randomness(struct gendisk *disk) | 659 | void add_disk_randomness(struct gendisk *disk) |
| 659 | { | 660 | { |
| 660 | if (!disk || !disk->random) | 661 | if (!disk || !disk->random) |
| @@ -667,6 +668,7 @@ void add_disk_randomness(struct gendisk *disk) | |||
| 667 | } | 668 | } |
| 668 | 669 | ||
| 669 | EXPORT_SYMBOL(add_disk_randomness); | 670 | EXPORT_SYMBOL(add_disk_randomness); |
| 671 | #endif | ||
| 670 | 672 | ||
| 671 | #define EXTRACT_SIZE 10 | 673 | #define EXTRACT_SIZE 10 |
| 672 | 674 | ||
| @@ -918,6 +920,7 @@ void rand_initialize_irq(int irq) | |||
| 918 | } | 920 | } |
| 919 | } | 921 | } |
| 920 | 922 | ||
| 923 | #ifdef CONFIG_BLOCK | ||
| 921 | void rand_initialize_disk(struct gendisk *disk) | 924 | void rand_initialize_disk(struct gendisk *disk) |
| 922 | { | 925 | { |
| 923 | struct timer_rand_state *state; | 926 | struct timer_rand_state *state; |
| @@ -932,6 +935,7 @@ void rand_initialize_disk(struct gendisk *disk) | |||
| 932 | disk->random = state; | 935 | disk->random = state; |
| 933 | } | 936 | } |
| 934 | } | 937 | } |
| 938 | #endif | ||
| 935 | 939 | ||
| 936 | static ssize_t | 940 | static ssize_t |
| 937 | random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) | 941 | random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) |
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index 1a159e8843ca..22d17474755f 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c | |||
| @@ -974,7 +974,6 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) | |||
| 974 | */ | 974 | */ |
| 975 | 975 | ||
| 976 | fc->rst_pkt->device->host->eh_action = &sem; | 976 | fc->rst_pkt->device->host->eh_action = &sem; |
| 977 | fc->rst_pkt->request->rq_status = RQ_SCSI_BUSY; | ||
| 978 | 977 | ||
| 979 | fc->rst_pkt->done = fcp_scsi_reset_done; | 978 | fc->rst_pkt->done = fcp_scsi_reset_done; |
| 980 | 979 | ||
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index b6fb167e20f6..69d627bd537a 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | # Andre Hedrick <andre@linux-ide.org> | 4 | # Andre Hedrick <andre@linux-ide.org> |
| 5 | # | 5 | # |
| 6 | 6 | ||
| 7 | if BLOCK | ||
| 8 | |||
| 7 | menu "ATA/ATAPI/MFM/RLL support" | 9 | menu "ATA/ATAPI/MFM/RLL support" |
| 8 | 10 | ||
| 9 | config IDE | 11 | config IDE |
| @@ -1082,3 +1084,5 @@ config BLK_DEV_HD | |||
| 1082 | endif | 1084 | endif |
| 1083 | 1085 | ||
| 1084 | endmenu | 1086 | endmenu |
| 1087 | |||
| 1088 | endif | ||
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 654d4cd09847..69bbb6206a00 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -372,7 +372,7 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, | |||
| 372 | { | 372 | { |
| 373 | int log = 0; | 373 | int log = 0; |
| 374 | 374 | ||
| 375 | if (!sense || !rq || (rq->flags & REQ_QUIET)) | 375 | if (!sense || !rq || (rq->cmd_flags & REQ_QUIET)) |
| 376 | return 0; | 376 | return 0; |
| 377 | 377 | ||
| 378 | switch (sense->sense_key) { | 378 | switch (sense->sense_key) { |
| @@ -597,7 +597,7 @@ static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq) | |||
| 597 | struct cdrom_info *cd = drive->driver_data; | 597 | struct cdrom_info *cd = drive->driver_data; |
| 598 | 598 | ||
| 599 | ide_init_drive_cmd(rq); | 599 | ide_init_drive_cmd(rq); |
| 600 | rq->flags = REQ_PC; | 600 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 601 | rq->rq_disk = cd->disk; | 601 | rq->rq_disk = cd->disk; |
| 602 | } | 602 | } |
| 603 | 603 | ||
| @@ -617,7 +617,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, | |||
| 617 | rq->cmd[0] = GPCMD_REQUEST_SENSE; | 617 | rq->cmd[0] = GPCMD_REQUEST_SENSE; |
| 618 | rq->cmd[4] = rq->data_len = 18; | 618 | rq->cmd[4] = rq->data_len = 18; |
| 619 | 619 | ||
| 620 | rq->flags = REQ_SENSE; | 620 | rq->cmd_type = REQ_TYPE_SENSE; |
| 621 | 621 | ||
| 622 | /* NOTE! Save the failed command in "rq->buffer" */ | 622 | /* NOTE! Save the failed command in "rq->buffer" */ |
| 623 | rq->buffer = (void *) failed_command; | 623 | rq->buffer = (void *) failed_command; |
| @@ -630,10 +630,10 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) | |||
| 630 | struct request *rq = HWGROUP(drive)->rq; | 630 | struct request *rq = HWGROUP(drive)->rq; |
| 631 | int nsectors = rq->hard_cur_sectors; | 631 | int nsectors = rq->hard_cur_sectors; |
| 632 | 632 | ||
| 633 | if ((rq->flags & REQ_SENSE) && uptodate) { | 633 | if (blk_sense_request(rq) && uptodate) { |
| 634 | /* | 634 | /* |
| 635 | * For REQ_SENSE, "rq->buffer" points to the original failed | 635 | * For REQ_TYPE_SENSE, "rq->buffer" points to the original |
| 636 | * request | 636 | * failed request |
| 637 | */ | 637 | */ |
| 638 | struct request *failed = (struct request *) rq->buffer; | 638 | struct request *failed = (struct request *) rq->buffer; |
| 639 | struct cdrom_info *info = drive->driver_data; | 639 | struct cdrom_info *info = drive->driver_data; |
| @@ -706,17 +706,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
| 706 | return 1; | 706 | return 1; |
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | if (rq->flags & REQ_SENSE) { | 709 | if (blk_sense_request(rq)) { |
| 710 | /* We got an error trying to get sense info | 710 | /* We got an error trying to get sense info |
| 711 | from the drive (probably while trying | 711 | from the drive (probably while trying |
| 712 | to recover from a former error). Just give up. */ | 712 | to recover from a former error). Just give up. */ |
| 713 | 713 | ||
| 714 | rq->flags |= REQ_FAILED; | 714 | rq->cmd_flags |= REQ_FAILED; |
| 715 | cdrom_end_request(drive, 0); | 715 | cdrom_end_request(drive, 0); |
| 716 | ide_error(drive, "request sense failure", stat); | 716 | ide_error(drive, "request sense failure", stat); |
| 717 | return 1; | 717 | return 1; |
| 718 | 718 | ||
| 719 | } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) { | 719 | } else if (blk_pc_request(rq)) { |
| 720 | /* All other functions, except for READ. */ | 720 | /* All other functions, except for READ. */ |
| 721 | unsigned long flags; | 721 | unsigned long flags; |
| 722 | 722 | ||
| @@ -724,7 +724,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
| 724 | * if we have an error, pass back CHECK_CONDITION as the | 724 | * if we have an error, pass back CHECK_CONDITION as the |
| 725 | * scsi status byte | 725 | * scsi status byte |
| 726 | */ | 726 | */ |
| 727 | if ((rq->flags & REQ_BLOCK_PC) && !rq->errors) | 727 | if (!rq->errors) |
| 728 | rq->errors = SAM_STAT_CHECK_CONDITION; | 728 | rq->errors = SAM_STAT_CHECK_CONDITION; |
| 729 | 729 | ||
| 730 | /* Check for tray open. */ | 730 | /* Check for tray open. */ |
| @@ -735,12 +735,12 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
| 735 | cdrom_saw_media_change (drive); | 735 | cdrom_saw_media_change (drive); |
| 736 | /*printk("%s: media changed\n",drive->name);*/ | 736 | /*printk("%s: media changed\n",drive->name);*/ |
| 737 | return 0; | 737 | return 0; |
| 738 | } else if (!(rq->flags & REQ_QUIET)) { | 738 | } else if (!(rq->cmd_flags & REQ_QUIET)) { |
| 739 | /* Otherwise, print an error. */ | 739 | /* Otherwise, print an error. */ |
| 740 | ide_dump_status(drive, "packet command error", stat); | 740 | ide_dump_status(drive, "packet command error", stat); |
| 741 | } | 741 | } |
| 742 | 742 | ||
| 743 | rq->flags |= REQ_FAILED; | 743 | rq->cmd_flags |= REQ_FAILED; |
| 744 | 744 | ||
| 745 | /* | 745 | /* |
| 746 | * instead of playing games with moving completions around, | 746 | * instead of playing games with moving completions around, |
| @@ -881,7 +881,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive) | |||
| 881 | wait = ATAPI_WAIT_PC; | 881 | wait = ATAPI_WAIT_PC; |
| 882 | break; | 882 | break; |
| 883 | default: | 883 | default: |
| 884 | if (!(rq->flags & REQ_QUIET)) | 884 | if (!(rq->cmd_flags & REQ_QUIET)) |
| 885 | printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]); | 885 | printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]); |
| 886 | wait = 0; | 886 | wait = 0; |
| 887 | break; | 887 | break; |
| @@ -1124,7 +1124,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) | |||
| 1124 | if (rq->current_nr_sectors > 0) { | 1124 | if (rq->current_nr_sectors > 0) { |
| 1125 | printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n", | 1125 | printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n", |
| 1126 | drive->name, rq->current_nr_sectors); | 1126 | drive->name, rq->current_nr_sectors); |
| 1127 | rq->flags |= REQ_FAILED; | 1127 | rq->cmd_flags |= REQ_FAILED; |
| 1128 | cdrom_end_request(drive, 0); | 1128 | cdrom_end_request(drive, 0); |
| 1129 | } else | 1129 | } else |
| 1130 | cdrom_end_request(drive, 1); | 1130 | cdrom_end_request(drive, 1); |
| @@ -1456,7 +1456,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) | |||
| 1456 | printk ("%s: cdrom_pc_intr: data underrun %d\n", | 1456 | printk ("%s: cdrom_pc_intr: data underrun %d\n", |
| 1457 | drive->name, pc->buflen); | 1457 | drive->name, pc->buflen); |
| 1458 | */ | 1458 | */ |
| 1459 | rq->flags |= REQ_FAILED; | 1459 | rq->cmd_flags |= REQ_FAILED; |
| 1460 | cdrom_end_request(drive, 0); | 1460 | cdrom_end_request(drive, 0); |
| 1461 | } | 1461 | } |
| 1462 | return ide_stopped; | 1462 | return ide_stopped; |
| @@ -1509,7 +1509,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) | |||
| 1509 | rq->data += thislen; | 1509 | rq->data += thislen; |
| 1510 | rq->data_len -= thislen; | 1510 | rq->data_len -= thislen; |
| 1511 | 1511 | ||
| 1512 | if (rq->flags & REQ_SENSE) | 1512 | if (blk_sense_request(rq)) |
| 1513 | rq->sense_len += thislen; | 1513 | rq->sense_len += thislen; |
| 1514 | } else { | 1514 | } else { |
| 1515 | confused: | 1515 | confused: |
| @@ -1517,7 +1517,7 @@ confused: | |||
| 1517 | "appears confused (ireason = 0x%02x). " | 1517 | "appears confused (ireason = 0x%02x). " |
| 1518 | "Trying to recover by ending request.\n", | 1518 | "Trying to recover by ending request.\n", |
| 1519 | drive->name, ireason); | 1519 | drive->name, ireason); |
| 1520 | rq->flags |= REQ_FAILED; | 1520 | rq->cmd_flags |= REQ_FAILED; |
| 1521 | cdrom_end_request(drive, 0); | 1521 | cdrom_end_request(drive, 0); |
| 1522 | return ide_stopped; | 1522 | return ide_stopped; |
| 1523 | } | 1523 | } |
| @@ -1546,7 +1546,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) | |||
| 1546 | struct cdrom_info *info = drive->driver_data; | 1546 | struct cdrom_info *info = drive->driver_data; |
| 1547 | 1547 | ||
| 1548 | info->dma = 0; | 1548 | info->dma = 0; |
| 1549 | rq->flags &= ~REQ_FAILED; | 1549 | rq->cmd_flags &= ~REQ_FAILED; |
| 1550 | len = rq->data_len; | 1550 | len = rq->data_len; |
| 1551 | 1551 | ||
| 1552 | /* Start sending the command to the drive. */ | 1552 | /* Start sending the command to the drive. */ |
| @@ -1558,7 +1558,7 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) | |||
| 1558 | { | 1558 | { |
| 1559 | struct request_sense sense; | 1559 | struct request_sense sense; |
| 1560 | int retries = 10; | 1560 | int retries = 10; |
| 1561 | unsigned int flags = rq->flags; | 1561 | unsigned int flags = rq->cmd_flags; |
| 1562 | 1562 | ||
| 1563 | if (rq->sense == NULL) | 1563 | if (rq->sense == NULL) |
| 1564 | rq->sense = &sense; | 1564 | rq->sense = &sense; |
| @@ -1567,14 +1567,14 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) | |||
| 1567 | do { | 1567 | do { |
| 1568 | int error; | 1568 | int error; |
| 1569 | unsigned long time = jiffies; | 1569 | unsigned long time = jiffies; |
| 1570 | rq->flags = flags; | 1570 | rq->cmd_flags = flags; |
| 1571 | 1571 | ||
| 1572 | error = ide_do_drive_cmd(drive, rq, ide_wait); | 1572 | error = ide_do_drive_cmd(drive, rq, ide_wait); |
| 1573 | time = jiffies - time; | 1573 | time = jiffies - time; |
| 1574 | 1574 | ||
| 1575 | /* FIXME: we should probably abort/retry or something | 1575 | /* FIXME: we should probably abort/retry or something |
| 1576 | * in case of failure */ | 1576 | * in case of failure */ |
| 1577 | if (rq->flags & REQ_FAILED) { | 1577 | if (rq->cmd_flags & REQ_FAILED) { |
| 1578 | /* The request failed. Retry if it was due to a unit | 1578 | /* The request failed. Retry if it was due to a unit |
| 1579 | attention status | 1579 | attention status |
| 1580 | (usually means media was changed). */ | 1580 | (usually means media was changed). */ |
| @@ -1596,10 +1596,10 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) | |||
| 1596 | } | 1596 | } |
| 1597 | 1597 | ||
| 1598 | /* End of retry loop. */ | 1598 | /* End of retry loop. */ |
| 1599 | } while ((rq->flags & REQ_FAILED) && retries >= 0); | 1599 | } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0); |
| 1600 | 1600 | ||
| 1601 | /* Return an error if the command failed. */ | 1601 | /* Return an error if the command failed. */ |
| 1602 | return (rq->flags & REQ_FAILED) ? -EIO : 0; | 1602 | return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0; |
| 1603 | } | 1603 | } |
| 1604 | 1604 | ||
| 1605 | /* | 1605 | /* |
| @@ -1963,7 +1963,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | |||
| 1963 | { | 1963 | { |
| 1964 | struct cdrom_info *info = drive->driver_data; | 1964 | struct cdrom_info *info = drive->driver_data; |
| 1965 | 1965 | ||
| 1966 | rq->flags |= REQ_QUIET; | 1966 | rq->cmd_flags |= REQ_QUIET; |
| 1967 | 1967 | ||
| 1968 | info->dma = 0; | 1968 | info->dma = 0; |
| 1969 | 1969 | ||
| @@ -2023,11 +2023,11 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) | |||
| 2023 | } | 2023 | } |
| 2024 | info->last_block = block; | 2024 | info->last_block = block; |
| 2025 | return action; | 2025 | return action; |
| 2026 | } else if (rq->flags & (REQ_PC | REQ_SENSE)) { | 2026 | } else if (rq->cmd_type == REQ_TYPE_SENSE) { |
| 2027 | return cdrom_do_packet_command(drive); | 2027 | return cdrom_do_packet_command(drive); |
| 2028 | } else if (rq->flags & REQ_BLOCK_PC) { | 2028 | } else if (blk_pc_request(rq)) { |
| 2029 | return cdrom_do_block_pc(drive, rq); | 2029 | return cdrom_do_block_pc(drive, rq); |
| 2030 | } else if (rq->flags & REQ_SPECIAL) { | 2030 | } else if (blk_special_request(rq)) { |
| 2031 | /* | 2031 | /* |
| 2032 | * right now this can only be a reset... | 2032 | * right now this can only be a reset... |
| 2033 | */ | 2033 | */ |
| @@ -2105,7 +2105,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) | |||
| 2105 | 2105 | ||
| 2106 | req.sense = sense; | 2106 | req.sense = sense; |
| 2107 | req.cmd[0] = GPCMD_TEST_UNIT_READY; | 2107 | req.cmd[0] = GPCMD_TEST_UNIT_READY; |
| 2108 | req.flags |= REQ_QUIET; | 2108 | req.cmd_flags |= REQ_QUIET; |
| 2109 | 2109 | ||
| 2110 | #if ! STANDARD_ATAPI | 2110 | #if ! STANDARD_ATAPI |
| 2111 | /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to | 2111 | /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to |
| @@ -2207,7 +2207,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
| 2207 | req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; | 2207 | req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; |
| 2208 | req.data = (char *)&capbuf; | 2208 | req.data = (char *)&capbuf; |
| 2209 | req.data_len = sizeof(capbuf); | 2209 | req.data_len = sizeof(capbuf); |
| 2210 | req.flags |= REQ_QUIET; | 2210 | req.cmd_flags |= REQ_QUIET; |
| 2211 | 2211 | ||
| 2212 | stat = cdrom_queue_packet_command(drive, &req); | 2212 | stat = cdrom_queue_packet_command(drive, &req); |
| 2213 | if (stat == 0) { | 2213 | if (stat == 0) { |
| @@ -2230,7 +2230,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, | |||
| 2230 | req.sense = sense; | 2230 | req.sense = sense; |
| 2231 | req.data = buf; | 2231 | req.data = buf; |
| 2232 | req.data_len = buflen; | 2232 | req.data_len = buflen; |
| 2233 | req.flags |= REQ_QUIET; | 2233 | req.cmd_flags |= REQ_QUIET; |
| 2234 | req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | 2234 | req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; |
| 2235 | req.cmd[6] = trackno; | 2235 | req.cmd[6] = trackno; |
| 2236 | req.cmd[7] = (buflen >> 8); | 2236 | req.cmd[7] = (buflen >> 8); |
| @@ -2531,7 +2531,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, | |||
| 2531 | req.timeout = cgc->timeout; | 2531 | req.timeout = cgc->timeout; |
| 2532 | 2532 | ||
| 2533 | if (cgc->quiet) | 2533 | if (cgc->quiet) |
| 2534 | req.flags |= REQ_QUIET; | 2534 | req.cmd_flags |= REQ_QUIET; |
| 2535 | 2535 | ||
| 2536 | req.sense = cgc->sense; | 2536 | req.sense = cgc->sense; |
| 2537 | cgc->stat = cdrom_queue_packet_command(drive, &req); | 2537 | cgc->stat = cdrom_queue_packet_command(drive, &req); |
| @@ -2629,7 +2629,8 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi) | |||
| 2629 | int ret; | 2629 | int ret; |
| 2630 | 2630 | ||
| 2631 | cdrom_prepare_request(drive, &req); | 2631 | cdrom_prepare_request(drive, &req); |
| 2632 | req.flags = REQ_SPECIAL | REQ_QUIET; | 2632 | req.cmd_type = REQ_TYPE_SPECIAL; |
| 2633 | req.cmd_flags = REQ_QUIET; | ||
| 2633 | ret = ide_do_drive_cmd(drive, &req, ide_wait); | 2634 | ret = ide_do_drive_cmd(drive, &req, ide_wait); |
| 2634 | 2635 | ||
| 2635 | /* | 2636 | /* |
| @@ -3116,9 +3117,9 @@ static int ide_cdrom_prep_pc(struct request *rq) | |||
| 3116 | 3117 | ||
| 3117 | static int ide_cdrom_prep_fn(request_queue_t *q, struct request *rq) | 3118 | static int ide_cdrom_prep_fn(request_queue_t *q, struct request *rq) |
| 3118 | { | 3119 | { |
| 3119 | if (rq->flags & REQ_CMD) | 3120 | if (blk_fs_request(rq)) |
| 3120 | return ide_cdrom_prep_fs(q, rq); | 3121 | return ide_cdrom_prep_fs(q, rq); |
| 3121 | else if (rq->flags & REQ_BLOCK_PC) | 3122 | else if (blk_pc_request(rq)) |
| 3122 | return ide_cdrom_prep_pc(rq); | 3123 | return ide_cdrom_prep_pc(rq); |
| 3123 | 3124 | ||
| 3124 | return 0; | 3125 | return 0; |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 7cf3eb023521..0a05a377d66a 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
| @@ -699,7 +699,8 @@ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) | |||
| 699 | rq->cmd[0] = WIN_FLUSH_CACHE; | 699 | rq->cmd[0] = WIN_FLUSH_CACHE; |
| 700 | 700 | ||
| 701 | 701 | ||
| 702 | rq->flags |= REQ_DRIVE_TASK; | 702 | rq->cmd_type = REQ_TYPE_ATA_TASK; |
| 703 | rq->cmd_flags |= REQ_SOFTBARRIER; | ||
| 703 | rq->buffer = rq->cmd; | 704 | rq->buffer = rq->cmd; |
| 704 | } | 705 | } |
| 705 | 706 | ||
| @@ -740,7 +741,7 @@ static int set_multcount(ide_drive_t *drive, int arg) | |||
| 740 | if (drive->special.b.set_multmode) | 741 | if (drive->special.b.set_multmode) |
| 741 | return -EBUSY; | 742 | return -EBUSY; |
| 742 | ide_init_drive_cmd (&rq); | 743 | ide_init_drive_cmd (&rq); |
| 743 | rq.flags = REQ_DRIVE_CMD; | 744 | rq.cmd_type = REQ_TYPE_ATA_CMD; |
| 744 | drive->mult_req = arg; | 745 | drive->mult_req = arg; |
| 745 | drive->special.b.set_multmode = 1; | 746 | drive->special.b.set_multmode = 1; |
| 746 | (void) ide_do_drive_cmd (drive, &rq, ide_wait); | 747 | (void) ide_do_drive_cmd (drive, &rq, ide_wait); |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 7c3a13e1cf64..c3546fe9af63 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
| @@ -205,7 +205,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) | |||
| 205 | ide_hwif_t *hwif = HWIF(drive); | 205 | ide_hwif_t *hwif = HWIF(drive); |
| 206 | struct scatterlist *sg = hwif->sg_table; | 206 | struct scatterlist *sg = hwif->sg_table; |
| 207 | 207 | ||
| 208 | BUG_ON((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256); | 208 | BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256); |
| 209 | 209 | ||
| 210 | ide_map_sg(drive, rq); | 210 | ide_map_sg(drive, rq); |
| 211 | 211 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index adbe9f76a505..8ccee9c769f8 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
| @@ -588,7 +588,7 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs) | |||
| 588 | /* Why does this happen? */ | 588 | /* Why does this happen? */ |
| 589 | if (!rq) | 589 | if (!rq) |
| 590 | return 0; | 590 | return 0; |
| 591 | if (!(rq->flags & REQ_SPECIAL)) { //if (!IDEFLOPPY_RQ_CMD (rq->cmd)) { | 591 | if (!blk_special_request(rq)) { |
| 592 | /* our real local end request function */ | 592 | /* our real local end request function */ |
| 593 | ide_end_request(drive, uptodate, nsecs); | 593 | ide_end_request(drive, uptodate, nsecs); |
| 594 | return 0; | 594 | return 0; |
| @@ -689,7 +689,7 @@ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struc | |||
| 689 | 689 | ||
| 690 | ide_init_drive_cmd(rq); | 690 | ide_init_drive_cmd(rq); |
| 691 | rq->buffer = (char *) pc; | 691 | rq->buffer = (char *) pc; |
| 692 | rq->flags = REQ_SPECIAL; //rq->cmd = IDEFLOPPY_PC_RQ; | 692 | rq->cmd_type = REQ_TYPE_SPECIAL; |
| 693 | rq->rq_disk = floppy->disk; | 693 | rq->rq_disk = floppy->disk; |
| 694 | (void) ide_do_drive_cmd(drive, rq, ide_preempt); | 694 | (void) ide_do_drive_cmd(drive, rq, ide_preempt); |
| 695 | } | 695 | } |
| @@ -1250,7 +1250,7 @@ static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t | |||
| 1250 | pc->callback = &idefloppy_rw_callback; | 1250 | pc->callback = &idefloppy_rw_callback; |
| 1251 | pc->rq = rq; | 1251 | pc->rq = rq; |
| 1252 | pc->b_count = cmd == READ ? 0 : rq->bio->bi_size; | 1252 | pc->b_count = cmd == READ ? 0 : rq->bio->bi_size; |
| 1253 | if (rq->flags & REQ_RW) | 1253 | if (rq->cmd_flags & REQ_RW) |
| 1254 | set_bit(PC_WRITING, &pc->flags); | 1254 | set_bit(PC_WRITING, &pc->flags); |
| 1255 | pc->buffer = NULL; | 1255 | pc->buffer = NULL; |
| 1256 | pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; | 1256 | pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; |
| @@ -1281,8 +1281,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request | |||
| 1281 | idefloppy_pc_t *pc; | 1281 | idefloppy_pc_t *pc; |
| 1282 | unsigned long block = (unsigned long)block_s; | 1282 | unsigned long block = (unsigned long)block_s; |
| 1283 | 1283 | ||
| 1284 | debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n", | 1284 | debug_log(KERN_INFO "dev: %s, flags: %lx, errors: %d\n", |
| 1285 | rq->rq_status, | ||
| 1286 | rq->rq_disk ? rq->rq_disk->disk_name : "?", | 1285 | rq->rq_disk ? rq->rq_disk->disk_name : "?", |
| 1287 | rq->flags, rq->errors); | 1286 | rq->flags, rq->errors); |
| 1288 | debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, " | 1287 | debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, " |
| @@ -1303,7 +1302,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request | |||
| 1303 | idefloppy_do_end_request(drive, 0, 0); | 1302 | idefloppy_do_end_request(drive, 0, 0); |
| 1304 | return ide_stopped; | 1303 | return ide_stopped; |
| 1305 | } | 1304 | } |
| 1306 | if (rq->flags & REQ_CMD) { | 1305 | if (blk_fs_request(rq)) { |
| 1307 | if (((long)rq->sector % floppy->bs_factor) || | 1306 | if (((long)rq->sector % floppy->bs_factor) || |
| 1308 | (rq->nr_sectors % floppy->bs_factor)) { | 1307 | (rq->nr_sectors % floppy->bs_factor)) { |
| 1309 | printk("%s: unsupported r/w request size\n", | 1308 | printk("%s: unsupported r/w request size\n", |
| @@ -1313,9 +1312,9 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request | |||
| 1313 | } | 1312 | } |
| 1314 | pc = idefloppy_next_pc_storage(drive); | 1313 | pc = idefloppy_next_pc_storage(drive); |
| 1315 | idefloppy_create_rw_cmd(floppy, pc, rq, block); | 1314 | idefloppy_create_rw_cmd(floppy, pc, rq, block); |
| 1316 | } else if (rq->flags & REQ_SPECIAL) { | 1315 | } else if (blk_special_request(rq)) { |
| 1317 | pc = (idefloppy_pc_t *) rq->buffer; | 1316 | pc = (idefloppy_pc_t *) rq->buffer; |
| 1318 | } else if (rq->flags & REQ_BLOCK_PC) { | 1317 | } else if (blk_pc_request(rq)) { |
| 1319 | pc = idefloppy_next_pc_storage(drive); | 1318 | pc = idefloppy_next_pc_storage(drive); |
| 1320 | if (idefloppy_blockpc_cmd(floppy, pc, rq)) { | 1319 | if (idefloppy_blockpc_cmd(floppy, pc, rq)) { |
| 1321 | idefloppy_do_end_request(drive, 0, 0); | 1320 | idefloppy_do_end_request(drive, 0, 0); |
| @@ -1343,7 +1342,7 @@ static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc) | |||
| 1343 | 1342 | ||
| 1344 | ide_init_drive_cmd (&rq); | 1343 | ide_init_drive_cmd (&rq); |
| 1345 | rq.buffer = (char *) pc; | 1344 | rq.buffer = (char *) pc; |
| 1346 | rq.flags = REQ_SPECIAL; // rq.cmd = IDEFLOPPY_PC_RQ; | 1345 | rq.cmd_type = REQ_TYPE_SPECIAL; |
| 1347 | rq.rq_disk = floppy->disk; | 1346 | rq.rq_disk = floppy->disk; |
| 1348 | 1347 | ||
| 1349 | return ide_do_drive_cmd(drive, &rq, ide_wait); | 1348 | return ide_do_drive_cmd(drive, &rq, ide_wait); |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index fb6795236e76..38479a29d3e1 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
| @@ -59,7 +59,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq, | |||
| 59 | { | 59 | { |
| 60 | int ret = 1; | 60 | int ret = 1; |
| 61 | 61 | ||
| 62 | BUG_ON(!(rq->flags & REQ_STARTED)); | 62 | BUG_ON(!blk_rq_started(rq)); |
| 63 | 63 | ||
| 64 | /* | 64 | /* |
| 65 | * if failfast is set on a request, override number of sectors and | 65 | * if failfast is set on a request, override number of sectors and |
| @@ -141,7 +141,7 @@ enum { | |||
| 141 | 141 | ||
| 142 | static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error) | 142 | static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error) |
| 143 | { | 143 | { |
| 144 | struct request_pm_state *pm = rq->end_io_data; | 144 | struct request_pm_state *pm = rq->data; |
| 145 | 145 | ||
| 146 | if (drive->media != ide_disk) | 146 | if (drive->media != ide_disk) |
| 147 | return; | 147 | return; |
| @@ -164,7 +164,7 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s | |||
| 164 | 164 | ||
| 165 | static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | 165 | static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) |
| 166 | { | 166 | { |
| 167 | struct request_pm_state *pm = rq->end_io_data; | 167 | struct request_pm_state *pm = rq->data; |
| 168 | ide_task_t *args = rq->special; | 168 | ide_task_t *args = rq->special; |
| 169 | 169 | ||
| 170 | memset(args, 0, sizeof(*args)); | 170 | memset(args, 0, sizeof(*args)); |
| @@ -244,7 +244,7 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, | |||
| 244 | 244 | ||
| 245 | spin_lock_irqsave(&ide_lock, flags); | 245 | spin_lock_irqsave(&ide_lock, flags); |
| 246 | 246 | ||
| 247 | BUG_ON(!(rq->flags & REQ_STARTED)); | 247 | BUG_ON(!blk_rq_started(rq)); |
| 248 | 248 | ||
| 249 | /* | 249 | /* |
| 250 | * if failfast is set on a request, override number of sectors and | 250 | * if failfast is set on a request, override number of sectors and |
| @@ -366,7 +366,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) | |||
| 366 | rq = HWGROUP(drive)->rq; | 366 | rq = HWGROUP(drive)->rq; |
| 367 | spin_unlock_irqrestore(&ide_lock, flags); | 367 | spin_unlock_irqrestore(&ide_lock, flags); |
| 368 | 368 | ||
| 369 | if (rq->flags & REQ_DRIVE_CMD) { | 369 | if (rq->cmd_type == REQ_TYPE_ATA_CMD) { |
| 370 | u8 *args = (u8 *) rq->buffer; | 370 | u8 *args = (u8 *) rq->buffer; |
| 371 | if (rq->errors == 0) | 371 | if (rq->errors == 0) |
| 372 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); | 372 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); |
| @@ -376,7 +376,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) | |||
| 376 | args[1] = err; | 376 | args[1] = err; |
| 377 | args[2] = hwif->INB(IDE_NSECTOR_REG); | 377 | args[2] = hwif->INB(IDE_NSECTOR_REG); |
| 378 | } | 378 | } |
| 379 | } else if (rq->flags & REQ_DRIVE_TASK) { | 379 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { |
| 380 | u8 *args = (u8 *) rq->buffer; | 380 | u8 *args = (u8 *) rq->buffer; |
| 381 | if (rq->errors == 0) | 381 | if (rq->errors == 0) |
| 382 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); | 382 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); |
| @@ -390,7 +390,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) | |||
| 390 | args[5] = hwif->INB(IDE_HCYL_REG); | 390 | args[5] = hwif->INB(IDE_HCYL_REG); |
| 391 | args[6] = hwif->INB(IDE_SELECT_REG); | 391 | args[6] = hwif->INB(IDE_SELECT_REG); |
| 392 | } | 392 | } |
| 393 | } else if (rq->flags & REQ_DRIVE_TASKFILE) { | 393 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
| 394 | ide_task_t *args = (ide_task_t *) rq->special; | 394 | ide_task_t *args = (ide_task_t *) rq->special; |
| 395 | if (rq->errors == 0) | 395 | if (rq->errors == 0) |
| 396 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); | 396 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); |
| @@ -421,7 +421,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) | |||
| 421 | } | 421 | } |
| 422 | } | 422 | } |
| 423 | } else if (blk_pm_request(rq)) { | 423 | } else if (blk_pm_request(rq)) { |
| 424 | struct request_pm_state *pm = rq->end_io_data; | 424 | struct request_pm_state *pm = rq->data; |
| 425 | #ifdef DEBUG_PM | 425 | #ifdef DEBUG_PM |
| 426 | printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", | 426 | printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", |
| 427 | drive->name, rq->pm->pm_step, stat, err); | 427 | drive->name, rq->pm->pm_step, stat, err); |
| @@ -587,7 +587,7 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) | |||
| 587 | return ide_stopped; | 587 | return ide_stopped; |
| 588 | 588 | ||
| 589 | /* retry only "normal" I/O: */ | 589 | /* retry only "normal" I/O: */ |
| 590 | if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) { | 590 | if (!blk_fs_request(rq)) { |
| 591 | rq->errors = 1; | 591 | rq->errors = 1; |
| 592 | ide_end_drive_cmd(drive, stat, err); | 592 | ide_end_drive_cmd(drive, stat, err); |
| 593 | return ide_stopped; | 593 | return ide_stopped; |
| @@ -638,7 +638,7 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg) | |||
| 638 | return ide_stopped; | 638 | return ide_stopped; |
| 639 | 639 | ||
| 640 | /* retry only "normal" I/O: */ | 640 | /* retry only "normal" I/O: */ |
| 641 | if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) { | 641 | if (!blk_fs_request(rq)) { |
| 642 | rq->errors = 1; | 642 | rq->errors = 1; |
| 643 | ide_end_drive_cmd(drive, BUSY_STAT, 0); | 643 | ide_end_drive_cmd(drive, BUSY_STAT, 0); |
| 644 | return ide_stopped; | 644 | return ide_stopped; |
| @@ -808,7 +808,7 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq) | |||
| 808 | if (hwif->sg_mapped) /* needed by ide-scsi */ | 808 | if (hwif->sg_mapped) /* needed by ide-scsi */ |
| 809 | return; | 809 | return; |
| 810 | 810 | ||
| 811 | if ((rq->flags & REQ_DRIVE_TASKFILE) == 0) { | 811 | if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) { |
| 812 | hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); | 812 | hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); |
| 813 | } else { | 813 | } else { |
| 814 | sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); | 814 | sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); |
| @@ -844,7 +844,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
| 844 | struct request *rq) | 844 | struct request *rq) |
| 845 | { | 845 | { |
| 846 | ide_hwif_t *hwif = HWIF(drive); | 846 | ide_hwif_t *hwif = HWIF(drive); |
| 847 | if (rq->flags & REQ_DRIVE_TASKFILE) { | 847 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
| 848 | ide_task_t *args = rq->special; | 848 | ide_task_t *args = rq->special; |
| 849 | 849 | ||
| 850 | if (!args) | 850 | if (!args) |
| @@ -866,7 +866,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
| 866 | if (args->tf_out_flags.all != 0) | 866 | if (args->tf_out_flags.all != 0) |
| 867 | return flagged_taskfile(drive, args); | 867 | return flagged_taskfile(drive, args); |
| 868 | return do_rw_taskfile(drive, args); | 868 | return do_rw_taskfile(drive, args); |
| 869 | } else if (rq->flags & REQ_DRIVE_TASK) { | 869 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { |
| 870 | u8 *args = rq->buffer; | 870 | u8 *args = rq->buffer; |
| 871 | u8 sel; | 871 | u8 sel; |
| 872 | 872 | ||
| @@ -892,7 +892,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
| 892 | hwif->OUTB(sel, IDE_SELECT_REG); | 892 | hwif->OUTB(sel, IDE_SELECT_REG); |
| 893 | ide_cmd(drive, args[0], args[2], &drive_cmd_intr); | 893 | ide_cmd(drive, args[0], args[2], &drive_cmd_intr); |
| 894 | return ide_started; | 894 | return ide_started; |
| 895 | } else if (rq->flags & REQ_DRIVE_CMD) { | 895 | } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) { |
| 896 | u8 *args = rq->buffer; | 896 | u8 *args = rq->buffer; |
| 897 | 897 | ||
| 898 | if (!args) | 898 | if (!args) |
| @@ -933,7 +933,7 @@ done: | |||
| 933 | 933 | ||
| 934 | static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | 934 | static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) |
| 935 | { | 935 | { |
| 936 | struct request_pm_state *pm = rq->end_io_data; | 936 | struct request_pm_state *pm = rq->data; |
| 937 | 937 | ||
| 938 | if (blk_pm_suspend_request(rq) && | 938 | if (blk_pm_suspend_request(rq) && |
| 939 | pm->pm_step == ide_pm_state_start_suspend) | 939 | pm->pm_step == ide_pm_state_start_suspend) |
| @@ -980,7 +980,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
| 980 | ide_startstop_t startstop; | 980 | ide_startstop_t startstop; |
| 981 | sector_t block; | 981 | sector_t block; |
| 982 | 982 | ||
| 983 | BUG_ON(!(rq->flags & REQ_STARTED)); | 983 | BUG_ON(!blk_rq_started(rq)); |
| 984 | 984 | ||
| 985 | #ifdef DEBUG | 985 | #ifdef DEBUG |
| 986 | printk("%s: start_request: current=0x%08lx\n", | 986 | printk("%s: start_request: current=0x%08lx\n", |
| @@ -1013,12 +1013,12 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
| 1013 | if (!drive->special.all) { | 1013 | if (!drive->special.all) { |
| 1014 | ide_driver_t *drv; | 1014 | ide_driver_t *drv; |
| 1015 | 1015 | ||
| 1016 | if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) | 1016 | if (rq->cmd_type == REQ_TYPE_ATA_CMD || |
| 1017 | return execute_drive_cmd(drive, rq); | 1017 | rq->cmd_type == REQ_TYPE_ATA_TASK || |
| 1018 | else if (rq->flags & REQ_DRIVE_TASKFILE) | 1018 | rq->cmd_type == REQ_TYPE_ATA_TASKFILE) |
| 1019 | return execute_drive_cmd(drive, rq); | 1019 | return execute_drive_cmd(drive, rq); |
| 1020 | else if (blk_pm_request(rq)) { | 1020 | else if (blk_pm_request(rq)) { |
| 1021 | struct request_pm_state *pm = rq->end_io_data; | 1021 | struct request_pm_state *pm = rq->data; |
| 1022 | #ifdef DEBUG_PM | 1022 | #ifdef DEBUG_PM |
| 1023 | printk("%s: start_power_step(step: %d)\n", | 1023 | printk("%s: start_power_step(step: %d)\n", |
| 1024 | drive->name, rq->pm->pm_step); | 1024 | drive->name, rq->pm->pm_step); |
| @@ -1264,7 +1264,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) | |||
| 1264 | * We count how many times we loop here to make sure we service | 1264 | * We count how many times we loop here to make sure we service |
| 1265 | * all drives in the hwgroup without looping for ever | 1265 | * all drives in the hwgroup without looping for ever |
| 1266 | */ | 1266 | */ |
| 1267 | if (drive->blocked && !blk_pm_request(rq) && !(rq->flags & REQ_PREEMPT)) { | 1267 | if (drive->blocked && !blk_pm_request(rq) && !(rq->cmd_flags & REQ_PREEMPT)) { |
| 1268 | drive = drive->next ? drive->next : hwgroup->drive; | 1268 | drive = drive->next ? drive->next : hwgroup->drive; |
| 1269 | if (loops++ < 4 && !blk_queue_plugged(drive->queue)) | 1269 | if (loops++ < 4 && !blk_queue_plugged(drive->queue)) |
| 1270 | goto again; | 1270 | goto again; |
| @@ -1670,7 +1670,7 @@ irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs) | |||
| 1670 | void ide_init_drive_cmd (struct request *rq) | 1670 | void ide_init_drive_cmd (struct request *rq) |
| 1671 | { | 1671 | { |
| 1672 | memset(rq, 0, sizeof(*rq)); | 1672 | memset(rq, 0, sizeof(*rq)); |
| 1673 | rq->flags = REQ_DRIVE_CMD; | 1673 | rq->cmd_type = REQ_TYPE_ATA_CMD; |
| 1674 | rq->ref_count = 1; | 1674 | rq->ref_count = 1; |
| 1675 | } | 1675 | } |
| 1676 | 1676 | ||
| @@ -1710,7 +1710,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio | |||
| 1710 | int must_wait = (action == ide_wait || action == ide_head_wait); | 1710 | int must_wait = (action == ide_wait || action == ide_head_wait); |
| 1711 | 1711 | ||
| 1712 | rq->errors = 0; | 1712 | rq->errors = 0; |
| 1713 | rq->rq_status = RQ_ACTIVE; | ||
| 1714 | 1713 | ||
| 1715 | /* | 1714 | /* |
| 1716 | * we need to hold an extra reference to request for safe inspection | 1715 | * we need to hold an extra reference to request for safe inspection |
| @@ -1718,7 +1717,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio | |||
| 1718 | */ | 1717 | */ |
| 1719 | if (must_wait) { | 1718 | if (must_wait) { |
| 1720 | rq->ref_count++; | 1719 | rq->ref_count++; |
| 1721 | rq->waiting = &wait; | 1720 | rq->end_io_data = &wait; |
| 1722 | rq->end_io = blk_end_sync_rq; | 1721 | rq->end_io = blk_end_sync_rq; |
| 1723 | } | 1722 | } |
| 1724 | 1723 | ||
| @@ -1727,7 +1726,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio | |||
| 1727 | hwgroup->rq = NULL; | 1726 | hwgroup->rq = NULL; |
| 1728 | if (action == ide_preempt || action == ide_head_wait) { | 1727 | if (action == ide_preempt || action == ide_head_wait) { |
| 1729 | where = ELEVATOR_INSERT_FRONT; | 1728 | where = ELEVATOR_INSERT_FRONT; |
| 1730 | rq->flags |= REQ_PREEMPT; | 1729 | rq->cmd_flags |= REQ_PREEMPT; |
| 1731 | } | 1730 | } |
| 1732 | __elv_add_request(drive->queue, rq, where, 0); | 1731 | __elv_add_request(drive->queue, rq, where, 0); |
| 1733 | ide_do_request(hwgroup, IDE_NO_IRQ); | 1732 | ide_do_request(hwgroup, IDE_NO_IRQ); |
| @@ -1736,7 +1735,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio | |||
| 1736 | err = 0; | 1735 | err = 0; |
| 1737 | if (must_wait) { | 1736 | if (must_wait) { |
| 1738 | wait_for_completion(&wait); | 1737 | wait_for_completion(&wait); |
| 1739 | rq->waiting = NULL; | ||
| 1740 | if (rq->errors) | 1738 | if (rq->errors) |
| 1741 | err = -EIO; | 1739 | err = -EIO; |
| 1742 | 1740 | ||
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 1feff23487d4..850ef63cc986 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c | |||
| @@ -456,13 +456,14 @@ static void ide_dump_opcode(ide_drive_t *drive) | |||
| 456 | spin_unlock(&ide_lock); | 456 | spin_unlock(&ide_lock); |
| 457 | if (!rq) | 457 | if (!rq) |
| 458 | return; | 458 | return; |
| 459 | if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { | 459 | if (rq->cmd_type == REQ_TYPE_ATA_CMD || |
| 460 | rq->cmd_type == REQ_TYPE_ATA_TASK) { | ||
| 460 | char *args = rq->buffer; | 461 | char *args = rq->buffer; |
| 461 | if (args) { | 462 | if (args) { |
| 462 | opcode = args[0]; | 463 | opcode = args[0]; |
| 463 | found = 1; | 464 | found = 1; |
| 464 | } | 465 | } |
| 465 | } else if (rq->flags & REQ_DRIVE_TASKFILE) { | 466 | } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
| 466 | ide_task_t *args = rq->special; | 467 | ide_task_t *args = rq->special; |
| 467 | if (args) { | 468 | if (args) { |
| 468 | task_struct_t *tf = (task_struct_t *) args->tfRegister; | 469 | task_struct_t *tf = (task_struct_t *) args->tfRegister; |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 7067ab997927..2ebc3760f261 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
| @@ -1776,7 +1776,7 @@ static void idetape_create_request_sense_cmd (idetape_pc_t *pc) | |||
| 1776 | static void idetape_init_rq(struct request *rq, u8 cmd) | 1776 | static void idetape_init_rq(struct request *rq, u8 cmd) |
| 1777 | { | 1777 | { |
| 1778 | memset(rq, 0, sizeof(*rq)); | 1778 | memset(rq, 0, sizeof(*rq)); |
| 1779 | rq->flags = REQ_SPECIAL; | 1779 | rq->cmd_type = REQ_TYPE_SPECIAL; |
| 1780 | rq->cmd[0] = cmd; | 1780 | rq->cmd[0] = cmd; |
| 1781 | } | 1781 | } |
| 1782 | 1782 | ||
| @@ -2423,8 +2423,8 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
| 2423 | #if IDETAPE_DEBUG_LOG | 2423 | #if IDETAPE_DEBUG_LOG |
| 2424 | #if 0 | 2424 | #if 0 |
| 2425 | if (tape->debug_level >= 5) | 2425 | if (tape->debug_level >= 5) |
| 2426 | printk(KERN_INFO "ide-tape: rq_status: %d, " | 2426 | printk(KERN_INFO "ide-tape: %d, " |
| 2427 | "dev: %s, cmd: %ld, errors: %d\n", rq->rq_status, | 2427 | "dev: %s, cmd: %ld, errors: %d\n", |
| 2428 | rq->rq_disk->disk_name, rq->cmd[0], rq->errors); | 2428 | rq->rq_disk->disk_name, rq->cmd[0], rq->errors); |
| 2429 | #endif | 2429 | #endif |
| 2430 | if (tape->debug_level >= 2) | 2430 | if (tape->debug_level >= 2) |
| @@ -2433,12 +2433,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
| 2433 | rq->sector, rq->nr_sectors, rq->current_nr_sectors); | 2433 | rq->sector, rq->nr_sectors, rq->current_nr_sectors); |
| 2434 | #endif /* IDETAPE_DEBUG_LOG */ | 2434 | #endif /* IDETAPE_DEBUG_LOG */ |
| 2435 | 2435 | ||
| 2436 | if ((rq->flags & REQ_SPECIAL) == 0) { | 2436 | if (!blk_special_request(rq)) { |
| 2437 | /* | 2437 | /* |
| 2438 | * We do not support buffer cache originated requests. | 2438 | * We do not support buffer cache originated requests. |
| 2439 | */ | 2439 | */ |
| 2440 | printk(KERN_NOTICE "ide-tape: %s: Unsupported request in " | 2440 | printk(KERN_NOTICE "ide-tape: %s: Unsupported request in " |
| 2441 | "request queue (%ld)\n", drive->name, rq->flags); | 2441 | "request queue (%d)\n", drive->name, rq->cmd_type); |
| 2442 | ide_end_request(drive, 0, 0); | 2442 | ide_end_request(drive, 0, 0); |
| 2443 | return ide_stopped; | 2443 | return ide_stopped; |
| 2444 | } | 2444 | } |
| @@ -2768,12 +2768,12 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq) | |||
| 2768 | idetape_tape_t *tape = drive->driver_data; | 2768 | idetape_tape_t *tape = drive->driver_data; |
| 2769 | 2769 | ||
| 2770 | #if IDETAPE_DEBUG_BUGS | 2770 | #if IDETAPE_DEBUG_BUGS |
| 2771 | if (rq == NULL || (rq->flags & REQ_SPECIAL) == 0) { | 2771 | if (rq == NULL || !blk_special_request(rq)) { |
| 2772 | printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n"); | 2772 | printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n"); |
| 2773 | return; | 2773 | return; |
| 2774 | } | 2774 | } |
| 2775 | #endif /* IDETAPE_DEBUG_BUGS */ | 2775 | #endif /* IDETAPE_DEBUG_BUGS */ |
| 2776 | rq->waiting = &wait; | 2776 | rq->end_io_data = &wait; |
| 2777 | rq->end_io = blk_end_sync_rq; | 2777 | rq->end_io = blk_end_sync_rq; |
| 2778 | spin_unlock_irq(&tape->spinlock); | 2778 | spin_unlock_irq(&tape->spinlock); |
| 2779 | wait_for_completion(&wait); | 2779 | wait_for_completion(&wait); |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 97a9244312fc..1d0470c1f957 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
| @@ -363,7 +363,7 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, | |||
| 363 | 363 | ||
| 364 | static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) | 364 | static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) |
| 365 | { | 365 | { |
| 366 | if (rq->flags & REQ_DRIVE_TASKFILE) { | 366 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
| 367 | ide_task_t *task = rq->special; | 367 | ide_task_t *task = rq->special; |
| 368 | 368 | ||
| 369 | if (task->tf_out_flags.all) { | 369 | if (task->tf_out_flags.all) { |
| @@ -474,7 +474,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long | |||
| 474 | struct request rq; | 474 | struct request rq; |
| 475 | 475 | ||
| 476 | memset(&rq, 0, sizeof(rq)); | 476 | memset(&rq, 0, sizeof(rq)); |
| 477 | rq.flags = REQ_DRIVE_TASKFILE; | 477 | rq.cmd_type = REQ_TYPE_ATA_TASKFILE; |
| 478 | rq.buffer = buf; | 478 | rq.buffer = buf; |
| 479 | 479 | ||
| 480 | /* | 480 | /* |
| @@ -499,7 +499,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long | |||
| 499 | rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors; | 499 | rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors; |
| 500 | 500 | ||
| 501 | if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) | 501 | if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) |
| 502 | rq.flags |= REQ_RW; | 502 | rq.cmd_flags |= REQ_RW; |
| 503 | } | 503 | } |
| 504 | 504 | ||
| 505 | rq.special = args; | 505 | rq.special = args; |
| @@ -737,7 +737,7 @@ static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf) | |||
| 737 | struct request rq; | 737 | struct request rq; |
| 738 | 738 | ||
| 739 | ide_init_drive_cmd(&rq); | 739 | ide_init_drive_cmd(&rq); |
| 740 | rq.flags = REQ_DRIVE_TASK; | 740 | rq.cmd_type = REQ_TYPE_ATA_TASK; |
| 741 | rq.buffer = buf; | 741 | rq.buffer = buf; |
| 742 | return ide_do_drive_cmd(drive, &rq, ide_wait); | 742 | return ide_do_drive_cmd(drive, &rq, ide_wait); |
| 743 | } | 743 | } |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 9c8468de1a75..2b1a1389c318 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
| @@ -1217,9 +1217,9 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
| 1217 | memset(&rq, 0, sizeof(rq)); | 1217 | memset(&rq, 0, sizeof(rq)); |
| 1218 | memset(&rqpm, 0, sizeof(rqpm)); | 1218 | memset(&rqpm, 0, sizeof(rqpm)); |
| 1219 | memset(&args, 0, sizeof(args)); | 1219 | memset(&args, 0, sizeof(args)); |
| 1220 | rq.flags = REQ_PM_SUSPEND; | 1220 | rq.cmd_type = REQ_TYPE_PM_SUSPEND; |
| 1221 | rq.special = &args; | 1221 | rq.special = &args; |
| 1222 | rq.end_io_data = &rqpm; | 1222 | rq.data = &rqpm; |
| 1223 | rqpm.pm_step = ide_pm_state_start_suspend; | 1223 | rqpm.pm_step = ide_pm_state_start_suspend; |
| 1224 | if (mesg.event == PM_EVENT_PRETHAW) | 1224 | if (mesg.event == PM_EVENT_PRETHAW) |
| 1225 | mesg.event = PM_EVENT_FREEZE; | 1225 | mesg.event = PM_EVENT_FREEZE; |
| @@ -1238,9 +1238,9 @@ static int generic_ide_resume(struct device *dev) | |||
| 1238 | memset(&rq, 0, sizeof(rq)); | 1238 | memset(&rq, 0, sizeof(rq)); |
| 1239 | memset(&rqpm, 0, sizeof(rqpm)); | 1239 | memset(&rqpm, 0, sizeof(rqpm)); |
| 1240 | memset(&args, 0, sizeof(args)); | 1240 | memset(&args, 0, sizeof(args)); |
| 1241 | rq.flags = REQ_PM_RESUME; | 1241 | rq.cmd_type = REQ_TYPE_PM_RESUME; |
| 1242 | rq.special = &args; | 1242 | rq.special = &args; |
| 1243 | rq.end_io_data = &rqpm; | 1243 | rq.data = &rqpm; |
| 1244 | rqpm.pm_step = ide_pm_state_start_resume; | 1244 | rqpm.pm_step = ide_pm_state_start_resume; |
| 1245 | rqpm.pm_state = PM_EVENT_ON; | 1245 | rqpm.pm_state = PM_EVENT_ON; |
| 1246 | 1246 | ||
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index aebecd8f51cc..4ab931145673 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c | |||
| @@ -626,7 +626,7 @@ repeat: | |||
| 626 | req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ", | 626 | req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ", |
| 627 | cyl, head, sec, nsect, req->buffer); | 627 | cyl, head, sec, nsect, req->buffer); |
| 628 | #endif | 628 | #endif |
| 629 | if (req->flags & REQ_CMD) { | 629 | if (blk_fs_request(req)) { |
| 630 | switch (rq_data_dir(req)) { | 630 | switch (rq_data_dir(req)) { |
| 631 | case READ: | 631 | case READ: |
| 632 | hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr); | 632 | hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr); |
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index bf869ed03eed..6dd31a291d84 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | # Block device driver configuration | 2 | # Block device driver configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | if BLOCK | ||
| 6 | |||
| 5 | menu "Multi-device support (RAID and LVM)" | 7 | menu "Multi-device support (RAID and LVM)" |
| 6 | 8 | ||
| 7 | config MD | 9 | config MD |
| @@ -251,3 +253,4 @@ config DM_MULTIPATH_EMC | |||
| 251 | 253 | ||
| 252 | endmenu | 254 | endmenu |
| 253 | 255 | ||
| 256 | endif | ||
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index 2a374ccb30dd..2b2d45d7baaa 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c | |||
| @@ -126,7 +126,8 @@ static struct request *get_failover_req(struct emc_handler *h, | |||
| 126 | memset(&rq->cmd, 0, BLK_MAX_CDB); | 126 | memset(&rq->cmd, 0, BLK_MAX_CDB); |
| 127 | 127 | ||
| 128 | rq->timeout = EMC_FAILOVER_TIMEOUT; | 128 | rq->timeout = EMC_FAILOVER_TIMEOUT; |
| 129 | rq->flags |= (REQ_BLOCK_PC | REQ_FAILFAST | REQ_NOMERGE); | 129 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 130 | rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; | ||
| 130 | 131 | ||
| 131 | return rq; | 132 | return rq; |
| 132 | } | 133 | } |
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index fef677103880..6443392bffff 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig | |||
| @@ -88,7 +88,7 @@ config I2O_BUS | |||
| 88 | 88 | ||
| 89 | config I2O_BLOCK | 89 | config I2O_BLOCK |
| 90 | tristate "I2O Block OSM" | 90 | tristate "I2O Block OSM" |
| 91 | depends on I2O | 91 | depends on I2O && BLOCK |
| 92 | ---help--- | 92 | ---help--- |
| 93 | Include support for the I2O Block OSM. The Block OSM presents disk | 93 | Include support for the I2O Block OSM. The Block OSM presents disk |
| 94 | and other structured block devices to the operating system. If you | 94 | and other structured block devices to the operating system. If you |
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 1ddc2fb429d5..eaba81bf2eca 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c | |||
| @@ -390,9 +390,9 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) | |||
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | /* request is already processed by us, so return */ | 392 | /* request is already processed by us, so return */ |
| 393 | if (req->flags & REQ_SPECIAL) { | 393 | if (blk_special_request(req)) { |
| 394 | osm_debug("REQ_SPECIAL already set!\n"); | 394 | osm_debug("REQ_SPECIAL already set!\n"); |
| 395 | req->flags |= REQ_DONTPREP; | 395 | req->cmd_flags |= REQ_DONTPREP; |
| 396 | return BLKPREP_OK; | 396 | return BLKPREP_OK; |
| 397 | } | 397 | } |
| 398 | 398 | ||
| @@ -411,7 +411,8 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) | |||
| 411 | ireq = req->special; | 411 | ireq = req->special; |
| 412 | 412 | ||
| 413 | /* do not come back here */ | 413 | /* do not come back here */ |
| 414 | req->flags |= REQ_DONTPREP | REQ_SPECIAL; | 414 | req->cmd_type = REQ_TYPE_SPECIAL; |
| 415 | req->cmd_flags |= REQ_DONTPREP; | ||
| 415 | 416 | ||
| 416 | return BLKPREP_OK; | 417 | return BLKPREP_OK; |
| 417 | }; | 418 | }; |
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 45bcf098e762..f540bd88dc5a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig | |||
| @@ -21,7 +21,7 @@ config MMC_DEBUG | |||
| 21 | 21 | ||
| 22 | config MMC_BLOCK | 22 | config MMC_BLOCK |
| 23 | tristate "MMC block device driver" | 23 | tristate "MMC block device driver" |
| 24 | depends on MMC | 24 | depends on MMC && BLOCK |
| 25 | default y | 25 | default y |
| 26 | help | 26 | help |
| 27 | Say Y here to enable the MMC block device driver support. | 27 | Say Y here to enable the MMC block device driver support. |
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index d2957e35cc6f..b1f6e03e7aa9 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile | |||
| @@ -24,7 +24,8 @@ obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | |||
| 24 | obj-$(CONFIG_MMC_OMAP) += omap.o | 24 | obj-$(CONFIG_MMC_OMAP) += omap.o |
| 25 | obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o | 25 | obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o |
| 26 | 26 | ||
| 27 | mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o | 27 | mmc_core-y := mmc.o mmc_sysfs.o |
| 28 | mmc_core-$(CONFIG_BLOCK) += mmc_queue.o | ||
| 28 | 29 | ||
| 29 | ifeq ($(CONFIG_MMC_DEBUG),y) | 30 | ifeq ($(CONFIG_MMC_DEBUG),y) |
| 30 | EXTRA_CFLAGS += -DDEBUG | 31 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index 74f8cdeeff0f..4ccdd82b680f 100644 --- a/drivers/mmc/mmc_queue.c +++ b/drivers/mmc/mmc_queue.c | |||
| @@ -28,7 +28,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) | |||
| 28 | struct mmc_queue *mq = q->queuedata; | 28 | struct mmc_queue *mq = q->queuedata; |
| 29 | int ret = BLKPREP_KILL; | 29 | int ret = BLKPREP_KILL; |
| 30 | 30 | ||
| 31 | if (req->flags & REQ_SPECIAL) { | 31 | if (blk_special_request(req)) { |
| 32 | /* | 32 | /* |
| 33 | * Special commands already have the command | 33 | * Special commands already have the command |
| 34 | * blocks already setup in req->special. | 34 | * blocks already setup in req->special. |
| @@ -36,7 +36,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) | |||
| 36 | BUG_ON(!req->special); | 36 | BUG_ON(!req->special); |
| 37 | 37 | ||
| 38 | ret = BLKPREP_OK; | 38 | ret = BLKPREP_OK; |
| 39 | } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { | 39 | } else if (blk_fs_request(req) || blk_pc_request(req)) { |
| 40 | /* | 40 | /* |
| 41 | * Block I/O requests need translating according | 41 | * Block I/O requests need translating according |
| 42 | * to the protocol. | 42 | * to the protocol. |
| @@ -50,7 +50,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | if (ret == BLKPREP_OK) | 52 | if (ret == BLKPREP_OK) |
| 53 | req->flags |= REQ_DONTPREP; | 53 | req->cmd_flags |= REQ_DONTPREP; |
| 54 | 54 | ||
| 55 | return ret; | 55 | return ret; |
| 56 | } | 56 | } |
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index a03e862851db..a304b34c2632 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
| @@ -166,7 +166,7 @@ config MTD_CHAR | |||
| 166 | 166 | ||
| 167 | config MTD_BLOCK | 167 | config MTD_BLOCK |
| 168 | tristate "Caching block device access to MTD devices" | 168 | tristate "Caching block device access to MTD devices" |
| 169 | depends on MTD | 169 | depends on MTD && BLOCK |
| 170 | ---help--- | 170 | ---help--- |
| 171 | Although most flash chips have an erase size too large to be useful | 171 | Although most flash chips have an erase size too large to be useful |
| 172 | as block devices, it is possible to use MTD devices which are based | 172 | as block devices, it is possible to use MTD devices which are based |
| @@ -188,7 +188,7 @@ config MTD_BLOCK | |||
| 188 | 188 | ||
| 189 | config MTD_BLOCK_RO | 189 | config MTD_BLOCK_RO |
| 190 | tristate "Readonly block device access to MTD devices" | 190 | tristate "Readonly block device access to MTD devices" |
| 191 | depends on MTD_BLOCK!=y && MTD | 191 | depends on MTD_BLOCK!=y && MTD && BLOCK |
| 192 | help | 192 | help |
| 193 | This allows you to mount read-only file systems (such as cramfs) | 193 | This allows you to mount read-only file systems (such as cramfs) |
| 194 | from an MTD device, without the overhead (and danger) of the caching | 194 | from an MTD device, without the overhead (and danger) of the caching |
| @@ -199,7 +199,7 @@ config MTD_BLOCK_RO | |||
| 199 | 199 | ||
| 200 | config FTL | 200 | config FTL |
| 201 | tristate "FTL (Flash Translation Layer) support" | 201 | tristate "FTL (Flash Translation Layer) support" |
| 202 | depends on MTD | 202 | depends on MTD && BLOCK |
| 203 | ---help--- | 203 | ---help--- |
| 204 | This provides support for the original Flash Translation Layer which | 204 | This provides support for the original Flash Translation Layer which |
| 205 | is part of the PCMCIA specification. It uses a kind of pseudo- | 205 | is part of the PCMCIA specification. It uses a kind of pseudo- |
| @@ -215,7 +215,7 @@ config FTL | |||
| 215 | 215 | ||
| 216 | config NFTL | 216 | config NFTL |
| 217 | tristate "NFTL (NAND Flash Translation Layer) support" | 217 | tristate "NFTL (NAND Flash Translation Layer) support" |
| 218 | depends on MTD | 218 | depends on MTD && BLOCK |
| 219 | ---help--- | 219 | ---help--- |
| 220 | This provides support for the NAND Flash Translation Layer which is | 220 | This provides support for the NAND Flash Translation Layer which is |
| 221 | used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- | 221 | used on M-Systems' DiskOnChip devices. It uses a kind of pseudo- |
| @@ -238,7 +238,7 @@ config NFTL_RW | |||
| 238 | 238 | ||
| 239 | config INFTL | 239 | config INFTL |
| 240 | tristate "INFTL (Inverse NAND Flash Translation Layer) support" | 240 | tristate "INFTL (Inverse NAND Flash Translation Layer) support" |
| 241 | depends on MTD | 241 | depends on MTD && BLOCK |
| 242 | ---help--- | 242 | ---help--- |
| 243 | This provides support for the Inverse NAND Flash Translation | 243 | This provides support for the Inverse NAND Flash Translation |
| 244 | Layer which is used on M-Systems' newer DiskOnChip devices. It | 244 | Layer which is used on M-Systems' newer DiskOnChip devices. It |
| @@ -255,7 +255,7 @@ config INFTL | |||
| 255 | 255 | ||
| 256 | config RFD_FTL | 256 | config RFD_FTL |
| 257 | tristate "Resident Flash Disk (Flash Translation Layer) support" | 257 | tristate "Resident Flash Disk (Flash Translation Layer) support" |
| 258 | depends on MTD | 258 | depends on MTD && BLOCK |
| 259 | ---help--- | 259 | ---help--- |
| 260 | This provides support for the flash translation layer known | 260 | This provides support for the flash translation layer known |
| 261 | as the Resident Flash Disk (RFD), as used by the Embedded BIOS | 261 | as the Resident Flash Disk (RFD), as used by the Embedded BIOS |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 16c02b5ccf7e..440f6851da69 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
| @@ -136,7 +136,7 @@ config MTDRAM_ABS_POS | |||
| 136 | 136 | ||
| 137 | config MTD_BLOCK2MTD | 137 | config MTD_BLOCK2MTD |
| 138 | tristate "MTD using block device" | 138 | tristate "MTD using block device" |
| 139 | depends on MTD | 139 | depends on MTD && BLOCK |
| 140 | help | 140 | help |
| 141 | This driver allows a block device to appear as an MTD. It would | 141 | This driver allows a block device to appear as an MTD. It would |
| 142 | generally be used in the following cases: | 142 | generally be used in the following cases: |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 458d3c8ae1ee..6baf5fe14230 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
| @@ -46,7 +46,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, | |||
| 46 | nsect = req->current_nr_sectors; | 46 | nsect = req->current_nr_sectors; |
| 47 | buf = req->buffer; | 47 | buf = req->buffer; |
| 48 | 48 | ||
| 49 | if (!(req->flags & REQ_CMD)) | 49 | if (!blk_fs_request(req)) |
| 50 | return 0; | 50 | return 0; |
| 51 | 51 | ||
| 52 | if (block + nsect > get_capacity(req->rq_disk)) | 52 | if (block + nsect > get_capacity(req->rq_disk)) |
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig index 929d6fff6152..b250c5354503 100644 --- a/drivers/s390/block/Kconfig +++ b/drivers/s390/block/Kconfig | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | if S390 | 1 | if S390 && BLOCK |
| 2 | 2 | ||
| 3 | comment "S/390 block device drivers" | 3 | comment "S/390 block device drivers" |
| 4 | depends on S390 | 4 | depends on S390 |
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 9d051e5687ea..222a8a71a5e8 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
| @@ -529,7 +529,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) | |||
| 529 | } | 529 | } |
| 530 | cqr->retries = DIAG_MAX_RETRIES; | 530 | cqr->retries = DIAG_MAX_RETRIES; |
| 531 | cqr->buildclk = get_clock(); | 531 | cqr->buildclk = get_clock(); |
| 532 | if (req->flags & REQ_FAILFAST) | 532 | if (req->cmd_flags & REQ_FAILFAST) |
| 533 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | 533 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); |
| 534 | cqr->device = device; | 534 | cqr->device = device; |
| 535 | cqr->expires = DIAG_TIMEOUT; | 535 | cqr->expires = DIAG_TIMEOUT; |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index b7a7fac3f7c3..5ecea3e4fdef 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -1266,7 +1266,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) | |||
| 1266 | recid++; | 1266 | recid++; |
| 1267 | } | 1267 | } |
| 1268 | } | 1268 | } |
| 1269 | if (req->flags & REQ_FAILFAST) | 1269 | if (req->cmd_flags & REQ_FAILFAST) |
| 1270 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | 1270 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); |
| 1271 | cqr->device = device; | 1271 | cqr->device = device; |
| 1272 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 1272 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index e85015be109b..80926c548228 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
| @@ -344,7 +344,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) | |||
| 344 | recid++; | 344 | recid++; |
| 345 | } | 345 | } |
| 346 | } | 346 | } |
| 347 | if (req->flags & REQ_FAILFAST) | 347 | if (req->cmd_flags & REQ_FAILFAST) |
| 348 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | 348 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); |
| 349 | cqr->device = device; | 349 | cqr->device = device; |
| 350 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ | 350 | cqr->expires = 5 * 60 * HZ; /* 5 minutes */ |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index c4dfcc91ddda..dab082002e6f 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -3,11 +3,13 @@ menu "SCSI device support" | |||
| 3 | config RAID_ATTRS | 3 | config RAID_ATTRS |
| 4 | tristate "RAID Transport Class" | 4 | tristate "RAID Transport Class" |
| 5 | default n | 5 | default n |
| 6 | depends on BLOCK | ||
| 6 | ---help--- | 7 | ---help--- |
| 7 | Provides RAID | 8 | Provides RAID |
| 8 | 9 | ||
| 9 | config SCSI | 10 | config SCSI |
| 10 | tristate "SCSI device support" | 11 | tristate "SCSI device support" |
| 12 | depends on BLOCK | ||
| 11 | ---help--- | 13 | ---help--- |
| 12 | If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or | 14 | If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or |
| 13 | any other SCSI device under Linux, say Y and make sure that you know | 15 | any other SCSI device under Linux, say Y and make sure that you know |
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 5dcef48d414f..10353379a074 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c | |||
| @@ -2862,7 +2862,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb) | |||
| 2862 | aic_dev->r_total++; | 2862 | aic_dev->r_total++; |
| 2863 | ptr = aic_dev->r_bins; | 2863 | ptr = aic_dev->r_bins; |
| 2864 | } | 2864 | } |
| 2865 | if(cmd->device->simple_tags && cmd->request->flags & REQ_HARDBARRIER) | 2865 | if(cmd->device->simple_tags && cmd->request->cmd_flags & REQ_HARDBARRIER) |
| 2866 | { | 2866 | { |
| 2867 | aic_dev->barrier_total++; | 2867 | aic_dev->barrier_total++; |
| 2868 | if(scb->tag_action == MSG_ORDERED_Q_TAG) | 2868 | if(scb->tag_action == MSG_ORDERED_Q_TAG) |
| @@ -10158,7 +10158,7 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd, | |||
| 10158 | /* We always force TEST_UNIT_READY to untagged */ | 10158 | /* We always force TEST_UNIT_READY to untagged */ |
| 10159 | if (cmd->cmnd[0] != TEST_UNIT_READY && sdptr->simple_tags) | 10159 | if (cmd->cmnd[0] != TEST_UNIT_READY && sdptr->simple_tags) |
| 10160 | { | 10160 | { |
| 10161 | if (req->flags & REQ_HARDBARRIER) | 10161 | if (req->cmd_flags & REQ_HARDBARRIER) |
| 10162 | { | 10162 | { |
| 10163 | if(sdptr->ordered_tags) | 10163 | if(sdptr->ordered_tags) |
| 10164 | { | 10164 | { |
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 94d1de55607f..1427a41e8441 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
| @@ -344,7 +344,7 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co | |||
| 344 | pc->buffer = buf; | 344 | pc->buffer = buf; |
| 345 | pc->c[0] = REQUEST_SENSE; | 345 | pc->c[0] = REQUEST_SENSE; |
| 346 | pc->c[4] = pc->request_transfer = pc->buffer_size = SCSI_SENSE_BUFFERSIZE; | 346 | pc->c[4] = pc->request_transfer = pc->buffer_size = SCSI_SENSE_BUFFERSIZE; |
| 347 | rq->flags = REQ_SENSE; | 347 | rq->cmd_type = REQ_TYPE_SENSE; |
| 348 | pc->timeout = jiffies + WAIT_READY; | 348 | pc->timeout = jiffies + WAIT_READY; |
| 349 | /* NOTE! Save the failed packet command in "rq->buffer" */ | 349 | /* NOTE! Save the failed packet command in "rq->buffer" */ |
| 350 | rq->buffer = (void *) failed_command->special; | 350 | rq->buffer = (void *) failed_command->special; |
| @@ -398,12 +398,12 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) | |||
| 398 | int errors = rq->errors; | 398 | int errors = rq->errors; |
| 399 | unsigned long flags; | 399 | unsigned long flags; |
| 400 | 400 | ||
| 401 | if (!(rq->flags & (REQ_SPECIAL|REQ_SENSE))) { | 401 | if (!blk_special_request(rq) && !blk_sense_request(rq)) { |
| 402 | ide_end_request(drive, uptodate, nrsecs); | 402 | ide_end_request(drive, uptodate, nrsecs); |
| 403 | return 0; | 403 | return 0; |
| 404 | } | 404 | } |
| 405 | ide_end_drive_cmd (drive, 0, 0); | 405 | ide_end_drive_cmd (drive, 0, 0); |
| 406 | if (rq->flags & REQ_SENSE) { | 406 | if (blk_sense_request(rq)) { |
| 407 | idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer; | 407 | idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer; |
| 408 | if (log) { | 408 | if (log) { |
| 409 | printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number); | 409 | printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number); |
| @@ -708,11 +708,11 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) | |||
| 708 | static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block) | 708 | static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block) |
| 709 | { | 709 | { |
| 710 | #if IDESCSI_DEBUG_LOG | 710 | #if IDESCSI_DEBUG_LOG |
| 711 | printk (KERN_INFO "rq_status: %d, dev: %s, cmd: %x, errors: %d\n",rq->rq_status, rq->rq_disk->disk_name,rq->cmd[0],rq->errors); | 711 | printk (KERN_INFO "dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name,rq->cmd[0],rq->errors); |
| 712 | printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); | 712 | printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); |
| 713 | #endif /* IDESCSI_DEBUG_LOG */ | 713 | #endif /* IDESCSI_DEBUG_LOG */ |
| 714 | 714 | ||
| 715 | if (rq->flags & (REQ_SPECIAL|REQ_SENSE)) { | 715 | if (blk_sense_request(rq) || blk_special_request(rq)) { |
| 716 | return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->special); | 716 | return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->special); |
| 717 | } | 717 | } |
| 718 | blk_dump_rq_flags(rq, "ide-scsi: unsup command"); | 718 | blk_dump_rq_flags(rq, "ide-scsi: unsup command"); |
| @@ -938,7 +938,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd, | |||
| 938 | 938 | ||
| 939 | ide_init_drive_cmd (rq); | 939 | ide_init_drive_cmd (rq); |
| 940 | rq->special = (char *) pc; | 940 | rq->special = (char *) pc; |
| 941 | rq->flags = REQ_SPECIAL; | 941 | rq->cmd_type = REQ_TYPE_SPECIAL; |
| 942 | spin_unlock_irq(host->host_lock); | 942 | spin_unlock_irq(host->host_lock); |
| 943 | rq->rq_disk = scsi->disk; | 943 | rq->rq_disk = scsi->disk; |
| 944 | (void) ide_do_drive_cmd (drive, rq, ide_end); | 944 | (void) ide_do_drive_cmd (drive, rq, ide_end); |
| @@ -992,7 +992,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd) | |||
| 992 | */ | 992 | */ |
| 993 | printk (KERN_ERR "ide-scsi: cmd aborted!\n"); | 993 | printk (KERN_ERR "ide-scsi: cmd aborted!\n"); |
| 994 | 994 | ||
| 995 | if (scsi->pc->rq->flags & REQ_SENSE) | 995 | if (blk_sense_request(scsi->pc->rq)) |
| 996 | kfree(scsi->pc->buffer); | 996 | kfree(scsi->pc->buffer); |
| 997 | kfree(scsi->pc->rq); | 997 | kfree(scsi->pc->rq); |
| 998 | kfree(scsi->pc); | 998 | kfree(scsi->pc); |
| @@ -1042,7 +1042,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) | |||
| 1042 | /* kill current request */ | 1042 | /* kill current request */ |
| 1043 | blkdev_dequeue_request(req); | 1043 | blkdev_dequeue_request(req); |
| 1044 | end_that_request_last(req, 0); | 1044 | end_that_request_last(req, 0); |
| 1045 | if (req->flags & REQ_SENSE) | 1045 | if (blk_sense_request(req)) |
| 1046 | kfree(scsi->pc->buffer); | 1046 | kfree(scsi->pc->buffer); |
| 1047 | kfree(scsi->pc); | 1047 | kfree(scsi->pc); |
| 1048 | scsi->pc = NULL; | 1048 | scsi->pc = NULL; |
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c index 0bd9c60e6455..aa60a5f1fbc3 100644 --- a/drivers/scsi/pluto.c +++ b/drivers/scsi/pluto.c | |||
| @@ -67,7 +67,6 @@ static void __init pluto_detect_done(Scsi_Cmnd *SCpnt) | |||
| 67 | 67 | ||
| 68 | static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt) | 68 | static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt) |
| 69 | { | 69 | { |
| 70 | SCpnt->request->rq_status = RQ_SCSI_DONE; | ||
| 71 | PLND(("Detect done %08lx\n", (long)SCpnt)) | 70 | PLND(("Detect done %08lx\n", (long)SCpnt)) |
| 72 | if (atomic_dec_and_test (&fcss)) | 71 | if (atomic_dec_and_test (&fcss)) |
| 73 | up(&fc_sem); | 72 | up(&fc_sem); |
| @@ -166,7 +165,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) | |||
| 166 | 165 | ||
| 167 | SCpnt->cmd_len = COMMAND_SIZE(INQUIRY); | 166 | SCpnt->cmd_len = COMMAND_SIZE(INQUIRY); |
| 168 | 167 | ||
| 169 | SCpnt->request->rq_status = RQ_SCSI_BUSY; | 168 | SCpnt->request->cmd_flags &= ~REQ_STARTED; |
| 170 | 169 | ||
| 171 | SCpnt->done = pluto_detect_done; | 170 | SCpnt->done = pluto_detect_done; |
| 172 | SCpnt->request_bufflen = 256; | 171 | SCpnt->request_bufflen = 256; |
| @@ -178,7 +177,8 @@ int __init pluto_detect(struct scsi_host_template *tpnt) | |||
| 178 | for (retry = 0; retry < 5; retry++) { | 177 | for (retry = 0; retry < 5; retry++) { |
| 179 | for (i = 0; i < fcscount; i++) { | 178 | for (i = 0; i < fcscount; i++) { |
| 180 | if (!fcs[i].fc) break; | 179 | if (!fcs[i].fc) break; |
| 181 | if (fcs[i].cmd.request->rq_status != RQ_SCSI_DONE) { | 180 | if (!(fcs[i].cmd.request->cmd_flags & REQ_STARTED)) { |
| 181 | fcs[i].cmd.request->cmd_flags |= REQ_STARTED; | ||
| 182 | disable_irq(fcs[i].fc->irq); | 182 | disable_irq(fcs[i].fc->irq); |
| 183 | PLND(("queuecommand %d %d\n", retry, i)) | 183 | PLND(("queuecommand %d %d\n", retry, i)) |
| 184 | fcp_scsi_queuecommand (&(fcs[i].cmd), | 184 | fcp_scsi_queuecommand (&(fcs[i].cmd), |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 7a054f9d1ee3..da95bce907dd 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
| @@ -592,12 +592,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) | |||
| 592 | return rtn; | 592 | return rtn; |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | |||
| 596 | /* | ||
| 597 | * Per-CPU I/O completion queue. | ||
| 598 | */ | ||
| 599 | static DEFINE_PER_CPU(struct list_head, scsi_done_q); | ||
| 600 | |||
| 601 | /** | 595 | /** |
| 602 | * scsi_req_abort_cmd -- Request command recovery for the specified command | 596 | * scsi_req_abort_cmd -- Request command recovery for the specified command |
| 603 | * cmd: pointer to the SCSI command of interest | 597 | * cmd: pointer to the SCSI command of interest |
| @@ -1065,7 +1059,7 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) | |||
| 1065 | 1059 | ||
| 1066 | spin_lock_irqsave(&sdev->list_lock, flags); | 1060 | spin_lock_irqsave(&sdev->list_lock, flags); |
| 1067 | list_for_each_entry(scmd, &sdev->cmd_list, list) { | 1061 | list_for_each_entry(scmd, &sdev->cmd_list, list) { |
| 1068 | if (scmd->request && scmd->request->rq_status != RQ_INACTIVE) { | 1062 | if (scmd->request) { |
| 1069 | /* | 1063 | /* |
| 1070 | * If we are unable to remove the timer, it means | 1064 | * If we are unable to remove the timer, it means |
| 1071 | * that the command has already timed out or | 1065 | * that the command has already timed out or |
| @@ -1102,7 +1096,7 @@ MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels"); | |||
| 1102 | 1096 | ||
| 1103 | static int __init init_scsi(void) | 1097 | static int __init init_scsi(void) |
| 1104 | { | 1098 | { |
| 1105 | int error, i; | 1099 | int error; |
| 1106 | 1100 | ||
| 1107 | error = scsi_init_queue(); | 1101 | error = scsi_init_queue(); |
| 1108 | if (error) | 1102 | if (error) |
| @@ -1123,9 +1117,6 @@ static int __init init_scsi(void) | |||
| 1123 | if (error) | 1117 | if (error) |
| 1124 | goto cleanup_sysctl; | 1118 | goto cleanup_sysctl; |
| 1125 | 1119 | ||
| 1126 | for_each_possible_cpu(i) | ||
| 1127 | INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); | ||
| 1128 | |||
| 1129 | scsi_netlink_init(); | 1120 | scsi_netlink_init(); |
| 1130 | 1121 | ||
| 1131 | printk(KERN_NOTICE "SCSI subsystem initialized\n"); | 1122 | printk(KERN_NOTICE "SCSI subsystem initialized\n"); |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index d6743b959a72..71084728eb42 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -82,7 +82,7 @@ static void scsi_unprep_request(struct request *req) | |||
| 82 | { | 82 | { |
| 83 | struct scsi_cmnd *cmd = req->special; | 83 | struct scsi_cmnd *cmd = req->special; |
| 84 | 84 | ||
| 85 | req->flags &= ~REQ_DONTPREP; | 85 | req->cmd_flags &= ~REQ_DONTPREP; |
| 86 | req->special = NULL; | 86 | req->special = NULL; |
| 87 | 87 | ||
| 88 | scsi_put_command(cmd); | 88 | scsi_put_command(cmd); |
| @@ -196,7 +196,8 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
| 196 | req->sense_len = 0; | 196 | req->sense_len = 0; |
| 197 | req->retries = retries; | 197 | req->retries = retries; |
| 198 | req->timeout = timeout; | 198 | req->timeout = timeout; |
| 199 | req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET; | 199 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
| 200 | req->cmd_flags |= flags | REQ_QUIET | REQ_PREEMPT; | ||
| 200 | 201 | ||
| 201 | /* | 202 | /* |
| 202 | * head injection *required* here otherwise quiesce won't work | 203 | * head injection *required* here otherwise quiesce won't work |
| @@ -397,7 +398,8 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, | |||
| 397 | req = blk_get_request(sdev->request_queue, write, gfp); | 398 | req = blk_get_request(sdev->request_queue, write, gfp); |
| 398 | if (!req) | 399 | if (!req) |
| 399 | goto free_sense; | 400 | goto free_sense; |
| 400 | req->flags |= REQ_BLOCK_PC | REQ_QUIET; | 401 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
| 402 | req->cmd_flags |= REQ_QUIET; | ||
| 401 | 403 | ||
| 402 | if (use_sg) | 404 | if (use_sg) |
| 403 | err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp); | 405 | err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp); |
| @@ -933,7 +935,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 933 | break; | 935 | break; |
| 934 | } | 936 | } |
| 935 | } | 937 | } |
| 936 | if (!(req->flags & REQ_QUIET)) { | 938 | if (!(req->cmd_flags & REQ_QUIET)) { |
| 937 | scmd_printk(KERN_INFO, cmd, | 939 | scmd_printk(KERN_INFO, cmd, |
| 938 | "Device not ready: "); | 940 | "Device not ready: "); |
| 939 | scsi_print_sense_hdr("", &sshdr); | 941 | scsi_print_sense_hdr("", &sshdr); |
| @@ -941,7 +943,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 941 | scsi_end_request(cmd, 0, this_count, 1); | 943 | scsi_end_request(cmd, 0, this_count, 1); |
| 942 | return; | 944 | return; |
| 943 | case VOLUME_OVERFLOW: | 945 | case VOLUME_OVERFLOW: |
| 944 | if (!(req->flags & REQ_QUIET)) { | 946 | if (!(req->cmd_flags & REQ_QUIET)) { |
| 945 | scmd_printk(KERN_INFO, cmd, | 947 | scmd_printk(KERN_INFO, cmd, |
| 946 | "Volume overflow, CDB: "); | 948 | "Volume overflow, CDB: "); |
| 947 | __scsi_print_command(cmd->cmnd); | 949 | __scsi_print_command(cmd->cmnd); |
| @@ -963,7 +965,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 963 | return; | 965 | return; |
| 964 | } | 966 | } |
| 965 | if (result) { | 967 | if (result) { |
| 966 | if (!(req->flags & REQ_QUIET)) { | 968 | if (!(req->cmd_flags & REQ_QUIET)) { |
| 967 | scmd_printk(KERN_INFO, cmd, | 969 | scmd_printk(KERN_INFO, cmd, |
| 968 | "SCSI error: return code = 0x%08x\n", | 970 | "SCSI error: return code = 0x%08x\n", |
| 969 | result); | 971 | result); |
| @@ -995,7 +997,7 @@ static int scsi_init_io(struct scsi_cmnd *cmd) | |||
| 995 | /* | 997 | /* |
| 996 | * if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer | 998 | * if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer |
| 997 | */ | 999 | */ |
| 998 | if ((req->flags & REQ_BLOCK_PC) && !req->bio) { | 1000 | if (blk_pc_request(req) && !req->bio) { |
| 999 | cmd->request_bufflen = req->data_len; | 1001 | cmd->request_bufflen = req->data_len; |
| 1000 | cmd->request_buffer = req->data; | 1002 | cmd->request_buffer = req->data; |
| 1001 | req->buffer = req->data; | 1003 | req->buffer = req->data; |
| @@ -1139,13 +1141,12 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
| 1139 | * these two cases differently. We differentiate by looking | 1141 | * these two cases differently. We differentiate by looking |
| 1140 | * at request->cmd, as this tells us the real story. | 1142 | * at request->cmd, as this tells us the real story. |
| 1141 | */ | 1143 | */ |
| 1142 | if (req->flags & REQ_SPECIAL && req->special) { | 1144 | if (blk_special_request(req) && req->special) |
| 1143 | cmd = req->special; | 1145 | cmd = req->special; |
| 1144 | } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { | 1146 | else if (blk_pc_request(req) || blk_fs_request(req)) { |
| 1145 | 1147 | if (unlikely(specials_only) && !(req->cmd_flags & REQ_PREEMPT)){ | |
| 1146 | if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { | 1148 | if (specials_only == SDEV_QUIESCE || |
| 1147 | if(specials_only == SDEV_QUIESCE || | 1149 | specials_only == SDEV_BLOCK) |
| 1148 | specials_only == SDEV_BLOCK) | ||
| 1149 | goto defer; | 1150 | goto defer; |
| 1150 | 1151 | ||
| 1151 | sdev_printk(KERN_ERR, sdev, | 1152 | sdev_printk(KERN_ERR, sdev, |
| @@ -1153,7 +1154,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
| 1153 | goto kill; | 1154 | goto kill; |
| 1154 | } | 1155 | } |
| 1155 | 1156 | ||
| 1156 | |||
| 1157 | /* | 1157 | /* |
| 1158 | * Now try and find a command block that we can use. | 1158 | * Now try and find a command block that we can use. |
| 1159 | */ | 1159 | */ |
| @@ -1184,7 +1184,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
| 1184 | * lock. We hope REQ_STARTED prevents anything untoward from | 1184 | * lock. We hope REQ_STARTED prevents anything untoward from |
| 1185 | * happening now. | 1185 | * happening now. |
| 1186 | */ | 1186 | */ |
| 1187 | if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { | 1187 | if (blk_fs_request(req) || blk_pc_request(req)) { |
| 1188 | int ret; | 1188 | int ret; |
| 1189 | 1189 | ||
| 1190 | /* | 1190 | /* |
| @@ -1216,7 +1216,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
| 1216 | /* | 1216 | /* |
| 1217 | * Initialize the actual SCSI command for this request. | 1217 | * Initialize the actual SCSI command for this request. |
| 1218 | */ | 1218 | */ |
| 1219 | if (req->flags & REQ_BLOCK_PC) { | 1219 | if (blk_pc_request(req)) { |
| 1220 | scsi_setup_blk_pc_cmnd(cmd); | 1220 | scsi_setup_blk_pc_cmnd(cmd); |
| 1221 | } else if (req->rq_disk) { | 1221 | } else if (req->rq_disk) { |
| 1222 | struct scsi_driver *drv; | 1222 | struct scsi_driver *drv; |
| @@ -1233,7 +1233,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
| 1233 | /* | 1233 | /* |
| 1234 | * The request is now prepped, no need to come back here | 1234 | * The request is now prepped, no need to come back here |
| 1235 | */ | 1235 | */ |
| 1236 | req->flags |= REQ_DONTPREP; | 1236 | req->cmd_flags |= REQ_DONTPREP; |
| 1237 | return BLKPREP_OK; | 1237 | return BLKPREP_OK; |
| 1238 | 1238 | ||
| 1239 | defer: | 1239 | defer: |
| @@ -1454,8 +1454,9 @@ static void scsi_request_fn(struct request_queue *q) | |||
| 1454 | if (unlikely(cmd == NULL)) { | 1454 | if (unlikely(cmd == NULL)) { |
| 1455 | printk(KERN_CRIT "impossible request in %s.\n" | 1455 | printk(KERN_CRIT "impossible request in %s.\n" |
| 1456 | "please mail a stack trace to " | 1456 | "please mail a stack trace to " |
| 1457 | "linux-scsi@vger.kernel.org", | 1457 | "linux-scsi@vger.kernel.org\n", |
| 1458 | __FUNCTION__); | 1458 | __FUNCTION__); |
| 1459 | blk_dump_rq_flags(req, "foo"); | ||
| 1459 | BUG(); | 1460 | BUG(); |
| 1460 | } | 1461 | } |
| 1461 | spin_lock(shost->host_lock); | 1462 | spin_lock(shost->host_lock); |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 638cff41d436..10bc99c911fa 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -443,8 +443,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
| 443 | SCpnt->cmnd[0] = READ_6; | 443 | SCpnt->cmnd[0] = READ_6; |
| 444 | SCpnt->sc_data_direction = DMA_FROM_DEVICE; | 444 | SCpnt->sc_data_direction = DMA_FROM_DEVICE; |
| 445 | } else { | 445 | } else { |
| 446 | printk(KERN_ERR "sd: Unknown command %lx\n", rq->flags); | 446 | printk(KERN_ERR "sd: Unknown command %x\n", rq->cmd_flags); |
| 447 | /* overkill panic("Unknown sd command %lx\n", rq->flags); */ | ||
| 448 | return 0; | 447 | return 0; |
| 449 | } | 448 | } |
| 450 | 449 | ||
| @@ -840,7 +839,7 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector) | |||
| 840 | static void sd_prepare_flush(request_queue_t *q, struct request *rq) | 839 | static void sd_prepare_flush(request_queue_t *q, struct request *rq) |
| 841 | { | 840 | { |
| 842 | memset(rq->cmd, 0, sizeof(rq->cmd)); | 841 | memset(rq->cmd, 0, sizeof(rq->cmd)); |
| 843 | rq->flags |= REQ_BLOCK_PC; | 842 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 844 | rq->timeout = SD_TIMEOUT; | 843 | rq->timeout = SD_TIMEOUT; |
| 845 | rq->cmd[0] = SYNCHRONIZE_CACHE; | 844 | rq->cmd[0] = SYNCHRONIZE_CACHE; |
| 846 | rq->cmd_len = 10; | 845 | rq->cmd_len = 10; |
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 2f8073b73bf3..7f9bcef6adfa 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c | |||
| @@ -2017,7 +2017,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) | |||
| 2017 | if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done | 2017 | if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done |
| 2018 | != cmd)) | 2018 | != cmd)) |
| 2019 | { | 2019 | { |
| 2020 | if(cmd->request->flags & REQ_CMD) { | 2020 | if(blk_fs_request(cmd->request)) { |
| 2021 | sun3scsi_dma_setup(d, count, | 2021 | sun3scsi_dma_setup(d, count, |
| 2022 | rq_data_dir(cmd->request)); | 2022 | rq_data_dir(cmd->request)); |
| 2023 | sun3_dma_setup_done = cmd; | 2023 | sun3_dma_setup_done = cmd; |
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 837173415d4c..44a99aeb8180 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c | |||
| @@ -524,7 +524,7 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) | |||
| 524 | static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd, | 524 | static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd, |
| 525 | int write_flag) | 525 | int write_flag) |
| 526 | { | 526 | { |
| 527 | if(cmd->request->flags & REQ_CMD) | 527 | if(blk_fs_request(cmd->request)) |
| 528 | return wanted; | 528 | return wanted; |
| 529 | else | 529 | else |
| 530 | return 0; | 530 | return 0; |
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index 008a82ab8521..f5742b84b27a 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c | |||
| @@ -458,7 +458,7 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) | |||
| 458 | static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd, | 458 | static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd, |
| 459 | int write_flag) | 459 | int write_flag) |
| 460 | { | 460 | { |
| 461 | if(cmd->request->flags & REQ_CMD) | 461 | if(blk_fs_request(cmd->request)) |
| 462 | return wanted; | 462 | return wanted; |
| 463 | else | 463 | else |
| 464 | return 0; | 464 | return 0; |
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 86e48c42d6af..422a4b288e34 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
| @@ -8,8 +8,7 @@ comment "may also be needed; see USB_STORAGE Help for more information" | |||
| 8 | 8 | ||
| 9 | config USB_STORAGE | 9 | config USB_STORAGE |
| 10 | tristate "USB Mass Storage support" | 10 | tristate "USB Mass Storage support" |
| 11 | depends on USB | 11 | depends on USB && SCSI |
| 12 | select SCSI | ||
| 13 | ---help--- | 12 | ---help--- |
| 14 | Say Y here if you want to connect USB mass storage devices to your | 13 | Say Y here if you want to connect USB mass storage devices to your |
| 15 | computer's USB port. This is the driver you need for USB | 14 | computer's USB port. This is the driver you need for USB |
| @@ -18,7 +17,7 @@ config USB_STORAGE | |||
| 18 | similar devices. This driver may also be used for some cameras | 17 | similar devices. This driver may also be used for some cameras |
| 19 | and card readers. | 18 | and card readers. |
| 20 | 19 | ||
| 21 | This option 'selects' (turns on, enables) 'SCSI', but you | 20 | This option depends on 'SCSI' support being enabled, but you |
| 22 | probably also need 'SCSI device support: SCSI disk support' | 21 | probably also need 'SCSI device support: SCSI disk support' |
| 23 | (BLK_DEV_SD) for most USB storage devices. | 22 | (BLK_DEV_SD) for most USB storage devices. |
| 24 | 23 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index 4fd9efac29ab..1453d2d164f7 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | menu "File systems" | 5 | menu "File systems" |
| 6 | 6 | ||
| 7 | if BLOCK | ||
| 8 | |||
| 7 | config EXT2_FS | 9 | config EXT2_FS |
| 8 | tristate "Second extended fs support" | 10 | tristate "Second extended fs support" |
| 9 | help | 11 | help |
| @@ -399,6 +401,8 @@ config ROMFS_FS | |||
| 399 | If you don't know whether you need it, then you don't need it: | 401 | If you don't know whether you need it, then you don't need it: |
| 400 | answer N. | 402 | answer N. |
| 401 | 403 | ||
| 404 | endif | ||
| 405 | |||
| 402 | config INOTIFY | 406 | config INOTIFY |
| 403 | bool "Inotify file change notification support" | 407 | bool "Inotify file change notification support" |
| 404 | default y | 408 | default y |
| @@ -530,6 +534,7 @@ config FUSE_FS | |||
| 530 | If you want to develop a userspace FS, or if you want to use | 534 | If you want to develop a userspace FS, or if you want to use |
| 531 | a filesystem based on FUSE, answer Y or M. | 535 | a filesystem based on FUSE, answer Y or M. |
| 532 | 536 | ||
| 537 | if BLOCK | ||
| 533 | menu "CD-ROM/DVD Filesystems" | 538 | menu "CD-ROM/DVD Filesystems" |
| 534 | 539 | ||
| 535 | config ISO9660_FS | 540 | config ISO9660_FS |
| @@ -597,7 +602,9 @@ config UDF_NLS | |||
| 597 | depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y) | 602 | depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y) |
| 598 | 603 | ||
| 599 | endmenu | 604 | endmenu |
| 605 | endif | ||
| 600 | 606 | ||
| 607 | if BLOCK | ||
| 601 | menu "DOS/FAT/NT Filesystems" | 608 | menu "DOS/FAT/NT Filesystems" |
| 602 | 609 | ||
| 603 | config FAT_FS | 610 | config FAT_FS |
| @@ -782,6 +789,7 @@ config NTFS_RW | |||
| 782 | It is perfectly safe to say N here. | 789 | It is perfectly safe to say N here. |
| 783 | 790 | ||
| 784 | endmenu | 791 | endmenu |
| 792 | endif | ||
| 785 | 793 | ||
| 786 | menu "Pseudo filesystems" | 794 | menu "Pseudo filesystems" |
| 787 | 795 | ||
| @@ -939,7 +947,7 @@ menu "Miscellaneous filesystems" | |||
| 939 | 947 | ||
| 940 | config ADFS_FS | 948 | config ADFS_FS |
| 941 | tristate "ADFS file system support (EXPERIMENTAL)" | 949 | tristate "ADFS file system support (EXPERIMENTAL)" |
| 942 | depends on EXPERIMENTAL | 950 | depends on BLOCK && EXPERIMENTAL |
| 943 | help | 951 | help |
| 944 | The Acorn Disc Filing System is the standard file system of the | 952 | The Acorn Disc Filing System is the standard file system of the |
| 945 | RiscOS operating system which runs on Acorn's ARM-based Risc PC | 953 | RiscOS operating system which runs on Acorn's ARM-based Risc PC |
| @@ -967,7 +975,7 @@ config ADFS_FS_RW | |||
| 967 | 975 | ||
| 968 | config AFFS_FS | 976 | config AFFS_FS |
| 969 | tristate "Amiga FFS file system support (EXPERIMENTAL)" | 977 | tristate "Amiga FFS file system support (EXPERIMENTAL)" |
| 970 | depends on EXPERIMENTAL | 978 | depends on BLOCK && EXPERIMENTAL |
| 971 | help | 979 | help |
| 972 | The Fast File System (FFS) is the common file system used on hard | 980 | The Fast File System (FFS) is the common file system used on hard |
| 973 | disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y | 981 | disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y |
| @@ -989,7 +997,7 @@ config AFFS_FS | |||
| 989 | 997 | ||
| 990 | config HFS_FS | 998 | config HFS_FS |
| 991 | tristate "Apple Macintosh file system support (EXPERIMENTAL)" | 999 | tristate "Apple Macintosh file system support (EXPERIMENTAL)" |
| 992 | depends on EXPERIMENTAL | 1000 | depends on BLOCK && EXPERIMENTAL |
| 993 | select NLS | 1001 | select NLS |
| 994 | help | 1002 | help |
| 995 | If you say Y here, you will be able to mount Macintosh-formatted | 1003 | If you say Y here, you will be able to mount Macintosh-formatted |
| @@ -1002,6 +1010,7 @@ config HFS_FS | |||
| 1002 | 1010 | ||
| 1003 | config HFSPLUS_FS | 1011 | config HFSPLUS_FS |
| 1004 | tristate "Apple Extended HFS file system support" | 1012 | tristate "Apple Extended HFS file system support" |
| 1013 | depends on BLOCK | ||
| 1005 | select NLS | 1014 | select NLS |
| 1006 | select NLS_UTF8 | 1015 | select NLS_UTF8 |
| 1007 | help | 1016 | help |
| @@ -1015,7 +1024,7 @@ config HFSPLUS_FS | |||
| 1015 | 1024 | ||
| 1016 | config BEFS_FS | 1025 | config BEFS_FS |
| 1017 | tristate "BeOS file system (BeFS) support (read only) (EXPERIMENTAL)" | 1026 | tristate "BeOS file system (BeFS) support (read only) (EXPERIMENTAL)" |
| 1018 | depends on EXPERIMENTAL | 1027 | depends on BLOCK && EXPERIMENTAL |
| 1019 | select NLS | 1028 | select NLS |
| 1020 | help | 1029 | help |
| 1021 | The BeOS File System (BeFS) is the native file system of Be, Inc's | 1030 | The BeOS File System (BeFS) is the native file system of Be, Inc's |
| @@ -1042,7 +1051,7 @@ config BEFS_DEBUG | |||
| 1042 | 1051 | ||
| 1043 | config BFS_FS | 1052 | config BFS_FS |
| 1044 | tristate "BFS file system support (EXPERIMENTAL)" | 1053 | tristate "BFS file system support (EXPERIMENTAL)" |
| 1045 | depends on EXPERIMENTAL | 1054 | depends on BLOCK && EXPERIMENTAL |
| 1046 | help | 1055 | help |
| 1047 | Boot File System (BFS) is a file system used under SCO UnixWare to | 1056 | Boot File System (BFS) is a file system used under SCO UnixWare to |
| 1048 | allow the bootloader access to the kernel image and other important | 1057 | allow the bootloader access to the kernel image and other important |
| @@ -1064,7 +1073,7 @@ config BFS_FS | |||
| 1064 | 1073 | ||
| 1065 | config EFS_FS | 1074 | config EFS_FS |
| 1066 | tristate "EFS file system support (read only) (EXPERIMENTAL)" | 1075 | tristate "EFS file system support (read only) (EXPERIMENTAL)" |
| 1067 | depends on EXPERIMENTAL | 1076 | depends on BLOCK && EXPERIMENTAL |
| 1068 | help | 1077 | help |
| 1069 | EFS is an older file system used for non-ISO9660 CD-ROMs and hard | 1078 | EFS is an older file system used for non-ISO9660 CD-ROMs and hard |
| 1070 | disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer | 1079 | disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer |
| @@ -1079,7 +1088,7 @@ config EFS_FS | |||
| 1079 | 1088 | ||
| 1080 | config JFFS_FS | 1089 | config JFFS_FS |
| 1081 | tristate "Journalling Flash File System (JFFS) support" | 1090 | tristate "Journalling Flash File System (JFFS) support" |
| 1082 | depends on MTD | 1091 | depends on MTD && BLOCK |
| 1083 | help | 1092 | help |
| 1084 | JFFS is the Journaling Flash File System developed by Axis | 1093 | JFFS is the Journaling Flash File System developed by Axis |
| 1085 | Communications in Sweden, aimed at providing a crash/powerdown-safe | 1094 | Communications in Sweden, aimed at providing a crash/powerdown-safe |
| @@ -1264,6 +1273,7 @@ endchoice | |||
| 1264 | 1273 | ||
| 1265 | config CRAMFS | 1274 | config CRAMFS |
| 1266 | tristate "Compressed ROM file system support (cramfs)" | 1275 | tristate "Compressed ROM file system support (cramfs)" |
| 1276 | depends on BLOCK | ||
| 1267 | select ZLIB_INFLATE | 1277 | select ZLIB_INFLATE |
| 1268 | help | 1278 | help |
| 1269 | Saying Y here includes support for CramFs (Compressed ROM File | 1279 | Saying Y here includes support for CramFs (Compressed ROM File |
| @@ -1283,6 +1293,7 @@ config CRAMFS | |||
| 1283 | 1293 | ||
| 1284 | config VXFS_FS | 1294 | config VXFS_FS |
| 1285 | tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" | 1295 | tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" |
| 1296 | depends on BLOCK | ||
| 1286 | help | 1297 | help |
| 1287 | FreeVxFS is a file system driver that support the VERITAS VxFS(TM) | 1298 | FreeVxFS is a file system driver that support the VERITAS VxFS(TM) |
| 1288 | file system format. VERITAS VxFS(TM) is the standard file system | 1299 | file system format. VERITAS VxFS(TM) is the standard file system |
| @@ -1300,6 +1311,7 @@ config VXFS_FS | |||
| 1300 | 1311 | ||
| 1301 | config HPFS_FS | 1312 | config HPFS_FS |
| 1302 | tristate "OS/2 HPFS file system support" | 1313 | tristate "OS/2 HPFS file system support" |
| 1314 | depends on BLOCK | ||
| 1303 | help | 1315 | help |
| 1304 | OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS | 1316 | OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS |
| 1305 | is the file system used for organizing files on OS/2 hard disk | 1317 | is the file system used for organizing files on OS/2 hard disk |
| @@ -1316,6 +1328,7 @@ config HPFS_FS | |||
| 1316 | 1328 | ||
| 1317 | config QNX4FS_FS | 1329 | config QNX4FS_FS |
| 1318 | tristate "QNX4 file system support (read only)" | 1330 | tristate "QNX4 file system support (read only)" |
| 1331 | depends on BLOCK | ||
| 1319 | help | 1332 | help |
| 1320 | This is the file system used by the real-time operating systems | 1333 | This is the file system used by the real-time operating systems |
| 1321 | QNX 4 and QNX 6 (the latter is also called QNX RTP). | 1334 | QNX 4 and QNX 6 (the latter is also called QNX RTP). |
| @@ -1343,6 +1356,7 @@ config QNX4FS_RW | |||
| 1343 | 1356 | ||
| 1344 | config SYSV_FS | 1357 | config SYSV_FS |
| 1345 | tristate "System V/Xenix/V7/Coherent file system support" | 1358 | tristate "System V/Xenix/V7/Coherent file system support" |
| 1359 | depends on BLOCK | ||
| 1346 | help | 1360 | help |
| 1347 | SCO, Xenix and Coherent are commercial Unix systems for Intel | 1361 | SCO, Xenix and Coherent are commercial Unix systems for Intel |
| 1348 | machines, and Version 7 was used on the DEC PDP-11. Saying Y | 1362 | machines, and Version 7 was used on the DEC PDP-11. Saying Y |
| @@ -1381,6 +1395,7 @@ config SYSV_FS | |||
| 1381 | 1395 | ||
| 1382 | config UFS_FS | 1396 | config UFS_FS |
| 1383 | tristate "UFS file system support (read only)" | 1397 | tristate "UFS file system support (read only)" |
| 1398 | depends on BLOCK | ||
| 1384 | help | 1399 | help |
| 1385 | BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, | 1400 | BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, |
| 1386 | OpenBSD and NeXTstep) use a file system called UFS. Some System V | 1401 | OpenBSD and NeXTstep) use a file system called UFS. Some System V |
| @@ -1959,11 +1974,13 @@ config GENERIC_ACL | |||
| 1959 | 1974 | ||
| 1960 | endmenu | 1975 | endmenu |
| 1961 | 1976 | ||
| 1977 | if BLOCK | ||
| 1962 | menu "Partition Types" | 1978 | menu "Partition Types" |
| 1963 | 1979 | ||
| 1964 | source "fs/partitions/Kconfig" | 1980 | source "fs/partitions/Kconfig" |
| 1965 | 1981 | ||
| 1966 | endmenu | 1982 | endmenu |
| 1983 | endif | ||
| 1967 | 1984 | ||
| 1968 | source "fs/nls/Kconfig" | 1985 | source "fs/nls/Kconfig" |
| 1969 | 1986 | ||
diff --git a/fs/Makefile b/fs/Makefile index 46b8cfe497b2..a503e6ce0f32 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
| @@ -5,12 +5,18 @@ | |||
| 5 | # Rewritten to use lists instead of if-statements. | 5 | # Rewritten to use lists instead of if-statements. |
| 6 | # | 6 | # |
| 7 | 7 | ||
| 8 | obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ | 8 | obj-y := open.o read_write.o file_table.o super.o \ |
| 9 | block_dev.o char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ | 9 | char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ |
| 10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ | 10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ |
| 11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ | 11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ |
| 12 | seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ | 12 | seq_file.o xattr.o libfs.o fs-writeback.o \ |
| 13 | ioprio.o pnode.o drop_caches.o splice.o sync.o | 13 | pnode.o drop_caches.o splice.o sync.o |
| 14 | |||
| 15 | ifeq ($(CONFIG_BLOCK),y) | ||
| 16 | obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o | ||
| 17 | else | ||
| 18 | obj-y += no-block.o | ||
| 19 | endif | ||
| 14 | 20 | ||
| 15 | obj-$(CONFIG_INOTIFY) += inotify.o | 21 | obj-$(CONFIG_INOTIFY) += inotify.o |
| 16 | obj-$(CONFIG_INOTIFY_USER) += inotify_user.o | 22 | obj-$(CONFIG_INOTIFY_USER) += inotify_user.o |
diff --git a/fs/afs/file.c b/fs/afs/file.c index 67d6634101fd..2e8c42639eaa 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
| 18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 19 | #include <linux/buffer_head.h> | ||
| 20 | #include "volume.h" | 19 | #include "volume.h" |
| 21 | #include "vnode.h" | 20 | #include "vnode.h" |
| 22 | #include <rxrpc/call.h> | 21 | #include <rxrpc/call.h> |
| @@ -37,7 +36,6 @@ struct inode_operations afs_file_inode_operations = { | |||
| 37 | 36 | ||
| 38 | const struct address_space_operations afs_fs_aops = { | 37 | const struct address_space_operations afs_fs_aops = { |
| 39 | .readpage = afs_file_readpage, | 38 | .readpage = afs_file_readpage, |
| 40 | .sync_page = block_sync_page, | ||
| 41 | .set_page_dirty = __set_page_dirty_nobuffers, | 39 | .set_page_dirty = __set_page_dirty_nobuffers, |
| 42 | .releasepage = afs_file_releasepage, | 40 | .releasepage = afs_file_releasepage, |
| 43 | .invalidatepage = afs_file_invalidatepage, | 41 | .invalidatepage = afs_file_invalidatepage, |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6eb48e1446ec..bad52433de69 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -46,7 +46,6 @@ | |||
| 46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); | 46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); |
| 47 | static int load_elf_library(struct file *); | 47 | static int load_elf_library(struct file *); |
| 48 | static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); | 48 | static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); |
| 49 | extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); | ||
| 50 | 49 | ||
| 51 | #ifndef elf_addr_t | 50 | #ifndef elf_addr_t |
| 52 | #define elf_addr_t unsigned long | 51 | #define elf_addr_t unsigned long |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2001 Jens Axboe <axboe@suse.de> | 2 | * Copyright (C) 2001 Jens Axboe <axboe@kernel.dk> |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
| @@ -1142,7 +1142,7 @@ static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale) | |||
| 1142 | struct biovec_slab *bp = bvec_slabs + i; | 1142 | struct biovec_slab *bp = bvec_slabs + i; |
| 1143 | mempool_t **bvp = bs->bvec_pools + i; | 1143 | mempool_t **bvp = bs->bvec_pools + i; |
| 1144 | 1144 | ||
| 1145 | if (i >= scale) | 1145 | if (pool_entries > 1 && i >= scale) |
| 1146 | pool_entries >>= 1; | 1146 | pool_entries >>= 1; |
| 1147 | 1147 | ||
| 1148 | *bvp = mempool_create_slab_pool(pool_entries, bp->slab); | 1148 | *bvp = mempool_create_slab_pool(pool_entries, bp->slab); |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 4346468139e8..0c361ea7e5a6 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -17,11 +17,13 @@ | |||
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/blkpg.h> | 18 | #include <linux/blkpg.h> |
| 19 | #include <linux/buffer_head.h> | 19 | #include <linux/buffer_head.h> |
| 20 | #include <linux/writeback.h> | ||
| 20 | #include <linux/mpage.h> | 21 | #include <linux/mpage.h> |
| 21 | #include <linux/mount.h> | 22 | #include <linux/mount.h> |
| 22 | #include <linux/uio.h> | 23 | #include <linux/uio.h> |
| 23 | #include <linux/namei.h> | 24 | #include <linux/namei.h> |
| 24 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
| 26 | #include "internal.h" | ||
| 25 | 27 | ||
| 26 | struct bdev_inode { | 28 | struct bdev_inode { |
| 27 | struct block_device bdev; | 29 | struct block_device bdev; |
| @@ -1313,3 +1315,24 @@ void close_bdev_excl(struct block_device *bdev) | |||
| 1313 | } | 1315 | } |
| 1314 | 1316 | ||
| 1315 | EXPORT_SYMBOL(close_bdev_excl); | 1317 | EXPORT_SYMBOL(close_bdev_excl); |
| 1318 | |||
| 1319 | int __invalidate_device(struct block_device *bdev) | ||
| 1320 | { | ||
| 1321 | struct super_block *sb = get_super(bdev); | ||
| 1322 | int res = 0; | ||
| 1323 | |||
| 1324 | if (sb) { | ||
| 1325 | /* | ||
| 1326 | * no need to lock the super, get_super holds the | ||
| 1327 | * read mutex so the filesystem cannot go away | ||
| 1328 | * under us (->put_super runs with the write lock | ||
| 1329 | * hold). | ||
| 1330 | */ | ||
| 1331 | shrink_dcache_sb(sb); | ||
| 1332 | res = invalidate_inodes(sb); | ||
| 1333 | drop_super(sb); | ||
| 1334 | } | ||
| 1335 | invalidate_bdev(bdev, 0); | ||
| 1336 | return res; | ||
| 1337 | } | ||
| 1338 | EXPORT_SYMBOL(__invalidate_device); | ||
diff --git a/fs/buffer.c b/fs/buffer.c index 3b6d701073e7..16cfbcd254f1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -159,31 +159,6 @@ int sync_blockdev(struct block_device *bdev) | |||
| 159 | } | 159 | } |
| 160 | EXPORT_SYMBOL(sync_blockdev); | 160 | EXPORT_SYMBOL(sync_blockdev); |
| 161 | 161 | ||
| 162 | static void __fsync_super(struct super_block *sb) | ||
| 163 | { | ||
| 164 | sync_inodes_sb(sb, 0); | ||
| 165 | DQUOT_SYNC(sb); | ||
| 166 | lock_super(sb); | ||
| 167 | if (sb->s_dirt && sb->s_op->write_super) | ||
| 168 | sb->s_op->write_super(sb); | ||
| 169 | unlock_super(sb); | ||
| 170 | if (sb->s_op->sync_fs) | ||
| 171 | sb->s_op->sync_fs(sb, 1); | ||
| 172 | sync_blockdev(sb->s_bdev); | ||
| 173 | sync_inodes_sb(sb, 1); | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * Write out and wait upon all dirty data associated with this | ||
| 178 | * superblock. Filesystem data as well as the underlying block | ||
| 179 | * device. Takes the superblock lock. | ||
| 180 | */ | ||
| 181 | int fsync_super(struct super_block *sb) | ||
| 182 | { | ||
| 183 | __fsync_super(sb); | ||
| 184 | return sync_blockdev(sb->s_bdev); | ||
| 185 | } | ||
| 186 | |||
| 187 | /* | 162 | /* |
| 188 | * Write out and wait upon all dirty data associated with this | 163 | * Write out and wait upon all dirty data associated with this |
| 189 | * device. Filesystem data as well as the underlying block | 164 | * device. Filesystem data as well as the underlying block |
| @@ -260,118 +235,6 @@ void thaw_bdev(struct block_device *bdev, struct super_block *sb) | |||
| 260 | EXPORT_SYMBOL(thaw_bdev); | 235 | EXPORT_SYMBOL(thaw_bdev); |
| 261 | 236 | ||
| 262 | /* | 237 | /* |
| 263 | * sync everything. Start out by waking pdflush, because that writes back | ||
| 264 | * all queues in parallel. | ||
| 265 | */ | ||
| 266 | static void do_sync(unsigned long wait) | ||
| 267 | { | ||
| 268 | wakeup_pdflush(0); | ||
| 269 | sync_inodes(0); /* All mappings, inodes and their blockdevs */ | ||
| 270 | DQUOT_SYNC(NULL); | ||
| 271 | sync_supers(); /* Write the superblocks */ | ||
| 272 | sync_filesystems(0); /* Start syncing the filesystems */ | ||
| 273 | sync_filesystems(wait); /* Waitingly sync the filesystems */ | ||
| 274 | sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */ | ||
| 275 | if (!wait) | ||
| 276 | printk("Emergency Sync complete\n"); | ||
| 277 | if (unlikely(laptop_mode)) | ||
| 278 | laptop_sync_completion(); | ||
| 279 | } | ||
| 280 | |||
| 281 | asmlinkage long sys_sync(void) | ||
| 282 | { | ||
| 283 | do_sync(1); | ||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | void emergency_sync(void) | ||
| 288 | { | ||
| 289 | pdflush_operation(do_sync, 0); | ||
| 290 | } | ||
| 291 | |||
| 292 | /* | ||
| 293 | * Generic function to fsync a file. | ||
| 294 | * | ||
| 295 | * filp may be NULL if called via the msync of a vma. | ||
| 296 | */ | ||
| 297 | |||
| 298 | int file_fsync(struct file *filp, struct dentry *dentry, int datasync) | ||
| 299 | { | ||
| 300 | struct inode * inode = dentry->d_inode; | ||
| 301 | struct super_block * sb; | ||
| 302 | int ret, err; | ||
| 303 | |||
| 304 | /* sync the inode to buffers */ | ||
| 305 | ret = write_inode_now(inode, 0); | ||
| 306 | |||
| 307 | /* sync the superblock to buffers */ | ||
| 308 | sb = inode->i_sb; | ||
| 309 | lock_super(sb); | ||
| 310 | if (sb->s_op->write_super) | ||
| 311 | sb->s_op->write_super(sb); | ||
| 312 | unlock_super(sb); | ||
| 313 | |||
| 314 | /* .. finally sync the buffers to disk */ | ||
| 315 | err = sync_blockdev(sb->s_bdev); | ||
| 316 | if (!ret) | ||
| 317 | ret = err; | ||
| 318 | return ret; | ||
| 319 | } | ||
| 320 | |||
| 321 | long do_fsync(struct file *file, int datasync) | ||
| 322 | { | ||
| 323 | int ret; | ||
| 324 | int err; | ||
| 325 | struct address_space *mapping = file->f_mapping; | ||
| 326 | |||
| 327 | if (!file->f_op || !file->f_op->fsync) { | ||
| 328 | /* Why? We can still call filemap_fdatawrite */ | ||
| 329 | ret = -EINVAL; | ||
| 330 | goto out; | ||
| 331 | } | ||
| 332 | |||
| 333 | ret = filemap_fdatawrite(mapping); | ||
| 334 | |||
| 335 | /* | ||
| 336 | * We need to protect against concurrent writers, which could cause | ||
| 337 | * livelocks in fsync_buffers_list(). | ||
| 338 | */ | ||
| 339 | mutex_lock(&mapping->host->i_mutex); | ||
| 340 | err = file->f_op->fsync(file, file->f_dentry, datasync); | ||
| 341 | if (!ret) | ||
| 342 | ret = err; | ||
| 343 | mutex_unlock(&mapping->host->i_mutex); | ||
| 344 | err = filemap_fdatawait(mapping); | ||
| 345 | if (!ret) | ||
| 346 | ret = err; | ||
| 347 | out: | ||
| 348 | return ret; | ||
| 349 | } | ||
| 350 | |||
| 351 | static long __do_fsync(unsigned int fd, int datasync) | ||
| 352 | { | ||
| 353 | struct file *file; | ||
| 354 | int ret = -EBADF; | ||
| 355 | |||
| 356 | file = fget(fd); | ||
| 357 | if (file) { | ||
| 358 | ret = do_fsync(file, datasync); | ||
| 359 | fput(file); | ||
| 360 | } | ||
| 361 | return ret; | ||
| 362 | } | ||
| 363 | |||
| 364 | asmlinkage long sys_fsync(unsigned int fd) | ||
| 365 | { | ||
| 366 | return __do_fsync(fd, 0); | ||
| 367 | } | ||
| 368 | |||
| 369 | asmlinkage long sys_fdatasync(unsigned int fd) | ||
| 370 | { | ||
| 371 | return __do_fsync(fd, 1); | ||
| 372 | } | ||
| 373 | |||
| 374 | /* | ||
| 375 | * Various filesystems appear to want __find_get_block to be non-blocking. | 238 | * Various filesystems appear to want __find_get_block to be non-blocking. |
| 376 | * But it's the page lock which protects the buffers. To get around this, | 239 | * But it's the page lock which protects the buffers. To get around this, |
| 377 | * we get exclusion from try_to_free_buffers with the blockdev mapping's | 240 | * we get exclusion from try_to_free_buffers with the blockdev mapping's |
| @@ -1551,35 +1414,6 @@ static void discard_buffer(struct buffer_head * bh) | |||
| 1551 | } | 1414 | } |
| 1552 | 1415 | ||
| 1553 | /** | 1416 | /** |
| 1554 | * try_to_release_page() - release old fs-specific metadata on a page | ||
| 1555 | * | ||
| 1556 | * @page: the page which the kernel is trying to free | ||
| 1557 | * @gfp_mask: memory allocation flags (and I/O mode) | ||
| 1558 | * | ||
| 1559 | * The address_space is to try to release any data against the page | ||
| 1560 | * (presumably at page->private). If the release was successful, return `1'. | ||
| 1561 | * Otherwise return zero. | ||
| 1562 | * | ||
| 1563 | * The @gfp_mask argument specifies whether I/O may be performed to release | ||
| 1564 | * this page (__GFP_IO), and whether the call may block (__GFP_WAIT). | ||
| 1565 | * | ||
| 1566 | * NOTE: @gfp_mask may go away, and this function may become non-blocking. | ||
| 1567 | */ | ||
| 1568 | int try_to_release_page(struct page *page, gfp_t gfp_mask) | ||
| 1569 | { | ||
| 1570 | struct address_space * const mapping = page->mapping; | ||
| 1571 | |||
| 1572 | BUG_ON(!PageLocked(page)); | ||
| 1573 | if (PageWriteback(page)) | ||
| 1574 | return 0; | ||
| 1575 | |||
| 1576 | if (mapping && mapping->a_ops->releasepage) | ||
| 1577 | return mapping->a_ops->releasepage(page, gfp_mask); | ||
| 1578 | return try_to_free_buffers(page); | ||
| 1579 | } | ||
| 1580 | EXPORT_SYMBOL(try_to_release_page); | ||
| 1581 | |||
| 1582 | /** | ||
| 1583 | * block_invalidatepage - invalidate part of all of a buffer-backed page | 1417 | * block_invalidatepage - invalidate part of all of a buffer-backed page |
| 1584 | * | 1418 | * |
| 1585 | * @page: the page which is affected | 1419 | * @page: the page which is affected |
| @@ -1630,14 +1464,6 @@ out: | |||
| 1630 | } | 1464 | } |
| 1631 | EXPORT_SYMBOL(block_invalidatepage); | 1465 | EXPORT_SYMBOL(block_invalidatepage); |
| 1632 | 1466 | ||
| 1633 | void do_invalidatepage(struct page *page, unsigned long offset) | ||
| 1634 | { | ||
| 1635 | void (*invalidatepage)(struct page *, unsigned long); | ||
| 1636 | invalidatepage = page->mapping->a_ops->invalidatepage ? : | ||
| 1637 | block_invalidatepage; | ||
| 1638 | (*invalidatepage)(page, offset); | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | /* | 1467 | /* |
| 1642 | * We attach and possibly dirty the buffers atomically wrt | 1468 | * We attach and possibly dirty the buffers atomically wrt |
| 1643 | * __set_page_dirty_buffers() via private_lock. try_to_free_buffers | 1469 | * __set_page_dirty_buffers() via private_lock. try_to_free_buffers |
diff --git a/fs/char_dev.c b/fs/char_dev.c index 1f3285affa39..a885f46ca001 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #ifdef CONFIG_KMOD | 24 | #ifdef CONFIG_KMOD |
| 25 | #include <linux/kmod.h> | 25 | #include <linux/kmod.h> |
| 26 | #endif | 26 | #endif |
| 27 | #include "internal.h" | ||
| 27 | 28 | ||
| 28 | /* | 29 | /* |
| 29 | * capabilities for /dev/mem, /dev/kmem and similar directly mappable character | 30 | * capabilities for /dev/mem, /dev/kmem and similar directly mappable character |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ddb012a68023..976a691c5a68 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/backing-dev.h> | 25 | #include <linux/backing-dev.h> |
| 26 | #include <linux/stat.h> | 26 | #include <linux/stat.h> |
| 27 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
| 28 | #include <linux/mpage.h> | ||
| 29 | #include <linux/pagemap.h> | 28 | #include <linux/pagemap.h> |
| 30 | #include <linux/pagevec.h> | 29 | #include <linux/pagevec.h> |
| 31 | #include <linux/smp_lock.h> | 30 | #include <linux/smp_lock.h> |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b88147c1dc27..05f874c7441b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ | 20 | */ |
| 21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
| 22 | #include <linux/buffer_head.h> | ||
| 23 | #include <linux/stat.h> | 22 | #include <linux/stat.h> |
| 24 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
| 25 | #include <asm/div64.h> | 24 | #include <asm/div64.h> |
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index b0ea6687ab55..e34c7db00f6f 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| 25 | #include <linux/ext2_fs.h> | ||
| 26 | #include "cifspdu.h" | 25 | #include "cifspdu.h" |
| 27 | #include "cifsglob.h" | 26 | #include "cifsglob.h" |
| 28 | #include "cifsproto.h" | 27 | #include "cifsproto.h" |
| @@ -74,7 +73,7 @@ int cifs_ioctl (struct inode * inode, struct file * filep, | |||
| 74 | } | 73 | } |
| 75 | break; | 74 | break; |
| 76 | #ifdef CONFIG_CIFS_POSIX | 75 | #ifdef CONFIG_CIFS_POSIX |
| 77 | case EXT2_IOC_GETFLAGS: | 76 | case FS_IOC_GETFLAGS: |
| 78 | if(CIFS_UNIX_EXTATTR_CAP & caps) { | 77 | if(CIFS_UNIX_EXTATTR_CAP & caps) { |
| 79 | if (pSMBFile == NULL) | 78 | if (pSMBFile == NULL) |
| 80 | break; | 79 | break; |
| @@ -82,12 +81,12 @@ int cifs_ioctl (struct inode * inode, struct file * filep, | |||
| 82 | &ExtAttrBits, &ExtAttrMask); | 81 | &ExtAttrBits, &ExtAttrMask); |
| 83 | if(rc == 0) | 82 | if(rc == 0) |
| 84 | rc = put_user(ExtAttrBits & | 83 | rc = put_user(ExtAttrBits & |
| 85 | EXT2_FL_USER_VISIBLE, | 84 | FS_FL_USER_VISIBLE, |
| 86 | (int __user *)arg); | 85 | (int __user *)arg); |
| 87 | } | 86 | } |
| 88 | break; | 87 | break; |
| 89 | 88 | ||
| 90 | case EXT2_IOC_SETFLAGS: | 89 | case FS_IOC_SETFLAGS: |
| 91 | if(CIFS_UNIX_EXTATTR_CAP & caps) { | 90 | if(CIFS_UNIX_EXTATTR_CAP & caps) { |
| 92 | if(get_user(ExtAttrBits,(int __user *)arg)) { | 91 | if(get_user(ExtAttrBits,(int __user *)arg)) { |
| 93 | rc = -EFAULT; | 92 | rc = -EFAULT; |
diff --git a/fs/compat.c b/fs/compat.c index ce982f6e8c80..122b4e3992b5 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -52,11 +52,12 @@ | |||
| 52 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
| 53 | #include <asm/mmu_context.h> | 53 | #include <asm/mmu_context.h> |
| 54 | #include <asm/ioctls.h> | 54 | #include <asm/ioctls.h> |
| 55 | 55 | #include "internal.h" | |
| 56 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | ||
| 57 | 56 | ||
| 58 | int compat_log = 1; | 57 | int compat_log = 1; |
| 59 | 58 | ||
| 59 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | ||
| 60 | |||
| 60 | int compat_printk(const char *fmt, ...) | 61 | int compat_printk(const char *fmt, ...) |
| 61 | { | 62 | { |
| 62 | va_list ap; | 63 | va_list ap; |
| @@ -313,9 +314,6 @@ out: | |||
| 313 | #define IOCTL_HASHSIZE 256 | 314 | #define IOCTL_HASHSIZE 256 |
| 314 | static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; | 315 | static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; |
| 315 | 316 | ||
| 316 | extern struct ioctl_trans ioctl_start[]; | ||
| 317 | extern int ioctl_table_size; | ||
| 318 | |||
| 319 | static inline unsigned long ioctl32_hash(unsigned long cmd) | 317 | static inline unsigned long ioctl32_hash(unsigned long cmd) |
| 320 | { | 318 | { |
| 321 | return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE; | 319 | return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE; |
| @@ -838,8 +836,6 @@ static int do_nfs4_super_data_conv(void *raw_data) | |||
| 838 | return 0; | 836 | return 0; |
| 839 | } | 837 | } |
| 840 | 838 | ||
| 841 | extern int copy_mount_options (const void __user *, unsigned long *); | ||
| 842 | |||
| 843 | #define SMBFS_NAME "smbfs" | 839 | #define SMBFS_NAME "smbfs" |
| 844 | #define NCPFS_NAME "ncpfs" | 840 | #define NCPFS_NAME "ncpfs" |
| 845 | #define NFS4_NAME "nfs4" | 841 | #define NFS4_NAME "nfs4" |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 4063a9396977..64b34533edea 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -40,15 +40,11 @@ | |||
| 40 | #include <linux/if_pppox.h> | 40 | #include <linux/if_pppox.h> |
| 41 | #include <linux/mtio.h> | 41 | #include <linux/mtio.h> |
| 42 | #include <linux/cdrom.h> | 42 | #include <linux/cdrom.h> |
| 43 | #include <linux/loop.h> | ||
| 44 | #include <linux/auto_fs.h> | 43 | #include <linux/auto_fs.h> |
| 45 | #include <linux/auto_fs4.h> | 44 | #include <linux/auto_fs4.h> |
| 46 | #include <linux/tty.h> | 45 | #include <linux/tty.h> |
| 47 | #include <linux/vt_kern.h> | 46 | #include <linux/vt_kern.h> |
| 48 | #include <linux/fb.h> | 47 | #include <linux/fb.h> |
| 49 | #include <linux/ext2_fs.h> | ||
| 50 | #include <linux/ext3_jbd.h> | ||
| 51 | #include <linux/ext3_fs.h> | ||
| 52 | #include <linux/videodev.h> | 48 | #include <linux/videodev.h> |
| 53 | #include <linux/netdevice.h> | 49 | #include <linux/netdevice.h> |
| 54 | #include <linux/raw.h> | 50 | #include <linux/raw.h> |
| @@ -60,7 +56,6 @@ | |||
| 60 | #include <linux/pci.h> | 56 | #include <linux/pci.h> |
| 61 | #include <linux/module.h> | 57 | #include <linux/module.h> |
| 62 | #include <linux/serial.h> | 58 | #include <linux/serial.h> |
| 63 | #include <linux/reiserfs_fs.h> | ||
| 64 | #include <linux/if_tun.h> | 59 | #include <linux/if_tun.h> |
| 65 | #include <linux/ctype.h> | 60 | #include <linux/ctype.h> |
| 66 | #include <linux/ioctl32.h> | 61 | #include <linux/ioctl32.h> |
| @@ -113,7 +108,6 @@ | |||
| 113 | #include <linux/nbd.h> | 108 | #include <linux/nbd.h> |
| 114 | #include <linux/random.h> | 109 | #include <linux/random.h> |
| 115 | #include <linux/filter.h> | 110 | #include <linux/filter.h> |
| 116 | #include <linux/msdos_fs.h> | ||
| 117 | #include <linux/pktcdvd.h> | 111 | #include <linux/pktcdvd.h> |
| 118 | 112 | ||
| 119 | #include <linux/hiddev.h> | 113 | #include <linux/hiddev.h> |
| @@ -124,21 +118,6 @@ | |||
| 124 | #include <linux/dvb/video.h> | 118 | #include <linux/dvb/video.h> |
| 125 | #include <linux/lp.h> | 119 | #include <linux/lp.h> |
| 126 | 120 | ||
| 127 | /* Aiee. Someone does not find a difference between int and long */ | ||
| 128 | #define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) | ||
| 129 | #define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) | ||
| 130 | #define EXT3_IOC32_GETVERSION _IOR('f', 3, int) | ||
| 131 | #define EXT3_IOC32_SETVERSION _IOW('f', 4, int) | ||
| 132 | #define EXT3_IOC32_GETRSVSZ _IOR('f', 5, int) | ||
| 133 | #define EXT3_IOC32_SETRSVSZ _IOW('f', 6, int) | ||
| 134 | #define EXT3_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int) | ||
| 135 | #ifdef CONFIG_JBD_DEBUG | ||
| 136 | #define EXT3_IOC32_WAIT_FOR_READONLY _IOR('f', 99, int) | ||
| 137 | #endif | ||
| 138 | |||
| 139 | #define EXT2_IOC32_GETVERSION _IOR('v', 1, int) | ||
| 140 | #define EXT2_IOC32_SETVERSION _IOW('v', 2, int) | ||
| 141 | |||
| 142 | static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, | 121 | static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, |
| 143 | unsigned long arg, struct file *f) | 122 | unsigned long arg, struct file *f) |
| 144 | { | 123 | { |
| @@ -176,34 +155,6 @@ static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
| 176 | return err; | 155 | return err; |
| 177 | } | 156 | } |
| 178 | 157 | ||
| 179 | static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
| 180 | { | ||
| 181 | /* These are just misnamed, they actually get/put from/to user an int */ | ||
| 182 | switch (cmd) { | ||
| 183 | case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break; | ||
| 184 | case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break; | ||
| 185 | case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; | ||
| 186 | case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break; | ||
| 187 | } | ||
| 188 | return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg)); | ||
| 189 | } | ||
| 190 | |||
| 191 | static int do_ext3_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
| 192 | { | ||
| 193 | /* These are just misnamed, they actually get/put from/to user an int */ | ||
| 194 | switch (cmd) { | ||
| 195 | case EXT3_IOC32_GETVERSION: cmd = EXT3_IOC_GETVERSION; break; | ||
| 196 | case EXT3_IOC32_SETVERSION: cmd = EXT3_IOC_SETVERSION; break; | ||
| 197 | case EXT3_IOC32_GETRSVSZ: cmd = EXT3_IOC_GETRSVSZ; break; | ||
| 198 | case EXT3_IOC32_SETRSVSZ: cmd = EXT3_IOC_SETRSVSZ; break; | ||
| 199 | case EXT3_IOC32_GROUP_EXTEND: cmd = EXT3_IOC_GROUP_EXTEND; break; | ||
| 200 | #ifdef CONFIG_JBD_DEBUG | ||
| 201 | case EXT3_IOC32_WAIT_FOR_READONLY: cmd = EXT3_IOC_WAIT_FOR_READONLY; break; | ||
| 202 | #endif | ||
| 203 | } | ||
| 204 | return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg)); | ||
| 205 | } | ||
| 206 | |||
| 207 | struct compat_video_event { | 158 | struct compat_video_event { |
| 208 | int32_t type; | 159 | int32_t type; |
| 209 | compat_time_t timestamp; | 160 | compat_time_t timestamp; |
| @@ -694,6 +645,7 @@ out: | |||
| 694 | } | 645 | } |
| 695 | #endif | 646 | #endif |
| 696 | 647 | ||
| 648 | #ifdef CONFIG_BLOCK | ||
| 697 | struct hd_geometry32 { | 649 | struct hd_geometry32 { |
| 698 | unsigned char heads; | 650 | unsigned char heads; |
| 699 | unsigned char sectors; | 651 | unsigned char sectors; |
| @@ -918,6 +870,7 @@ static int sg_grt_trans(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
| 918 | } | 870 | } |
| 919 | return err; | 871 | return err; |
| 920 | } | 872 | } |
| 873 | #endif /* CONFIG_BLOCK */ | ||
| 921 | 874 | ||
| 922 | struct sock_fprog32 { | 875 | struct sock_fprog32 { |
| 923 | unsigned short len; | 876 | unsigned short len; |
| @@ -1041,6 +994,7 @@ static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
| 1041 | } | 994 | } |
| 1042 | 995 | ||
| 1043 | 996 | ||
| 997 | #ifdef CONFIG_BLOCK | ||
| 1044 | struct mtget32 { | 998 | struct mtget32 { |
| 1045 | compat_long_t mt_type; | 999 | compat_long_t mt_type; |
| 1046 | compat_long_t mt_resid; | 1000 | compat_long_t mt_resid; |
| @@ -1213,73 +1167,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar | |||
| 1213 | 1167 | ||
| 1214 | return err; | 1168 | return err; |
| 1215 | } | 1169 | } |
| 1216 | 1170 | #endif /* CONFIG_BLOCK */ | |
| 1217 | struct loop_info32 { | ||
| 1218 | compat_int_t lo_number; /* ioctl r/o */ | ||
| 1219 | compat_dev_t lo_device; /* ioctl r/o */ | ||
| 1220 | compat_ulong_t lo_inode; /* ioctl r/o */ | ||
| 1221 | compat_dev_t lo_rdevice; /* ioctl r/o */ | ||
| 1222 | compat_int_t lo_offset; | ||
| 1223 | compat_int_t lo_encrypt_type; | ||
| 1224 | compat_int_t lo_encrypt_key_size; /* ioctl w/o */ | ||
| 1225 | compat_int_t lo_flags; /* ioctl r/o */ | ||
| 1226 | char lo_name[LO_NAME_SIZE]; | ||
| 1227 | unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ | ||
| 1228 | compat_ulong_t lo_init[2]; | ||
| 1229 | char reserved[4]; | ||
| 1230 | }; | ||
| 1231 | |||
| 1232 | static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) | ||
| 1233 | { | ||
| 1234 | mm_segment_t old_fs = get_fs(); | ||
| 1235 | struct loop_info l; | ||
| 1236 | struct loop_info32 __user *ul; | ||
| 1237 | int err = -EINVAL; | ||
| 1238 | |||
| 1239 | ul = compat_ptr(arg); | ||
| 1240 | switch(cmd) { | ||
| 1241 | case LOOP_SET_STATUS: | ||
| 1242 | err = get_user(l.lo_number, &ul->lo_number); | ||
| 1243 | err |= __get_user(l.lo_device, &ul->lo_device); | ||
| 1244 | err |= __get_user(l.lo_inode, &ul->lo_inode); | ||
| 1245 | err |= __get_user(l.lo_rdevice, &ul->lo_rdevice); | ||
| 1246 | err |= __copy_from_user(&l.lo_offset, &ul->lo_offset, | ||
| 1247 | 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); | ||
| 1248 | if (err) { | ||
| 1249 | err = -EFAULT; | ||
| 1250 | } else { | ||
| 1251 | set_fs (KERNEL_DS); | ||
| 1252 | err = sys_ioctl (fd, cmd, (unsigned long)&l); | ||
| 1253 | set_fs (old_fs); | ||
| 1254 | } | ||
| 1255 | break; | ||
| 1256 | case LOOP_GET_STATUS: | ||
| 1257 | set_fs (KERNEL_DS); | ||
| 1258 | err = sys_ioctl (fd, cmd, (unsigned long)&l); | ||
| 1259 | set_fs (old_fs); | ||
| 1260 | if (!err) { | ||
| 1261 | err = put_user(l.lo_number, &ul->lo_number); | ||
| 1262 | err |= __put_user(l.lo_device, &ul->lo_device); | ||
| 1263 | err |= __put_user(l.lo_inode, &ul->lo_inode); | ||
| 1264 | err |= __put_user(l.lo_rdevice, &ul->lo_rdevice); | ||
| 1265 | err |= __copy_to_user(&ul->lo_offset, &l.lo_offset, | ||
| 1266 | (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); | ||
| 1267 | if (err) | ||
| 1268 | err = -EFAULT; | ||
| 1269 | } | ||
| 1270 | break; | ||
| 1271 | default: { | ||
| 1272 | static int count; | ||
| 1273 | if (++count <= 20) | ||
| 1274 | printk("%s: Unknown loop ioctl cmd, fd(%d) " | ||
| 1275 | "cmd(%08x) arg(%08lx)\n", | ||
| 1276 | __FUNCTION__, fd, cmd, arg); | ||
| 1277 | } | ||
| 1278 | } | ||
| 1279 | return err; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); | ||
| 1283 | 1171 | ||
| 1284 | #ifdef CONFIG_VT | 1172 | #ifdef CONFIG_VT |
| 1285 | 1173 | ||
| @@ -1607,6 +1495,7 @@ ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
| 1607 | return -EINVAL; | 1495 | return -EINVAL; |
| 1608 | } | 1496 | } |
| 1609 | 1497 | ||
| 1498 | #ifdef CONFIG_BLOCK | ||
| 1610 | static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) | 1499 | static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) |
| 1611 | { | 1500 | { |
| 1612 | /* The mkswap binary hard codes it to Intel value :-((( */ | 1501 | /* The mkswap binary hard codes it to Intel value :-((( */ |
| @@ -1641,12 +1530,14 @@ static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar | |||
| 1641 | 1530 | ||
| 1642 | return sys_ioctl(fd, cmd, (unsigned long)a); | 1531 | return sys_ioctl(fd, cmd, (unsigned long)a); |
| 1643 | } | 1532 | } |
| 1533 | #endif | ||
| 1644 | 1534 | ||
| 1645 | static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) | 1535 | static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) |
| 1646 | { | 1536 | { |
| 1647 | return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); | 1537 | return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); |
| 1648 | } | 1538 | } |
| 1649 | 1539 | ||
| 1540 | #ifdef CONFIG_BLOCK | ||
| 1650 | /* Fix sizeof(sizeof()) breakage */ | 1541 | /* Fix sizeof(sizeof()) breakage */ |
| 1651 | #define BLKBSZGET_32 _IOR(0x12,112,int) | 1542 | #define BLKBSZGET_32 _IOR(0x12,112,int) |
| 1652 | #define BLKBSZSET_32 _IOW(0x12,113,int) | 1543 | #define BLKBSZSET_32 _IOW(0x12,113,int) |
| @@ -1667,6 +1558,7 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd, | |||
| 1667 | { | 1558 | { |
| 1668 | return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg)); | 1559 | return sys_ioctl(fd, BLKGETSIZE64, (unsigned long)compat_ptr(arg)); |
| 1669 | } | 1560 | } |
| 1561 | #endif | ||
| 1670 | 1562 | ||
| 1671 | /* Bluetooth ioctls */ | 1563 | /* Bluetooth ioctls */ |
| 1672 | #define HCIUARTSETPROTO _IOW('U', 200, int) | 1564 | #define HCIUARTSETPROTO _IOW('U', 200, int) |
| @@ -1687,6 +1579,7 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd, | |||
| 1687 | #define HIDPGETCONNLIST _IOR('H', 210, int) | 1579 | #define HIDPGETCONNLIST _IOR('H', 210, int) |
| 1688 | #define HIDPGETCONNINFO _IOR('H', 211, int) | 1580 | #define HIDPGETCONNINFO _IOR('H', 211, int) |
| 1689 | 1581 | ||
| 1582 | #ifdef CONFIG_BLOCK | ||
| 1690 | struct floppy_struct32 { | 1583 | struct floppy_struct32 { |
| 1691 | compat_uint_t size; | 1584 | compat_uint_t size; |
| 1692 | compat_uint_t sect; | 1585 | compat_uint_t sect; |
| @@ -2011,6 +1904,7 @@ out: | |||
| 2011 | kfree(karg); | 1904 | kfree(karg); |
| 2012 | return err; | 1905 | return err; |
| 2013 | } | 1906 | } |
| 1907 | #endif | ||
| 2014 | 1908 | ||
| 2015 | struct mtd_oob_buf32 { | 1909 | struct mtd_oob_buf32 { |
| 2016 | u_int32_t start; | 1910 | u_int32_t start; |
| @@ -2052,61 +1946,7 @@ static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
| 2052 | return err; | 1946 | return err; |
| 2053 | } | 1947 | } |
| 2054 | 1948 | ||
| 2055 | #define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2]) | 1949 | #ifdef CONFIG_BLOCK |
| 2056 | #define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2]) | ||
| 2057 | |||
| 2058 | static long | ||
| 2059 | put_dirent32 (struct dirent *d, struct compat_dirent __user *d32) | ||
| 2060 | { | ||
| 2061 | if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent))) | ||
| 2062 | return -EFAULT; | ||
| 2063 | |||
| 2064 | __put_user(d->d_ino, &d32->d_ino); | ||
| 2065 | __put_user(d->d_off, &d32->d_off); | ||
| 2066 | __put_user(d->d_reclen, &d32->d_reclen); | ||
| 2067 | if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen)) | ||
| 2068 | return -EFAULT; | ||
| 2069 | |||
| 2070 | return 0; | ||
| 2071 | } | ||
| 2072 | |||
| 2073 | static int vfat_ioctl32(unsigned fd, unsigned cmd, unsigned long arg) | ||
| 2074 | { | ||
| 2075 | struct compat_dirent __user *p = compat_ptr(arg); | ||
| 2076 | int ret; | ||
| 2077 | mm_segment_t oldfs = get_fs(); | ||
| 2078 | struct dirent d[2]; | ||
| 2079 | |||
| 2080 | switch(cmd) | ||
| 2081 | { | ||
| 2082 | case VFAT_IOCTL_READDIR_BOTH32: | ||
| 2083 | cmd = VFAT_IOCTL_READDIR_BOTH; | ||
| 2084 | break; | ||
| 2085 | case VFAT_IOCTL_READDIR_SHORT32: | ||
| 2086 | cmd = VFAT_IOCTL_READDIR_SHORT; | ||
| 2087 | break; | ||
| 2088 | } | ||
| 2089 | |||
| 2090 | set_fs(KERNEL_DS); | ||
| 2091 | ret = sys_ioctl(fd,cmd,(unsigned long)&d); | ||
| 2092 | set_fs(oldfs); | ||
| 2093 | if (ret >= 0) { | ||
| 2094 | ret |= put_dirent32(&d[0], p); | ||
| 2095 | ret |= put_dirent32(&d[1], p + 1); | ||
| 2096 | } | ||
| 2097 | return ret; | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | #define REISERFS_IOC_UNPACK32 _IOW(0xCD,1,int) | ||
| 2101 | |||
| 2102 | static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) | ||
| 2103 | { | ||
| 2104 | if (cmd == REISERFS_IOC_UNPACK32) | ||
| 2105 | cmd = REISERFS_IOC_UNPACK; | ||
| 2106 | |||
| 2107 | return sys_ioctl(fd,cmd,ptr); | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | struct raw32_config_request | 1950 | struct raw32_config_request |
| 2111 | { | 1951 | { |
| 2112 | compat_int_t raw_minor; | 1952 | compat_int_t raw_minor; |
| @@ -2171,6 +2011,7 @@ static int raw_ioctl(unsigned fd, unsigned cmd, unsigned long arg) | |||
| 2171 | } | 2011 | } |
| 2172 | return ret; | 2012 | return ret; |
| 2173 | } | 2013 | } |
| 2014 | #endif /* CONFIG_BLOCK */ | ||
| 2174 | 2015 | ||
| 2175 | struct serial_struct32 { | 2016 | struct serial_struct32 { |
| 2176 | compat_int_t type; | 2017 | compat_int_t type; |
| @@ -2777,6 +2618,7 @@ HANDLE_IOCTL(SIOCBRDELIF, dev_ifsioc) | |||
| 2777 | HANDLE_IOCTL(SIOCRTMSG, ret_einval) | 2618 | HANDLE_IOCTL(SIOCRTMSG, ret_einval) |
| 2778 | HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) | 2619 | HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) |
| 2779 | #endif | 2620 | #endif |
| 2621 | #ifdef CONFIG_BLOCK | ||
| 2780 | HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) | 2622 | HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) |
| 2781 | HANDLE_IOCTL(BLKRAGET, w_long) | 2623 | HANDLE_IOCTL(BLKRAGET, w_long) |
| 2782 | HANDLE_IOCTL(BLKGETSIZE, w_long) | 2624 | HANDLE_IOCTL(BLKGETSIZE, w_long) |
| @@ -2802,16 +2644,17 @@ HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) | |||
| 2802 | HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) | 2644 | HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) |
| 2803 | HANDLE_IOCTL(SG_IO,sg_ioctl_trans) | 2645 | HANDLE_IOCTL(SG_IO,sg_ioctl_trans) |
| 2804 | HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans) | 2646 | HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans) |
| 2647 | #endif | ||
| 2805 | HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans) | 2648 | HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans) |
| 2806 | HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans) | 2649 | HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans) |
| 2807 | HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans) | 2650 | HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans) |
| 2808 | HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans) | 2651 | HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans) |
| 2652 | #ifdef CONFIG_BLOCK | ||
| 2809 | HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) | 2653 | HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) |
| 2810 | HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) | 2654 | HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) |
| 2811 | HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) | 2655 | HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) |
| 2812 | HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) | 2656 | HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) |
| 2813 | HANDLE_IOCTL(LOOP_SET_STATUS, loop_status) | 2657 | #endif |
| 2814 | HANDLE_IOCTL(LOOP_GET_STATUS, loop_status) | ||
| 2815 | #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) | 2658 | #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) |
| 2816 | HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) | 2659 | HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) |
| 2817 | #ifdef CONFIG_VT | 2660 | #ifdef CONFIG_VT |
| @@ -2821,19 +2664,6 @@ HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl) | |||
| 2821 | HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl) | 2664 | HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl) |
| 2822 | HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) | 2665 | HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) |
| 2823 | #endif | 2666 | #endif |
| 2824 | HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl) | ||
| 2825 | HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl) | ||
| 2826 | HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl) | ||
| 2827 | HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl) | ||
| 2828 | HANDLE_IOCTL(EXT3_IOC32_GETVERSION, do_ext3_ioctl) | ||
| 2829 | HANDLE_IOCTL(EXT3_IOC32_SETVERSION, do_ext3_ioctl) | ||
| 2830 | HANDLE_IOCTL(EXT3_IOC32_GETRSVSZ, do_ext3_ioctl) | ||
| 2831 | HANDLE_IOCTL(EXT3_IOC32_SETRSVSZ, do_ext3_ioctl) | ||
| 2832 | HANDLE_IOCTL(EXT3_IOC32_GROUP_EXTEND, do_ext3_ioctl) | ||
| 2833 | COMPATIBLE_IOCTL(EXT3_IOC_GROUP_ADD) | ||
| 2834 | #ifdef CONFIG_JBD_DEBUG | ||
| 2835 | HANDLE_IOCTL(EXT3_IOC32_WAIT_FOR_READONLY, do_ext3_ioctl) | ||
| 2836 | #endif | ||
| 2837 | /* One SMB ioctl needs translations. */ | 2667 | /* One SMB ioctl needs translations. */ |
| 2838 | #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) | 2668 | #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) |
| 2839 | HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) | 2669 | HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) |
| @@ -2863,16 +2693,14 @@ HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) | |||
| 2863 | HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) | 2693 | HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) |
| 2864 | HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) | 2694 | HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) |
| 2865 | /* block stuff */ | 2695 | /* block stuff */ |
| 2696 | #ifdef CONFIG_BLOCK | ||
| 2866 | HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) | 2697 | HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) |
| 2867 | HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) | 2698 | HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) |
| 2868 | HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) | 2699 | HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) |
| 2869 | /* vfat */ | ||
| 2870 | HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) | ||
| 2871 | HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32) | ||
| 2872 | HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32) | ||
| 2873 | /* Raw devices */ | 2700 | /* Raw devices */ |
| 2874 | HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) | 2701 | HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) |
| 2875 | HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) | 2702 | HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) |
| 2703 | #endif | ||
| 2876 | /* Serial */ | 2704 | /* Serial */ |
| 2877 | HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) | 2705 | HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) |
| 2878 | HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) | 2706 | HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) |
diff --git a/fs/dcache.c b/fs/dcache.c index 17b392a2049e..fc2faa44f8d1 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/seqlock.h> | 32 | #include <linux/seqlock.h> |
| 33 | #include <linux/swap.h> | 33 | #include <linux/swap.h> |
| 34 | #include <linux/bootmem.h> | 34 | #include <linux/bootmem.h> |
| 35 | #include "internal.h" | ||
| 35 | 36 | ||
| 36 | 37 | ||
| 37 | int sysctl_vfs_cache_pressure __read_mostly = 100; | 38 | int sysctl_vfs_cache_pressure __read_mostly = 100; |
| @@ -1877,9 +1878,6 @@ kmem_cache_t *filp_cachep __read_mostly; | |||
| 1877 | 1878 | ||
| 1878 | EXPORT_SYMBOL(d_genocide); | 1879 | EXPORT_SYMBOL(d_genocide); |
| 1879 | 1880 | ||
| 1880 | extern void bdev_cache_init(void); | ||
| 1881 | extern void chrdev_init(void); | ||
| 1882 | |||
| 1883 | void __init vfs_caches_init_early(void) | 1881 | void __init vfs_caches_init_early(void) |
| 1884 | { | 1882 | { |
| 1885 | dcache_init_early(); | 1883 | dcache_init_early(); |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 92ea8265d7d5..3e7a84a1e509 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
| @@ -661,5 +661,8 @@ const struct file_operations ext2_dir_operations = { | |||
| 661 | .read = generic_read_dir, | 661 | .read = generic_read_dir, |
| 662 | .readdir = ext2_readdir, | 662 | .readdir = ext2_readdir, |
| 663 | .ioctl = ext2_ioctl, | 663 | .ioctl = ext2_ioctl, |
| 664 | #ifdef CONFIG_COMPAT | ||
| 665 | .compat_ioctl = ext2_compat_ioctl, | ||
| 666 | #endif | ||
| 664 | .fsync = ext2_sync_file, | 667 | .fsync = ext2_sync_file, |
| 665 | }; | 668 | }; |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index e65a019fc7a5..c19ac153f56b 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
| @@ -137,6 +137,7 @@ extern void ext2_set_inode_flags(struct inode *inode); | |||
| 137 | /* ioctl.c */ | 137 | /* ioctl.c */ |
| 138 | extern int ext2_ioctl (struct inode *, struct file *, unsigned int, | 138 | extern int ext2_ioctl (struct inode *, struct file *, unsigned int, |
| 139 | unsigned long); | 139 | unsigned long); |
| 140 | extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long); | ||
| 140 | 141 | ||
| 141 | /* namei.c */ | 142 | /* namei.c */ |
| 142 | struct dentry *ext2_get_parent(struct dentry *child); | 143 | struct dentry *ext2_get_parent(struct dentry *child); |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 23e2c7ccec1d..e8bbed9dd268 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
| @@ -46,6 +46,9 @@ const struct file_operations ext2_file_operations = { | |||
| 46 | .aio_read = generic_file_aio_read, | 46 | .aio_read = generic_file_aio_read, |
| 47 | .aio_write = generic_file_aio_write, | 47 | .aio_write = generic_file_aio_write, |
| 48 | .ioctl = ext2_ioctl, | 48 | .ioctl = ext2_ioctl, |
| 49 | #ifdef CONFIG_COMPAT | ||
| 50 | .compat_ioctl = ext2_compat_ioctl, | ||
| 51 | #endif | ||
| 49 | .mmap = generic_file_mmap, | 52 | .mmap = generic_file_mmap, |
| 50 | .open = generic_file_open, | 53 | .open = generic_file_open, |
| 51 | .release = ext2_release_file, | 54 | .release = ext2_release_file, |
| @@ -63,6 +66,9 @@ const struct file_operations ext2_xip_file_operations = { | |||
| 63 | .read = xip_file_read, | 66 | .read = xip_file_read, |
| 64 | .write = xip_file_write, | 67 | .write = xip_file_write, |
| 65 | .ioctl = ext2_ioctl, | 68 | .ioctl = ext2_ioctl, |
| 69 | #ifdef CONFIG_COMPAT | ||
| 70 | .compat_ioctl = ext2_compat_ioctl, | ||
| 71 | #endif | ||
| 66 | .mmap = xip_file_mmap, | 72 | .mmap = xip_file_mmap, |
| 67 | .open = generic_file_open, | 73 | .open = generic_file_open, |
| 68 | .release = ext2_release_file, | 74 | .release = ext2_release_file, |
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 3ca9afdf713d..1dfba77eab10 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <linux/capability.h> | 11 | #include <linux/capability.h> |
| 12 | #include <linux/time.h> | 12 | #include <linux/time.h> |
| 13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 14 | #include <linux/compat.h> | ||
| 15 | #include <linux/smp_lock.h> | ||
| 14 | #include <asm/current.h> | 16 | #include <asm/current.h> |
| 15 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
| 16 | 18 | ||
| @@ -80,3 +82,33 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
| 80 | return -ENOTTY; | 82 | return -ENOTTY; |
| 81 | } | 83 | } |
| 82 | } | 84 | } |
| 85 | |||
| 86 | #ifdef CONFIG_COMPAT | ||
| 87 | long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 88 | { | ||
| 89 | struct inode *inode = file->f_dentry->d_inode; | ||
| 90 | int ret; | ||
| 91 | |||
| 92 | /* These are just misnamed, they actually get/put from/to user an int */ | ||
| 93 | switch (cmd) { | ||
| 94 | case EXT2_IOC32_GETFLAGS: | ||
| 95 | cmd = EXT2_IOC_GETFLAGS; | ||
| 96 | break; | ||
| 97 | case EXT2_IOC32_SETFLAGS: | ||
| 98 | cmd = EXT2_IOC_SETFLAGS; | ||
| 99 | break; | ||
| 100 | case EXT2_IOC32_GETVERSION: | ||
| 101 | cmd = EXT2_IOC_GETVERSION; | ||
| 102 | break; | ||
| 103 | case EXT2_IOC32_SETVERSION: | ||
| 104 | cmd = EXT2_IOC_SETVERSION; | ||
| 105 | break; | ||
| 106 | default: | ||
| 107 | return -ENOIOCTLCMD; | ||
| 108 | } | ||
| 109 | lock_kernel(); | ||
| 110 | ret = ext2_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); | ||
| 111 | unlock_kernel(); | ||
| 112 | return ret; | ||
| 113 | } | ||
| 114 | #endif | ||
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 429acbb4e064..d0b54f30b914 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
| @@ -44,6 +44,9 @@ const struct file_operations ext3_dir_operations = { | |||
| 44 | .read = generic_read_dir, | 44 | .read = generic_read_dir, |
| 45 | .readdir = ext3_readdir, /* we take BKL. needed?*/ | 45 | .readdir = ext3_readdir, /* we take BKL. needed?*/ |
| 46 | .ioctl = ext3_ioctl, /* BKL held */ | 46 | .ioctl = ext3_ioctl, /* BKL held */ |
| 47 | #ifdef CONFIG_COMPAT | ||
| 48 | .compat_ioctl = ext3_compat_ioctl, | ||
| 49 | #endif | ||
| 47 | .fsync = ext3_sync_file, /* BKL held */ | 50 | .fsync = ext3_sync_file, /* BKL held */ |
| 48 | #ifdef CONFIG_EXT3_INDEX | 51 | #ifdef CONFIG_EXT3_INDEX |
| 49 | .release = ext3_release_dir, | 52 | .release = ext3_release_dir, |
diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 994efd189f4e..74ff20f9d09b 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c | |||
| @@ -114,6 +114,9 @@ const struct file_operations ext3_file_operations = { | |||
| 114 | .readv = generic_file_readv, | 114 | .readv = generic_file_readv, |
| 115 | .writev = generic_file_writev, | 115 | .writev = generic_file_writev, |
| 116 | .ioctl = ext3_ioctl, | 116 | .ioctl = ext3_ioctl, |
| 117 | #ifdef CONFIG_COMPAT | ||
| 118 | .compat_ioctl = ext3_compat_ioctl, | ||
| 119 | #endif | ||
| 117 | .mmap = generic_file_mmap, | 120 | .mmap = generic_file_mmap, |
| 118 | .open = generic_file_open, | 121 | .open = generic_file_open, |
| 119 | .release = ext3_release_file, | 122 | .release = ext3_release_file, |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index dcf4f1dd108b..03ba5bcab186 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/writeback.h> | 36 | #include <linux/writeback.h> |
| 37 | #include <linux/mpage.h> | 37 | #include <linux/mpage.h> |
| 38 | #include <linux/uio.h> | 38 | #include <linux/uio.h> |
| 39 | #include <linux/bio.h> | ||
| 39 | #include "xattr.h" | 40 | #include "xattr.h" |
| 40 | #include "acl.h" | 41 | #include "acl.h" |
| 41 | 42 | ||
| @@ -1073,7 +1074,7 @@ struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode, | |||
| 1073 | return bh; | 1074 | return bh; |
| 1074 | if (buffer_uptodate(bh)) | 1075 | if (buffer_uptodate(bh)) |
| 1075 | return bh; | 1076 | return bh; |
| 1076 | ll_rw_block(READ, 1, &bh); | 1077 | ll_rw_block(READ_META, 1, &bh); |
| 1077 | wait_on_buffer(bh); | 1078 | wait_on_buffer(bh); |
| 1078 | if (buffer_uptodate(bh)) | 1079 | if (buffer_uptodate(bh)) |
| 1079 | return bh; | 1080 | return bh; |
| @@ -2540,7 +2541,7 @@ make_io: | |||
| 2540 | */ | 2541 | */ |
| 2541 | get_bh(bh); | 2542 | get_bh(bh); |
| 2542 | bh->b_end_io = end_buffer_read_sync; | 2543 | bh->b_end_io = end_buffer_read_sync; |
| 2543 | submit_bh(READ, bh); | 2544 | submit_bh(READ_META, bh); |
| 2544 | wait_on_buffer(bh); | 2545 | wait_on_buffer(bh); |
| 2545 | if (!buffer_uptodate(bh)) { | 2546 | if (!buffer_uptodate(bh)) { |
| 2546 | ext3_error(inode->i_sb, "ext3_get_inode_loc", | 2547 | ext3_error(inode->i_sb, "ext3_get_inode_loc", |
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 3a6b012d120c..12daa6869572 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c | |||
| @@ -13,9 +13,10 @@ | |||
| 13 | #include <linux/ext3_fs.h> | 13 | #include <linux/ext3_fs.h> |
| 14 | #include <linux/ext3_jbd.h> | 14 | #include <linux/ext3_jbd.h> |
| 15 | #include <linux/time.h> | 15 | #include <linux/time.h> |
| 16 | #include <linux/compat.h> | ||
| 17 | #include <linux/smp_lock.h> | ||
| 16 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
| 17 | 19 | ||
| 18 | |||
| 19 | int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | 20 | int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, |
| 20 | unsigned long arg) | 21 | unsigned long arg) |
| 21 | { | 22 | { |
| @@ -252,3 +253,55 @@ flags_err: | |||
| 252 | return -ENOTTY; | 253 | return -ENOTTY; |
| 253 | } | 254 | } |
| 254 | } | 255 | } |
| 256 | |||
| 257 | #ifdef CONFIG_COMPAT | ||
| 258 | long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 259 | { | ||
| 260 | struct inode *inode = file->f_dentry->d_inode; | ||
| 261 | int ret; | ||
| 262 | |||
| 263 | /* These are just misnamed, they actually get/put from/to user an int */ | ||
| 264 | switch (cmd) { | ||
| 265 | case EXT3_IOC32_GETFLAGS: | ||
| 266 | cmd = EXT3_IOC_GETFLAGS; | ||
| 267 | break; | ||
| 268 | case EXT3_IOC32_SETFLAGS: | ||
| 269 | cmd = EXT3_IOC_SETFLAGS; | ||
| 270 | break; | ||
| 271 | case EXT3_IOC32_GETVERSION: | ||
| 272 | cmd = EXT3_IOC_GETVERSION; | ||
| 273 | break; | ||
| 274 | case EXT3_IOC32_SETVERSION: | ||
| 275 | cmd = EXT3_IOC_SETVERSION; | ||
| 276 | break; | ||
| 277 | case EXT3_IOC32_GROUP_EXTEND: | ||
| 278 | cmd = EXT3_IOC_GROUP_EXTEND; | ||
| 279 | break; | ||
| 280 | case EXT3_IOC32_GETVERSION_OLD: | ||
| 281 | cmd = EXT3_IOC_GETVERSION_OLD; | ||
| 282 | break; | ||
| 283 | case EXT3_IOC32_SETVERSION_OLD: | ||
| 284 | cmd = EXT3_IOC_SETVERSION_OLD; | ||
| 285 | break; | ||
| 286 | #ifdef CONFIG_JBD_DEBUG | ||
| 287 | case EXT3_IOC32_WAIT_FOR_READONLY: | ||
| 288 | cmd = EXT3_IOC_WAIT_FOR_READONLY; | ||
| 289 | break; | ||
| 290 | #endif | ||
| 291 | case EXT3_IOC32_GETRSVSZ: | ||
| 292 | cmd = EXT3_IOC_GETRSVSZ; | ||
| 293 | break; | ||
| 294 | case EXT3_IOC32_SETRSVSZ: | ||
| 295 | cmd = EXT3_IOC_SETRSVSZ; | ||
| 296 | break; | ||
| 297 | case EXT3_IOC_GROUP_ADD: | ||
| 298 | break; | ||
| 299 | default: | ||
| 300 | return -ENOIOCTLCMD; | ||
| 301 | } | ||
| 302 | lock_kernel(); | ||
| 303 | ret = ext3_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); | ||
| 304 | unlock_kernel(); | ||
| 305 | return ret; | ||
| 306 | } | ||
| 307 | #endif | ||
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 85d132c37ee0..235e77b52ea5 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/string.h> | 35 | #include <linux/string.h> |
| 36 | #include <linux/quotaops.h> | 36 | #include <linux/quotaops.h> |
| 37 | #include <linux/buffer_head.h> | 37 | #include <linux/buffer_head.h> |
| 38 | #include <linux/bio.h> | ||
| 38 | #include <linux/smp_lock.h> | 39 | #include <linux/smp_lock.h> |
| 39 | 40 | ||
| 40 | #include "namei.h" | 41 | #include "namei.h" |
| @@ -870,7 +871,7 @@ restart: | |||
| 870 | bh = ext3_getblk(NULL, dir, b++, 0, &err); | 871 | bh = ext3_getblk(NULL, dir, b++, 0, &err); |
| 871 | bh_use[ra_max] = bh; | 872 | bh_use[ra_max] = bh; |
| 872 | if (bh) | 873 | if (bh) |
| 873 | ll_rw_block(READ, 1, &bh); | 874 | ll_rw_block(READ_META, 1, &bh); |
| 874 | } | 875 | } |
| 875 | } | 876 | } |
| 876 | if ((bh = bh_use[ra_ptr++]) == NULL) | 877 | if ((bh = bh_use[ra_ptr++]) == NULL) |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 698b85bb1dd4..3e50a4166283 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/dirent.h> | 20 | #include <linux/dirent.h> |
| 21 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
| 22 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
| 23 | #include <linux/compat.h> | ||
| 23 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
| 24 | 25 | ||
| 25 | static inline loff_t fat_make_i_pos(struct super_block *sb, | 26 | static inline loff_t fat_make_i_pos(struct super_block *sb, |
| @@ -741,10 +742,65 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, | |||
| 741 | return ret; | 742 | return ret; |
| 742 | } | 743 | } |
| 743 | 744 | ||
| 745 | #ifdef CONFIG_COMPAT | ||
| 746 | #define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2]) | ||
| 747 | #define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2]) | ||
| 748 | |||
| 749 | static long fat_compat_put_dirent32(struct dirent *d, | ||
| 750 | struct compat_dirent __user *d32) | ||
| 751 | { | ||
| 752 | if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent))) | ||
| 753 | return -EFAULT; | ||
| 754 | |||
| 755 | __put_user(d->d_ino, &d32->d_ino); | ||
| 756 | __put_user(d->d_off, &d32->d_off); | ||
| 757 | __put_user(d->d_reclen, &d32->d_reclen); | ||
| 758 | if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen)) | ||
| 759 | return -EFAULT; | ||
| 760 | |||
| 761 | return 0; | ||
| 762 | } | ||
| 763 | |||
| 764 | static long fat_compat_dir_ioctl(struct file *file, unsigned cmd, | ||
| 765 | unsigned long arg) | ||
| 766 | { | ||
| 767 | struct compat_dirent __user *p = compat_ptr(arg); | ||
| 768 | int ret; | ||
| 769 | mm_segment_t oldfs = get_fs(); | ||
| 770 | struct dirent d[2]; | ||
| 771 | |||
| 772 | switch (cmd) { | ||
| 773 | case VFAT_IOCTL_READDIR_BOTH32: | ||
| 774 | cmd = VFAT_IOCTL_READDIR_BOTH; | ||
| 775 | break; | ||
| 776 | case VFAT_IOCTL_READDIR_SHORT32: | ||
| 777 | cmd = VFAT_IOCTL_READDIR_SHORT; | ||
| 778 | break; | ||
| 779 | default: | ||
| 780 | return -ENOIOCTLCMD; | ||
| 781 | } | ||
| 782 | |||
| 783 | set_fs(KERNEL_DS); | ||
| 784 | lock_kernel(); | ||
| 785 | ret = fat_dir_ioctl(file->f_dentry->d_inode, file, | ||
| 786 | cmd, (unsigned long) &d); | ||
| 787 | unlock_kernel(); | ||
| 788 | set_fs(oldfs); | ||
| 789 | if (ret >= 0) { | ||
| 790 | ret |= fat_compat_put_dirent32(&d[0], p); | ||
| 791 | ret |= fat_compat_put_dirent32(&d[1], p + 1); | ||
| 792 | } | ||
| 793 | return ret; | ||
| 794 | } | ||
| 795 | #endif /* CONFIG_COMPAT */ | ||
| 796 | |||
| 744 | const struct file_operations fat_dir_operations = { | 797 | const struct file_operations fat_dir_operations = { |
| 745 | .read = generic_read_dir, | 798 | .read = generic_read_dir, |
| 746 | .readdir = fat_readdir, | 799 | .readdir = fat_readdir, |
| 747 | .ioctl = fat_dir_ioctl, | 800 | .ioctl = fat_dir_ioctl, |
| 801 | #ifdef CONFIG_COMPAT | ||
| 802 | .compat_ioctl = fat_compat_dir_ioctl, | ||
| 803 | #endif | ||
| 748 | .fsync = file_fsync, | 804 | .fsync = file_fsync, |
| 749 | }; | 805 | }; |
| 750 | 806 | ||
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 892643dc9af1..c403b66ec83c 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -22,8 +22,7 @@ | |||
| 22 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
| 23 | #include <linux/backing-dev.h> | 23 | #include <linux/backing-dev.h> |
| 24 | #include <linux/buffer_head.h> | 24 | #include <linux/buffer_head.h> |
| 25 | 25 | #include "internal.h" | |
| 26 | extern struct super_block *blockdev_superblock; | ||
| 27 | 26 | ||
| 28 | /** | 27 | /** |
| 29 | * __mark_inode_dirty - internal function | 28 | * __mark_inode_dirty - internal function |
| @@ -320,7 +319,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc) | |||
| 320 | 319 | ||
| 321 | if (!bdi_cap_writeback_dirty(bdi)) { | 320 | if (!bdi_cap_writeback_dirty(bdi)) { |
| 322 | list_move(&inode->i_list, &sb->s_dirty); | 321 | list_move(&inode->i_list, &sb->s_dirty); |
| 323 | if (sb == blockdev_superblock) { | 322 | if (sb_is_blkdev_sb(sb)) { |
| 324 | /* | 323 | /* |
| 325 | * Dirty memory-backed blockdev: the ramdisk | 324 | * Dirty memory-backed blockdev: the ramdisk |
| 326 | * driver does this. Skip just this inode | 325 | * driver does this. Skip just this inode |
| @@ -337,14 +336,14 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc) | |||
| 337 | 336 | ||
| 338 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | 337 | if (wbc->nonblocking && bdi_write_congested(bdi)) { |
| 339 | wbc->encountered_congestion = 1; | 338 | wbc->encountered_congestion = 1; |
| 340 | if (sb != blockdev_superblock) | 339 | if (!sb_is_blkdev_sb(sb)) |
| 341 | break; /* Skip a congested fs */ | 340 | break; /* Skip a congested fs */ |
| 342 | list_move(&inode->i_list, &sb->s_dirty); | 341 | list_move(&inode->i_list, &sb->s_dirty); |
| 343 | continue; /* Skip a congested blockdev */ | 342 | continue; /* Skip a congested blockdev */ |
| 344 | } | 343 | } |
| 345 | 344 | ||
| 346 | if (wbc->bdi && bdi != wbc->bdi) { | 345 | if (wbc->bdi && bdi != wbc->bdi) { |
| 347 | if (sb != blockdev_superblock) | 346 | if (!sb_is_blkdev_sb(sb)) |
| 348 | break; /* fs has the wrong queue */ | 347 | break; /* fs has the wrong queue */ |
| 349 | list_move(&inode->i_list, &sb->s_dirty); | 348 | list_move(&inode->i_list, &sb->s_dirty); |
| 350 | continue; /* blockdev has wrong queue */ | 349 | continue; /* blockdev has wrong queue */ |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 8a1ca5ef7ada..3915635b4470 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
| @@ -246,12 +246,8 @@ struct hfsplus_readdir_data { | |||
| 246 | 246 | ||
| 247 | /* ext2 ioctls (EXT2_IOC_GETFLAGS and EXT2_IOC_SETFLAGS) to support | 247 | /* ext2 ioctls (EXT2_IOC_GETFLAGS and EXT2_IOC_SETFLAGS) to support |
| 248 | * chattr/lsattr */ | 248 | * chattr/lsattr */ |
| 249 | #define HFSPLUS_IOC_EXT2_GETFLAGS _IOR('f', 1, long) | 249 | #define HFSPLUS_IOC_EXT2_GETFLAGS FS_IOC_GETFLAGS |
| 250 | #define HFSPLUS_IOC_EXT2_SETFLAGS _IOW('f', 2, long) | 250 | #define HFSPLUS_IOC_EXT2_SETFLAGS FS_IOC_SETFLAGS |
| 251 | |||
| 252 | #define EXT2_FLAG_IMMUTABLE 0x00000010 /* Immutable file */ | ||
| 253 | #define EXT2_FLAG_APPEND 0x00000020 /* writes to file may only append */ | ||
| 254 | #define EXT2_FLAG_NODUMP 0x00000040 /* do not dump file */ | ||
| 255 | 251 | ||
| 256 | 252 | ||
| 257 | /* | 253 | /* |
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index 13cf848ac833..79fd10402ea3 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c | |||
| @@ -28,11 +28,11 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
| 28 | case HFSPLUS_IOC_EXT2_GETFLAGS: | 28 | case HFSPLUS_IOC_EXT2_GETFLAGS: |
| 29 | flags = 0; | 29 | flags = 0; |
| 30 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE) | 30 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE) |
| 31 | flags |= EXT2_FLAG_IMMUTABLE; /* EXT2_IMMUTABLE_FL */ | 31 | flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */ |
| 32 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND) | 32 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND) |
| 33 | flags |= EXT2_FLAG_APPEND; /* EXT2_APPEND_FL */ | 33 | flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */ |
| 34 | if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP) | 34 | if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP) |
| 35 | flags |= EXT2_FLAG_NODUMP; /* EXT2_NODUMP_FL */ | 35 | flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */ |
| 36 | return put_user(flags, (int __user *)arg); | 36 | return put_user(flags, (int __user *)arg); |
| 37 | case HFSPLUS_IOC_EXT2_SETFLAGS: { | 37 | case HFSPLUS_IOC_EXT2_SETFLAGS: { |
| 38 | if (IS_RDONLY(inode)) | 38 | if (IS_RDONLY(inode)) |
| @@ -44,32 +44,31 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
| 44 | if (get_user(flags, (int __user *)arg)) | 44 | if (get_user(flags, (int __user *)arg)) |
| 45 | return -EFAULT; | 45 | return -EFAULT; |
| 46 | 46 | ||
| 47 | if (flags & (EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND) || | 47 | if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) || |
| 48 | HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { | 48 | HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { |
| 49 | if (!capable(CAP_LINUX_IMMUTABLE)) | 49 | if (!capable(CAP_LINUX_IMMUTABLE)) |
| 50 | return -EPERM; | 50 | return -EPERM; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | /* don't silently ignore unsupported ext2 flags */ | 53 | /* don't silently ignore unsupported ext2 flags */ |
| 54 | if (flags & ~(EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND| | 54 | if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) |
| 55 | EXT2_FLAG_NODUMP)) | ||
| 56 | return -EOPNOTSUPP; | 55 | return -EOPNOTSUPP; |
| 57 | 56 | ||
| 58 | if (flags & EXT2_FLAG_IMMUTABLE) { /* EXT2_IMMUTABLE_FL */ | 57 | if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */ |
| 59 | inode->i_flags |= S_IMMUTABLE; | 58 | inode->i_flags |= S_IMMUTABLE; |
| 60 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; | 59 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; |
| 61 | } else { | 60 | } else { |
| 62 | inode->i_flags &= ~S_IMMUTABLE; | 61 | inode->i_flags &= ~S_IMMUTABLE; |
| 63 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | 62 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE; |
| 64 | } | 63 | } |
| 65 | if (flags & EXT2_FLAG_APPEND) { /* EXT2_APPEND_FL */ | 64 | if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */ |
| 66 | inode->i_flags |= S_APPEND; | 65 | inode->i_flags |= S_APPEND; |
| 67 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND; | 66 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND; |
| 68 | } else { | 67 | } else { |
| 69 | inode->i_flags &= ~S_APPEND; | 68 | inode->i_flags &= ~S_APPEND; |
| 70 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND; | 69 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND; |
| 71 | } | 70 | } |
| 72 | if (flags & EXT2_FLAG_NODUMP) /* EXT2_NODUMP_FL */ | 71 | if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */ |
| 73 | HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP; | 72 | HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP; |
| 74 | else | 73 | else |
| 75 | HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP; | 74 | HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP; |
diff --git a/fs/inode.c b/fs/inode.c index abf77471e6c4..ada7643104e1 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -362,27 +362,6 @@ int invalidate_inodes(struct super_block * sb) | |||
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | EXPORT_SYMBOL(invalidate_inodes); | 364 | EXPORT_SYMBOL(invalidate_inodes); |
| 365 | |||
| 366 | int __invalidate_device(struct block_device *bdev) | ||
| 367 | { | ||
| 368 | struct super_block *sb = get_super(bdev); | ||
| 369 | int res = 0; | ||
| 370 | |||
| 371 | if (sb) { | ||
| 372 | /* | ||
| 373 | * no need to lock the super, get_super holds the | ||
| 374 | * read mutex so the filesystem cannot go away | ||
| 375 | * under us (->put_super runs with the write lock | ||
| 376 | * hold). | ||
| 377 | */ | ||
| 378 | shrink_dcache_sb(sb); | ||
| 379 | res = invalidate_inodes(sb); | ||
| 380 | drop_super(sb); | ||
| 381 | } | ||
| 382 | invalidate_bdev(bdev, 0); | ||
| 383 | return res; | ||
| 384 | } | ||
| 385 | EXPORT_SYMBOL(__invalidate_device); | ||
| 386 | 365 | ||
| 387 | static int can_unuse(struct inode *inode) | 366 | static int can_unuse(struct inode *inode) |
| 388 | { | 367 | { |
diff --git a/fs/internal.h b/fs/internal.h new file mode 100644 index 000000000000..ea00126c9a59 --- /dev/null +++ b/fs/internal.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* fs/ internal definitions | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/ioctl32.h> | ||
| 13 | |||
| 14 | struct super_block; | ||
| 15 | |||
| 16 | /* | ||
| 17 | * block_dev.c | ||
| 18 | */ | ||
| 19 | #ifdef CONFIG_BLOCK | ||
| 20 | extern struct super_block *blockdev_superblock; | ||
| 21 | extern void __init bdev_cache_init(void); | ||
| 22 | |||
| 23 | static inline int sb_is_blkdev_sb(struct super_block *sb) | ||
| 24 | { | ||
| 25 | return sb == blockdev_superblock; | ||
| 26 | } | ||
| 27 | |||
| 28 | #else | ||
| 29 | static inline void bdev_cache_init(void) | ||
| 30 | { | ||
| 31 | } | ||
| 32 | |||
| 33 | static inline int sb_is_blkdev_sb(struct super_block *sb) | ||
| 34 | { | ||
| 35 | return 0; | ||
| 36 | } | ||
| 37 | #endif | ||
| 38 | |||
| 39 | /* | ||
| 40 | * char_dev.c | ||
| 41 | */ | ||
| 42 | extern void __init chrdev_init(void); | ||
| 43 | |||
| 44 | /* | ||
| 45 | * compat_ioctl.c | ||
| 46 | */ | ||
| 47 | #ifdef CONFIG_COMPAT | ||
| 48 | extern struct ioctl_trans ioctl_start[]; | ||
| 49 | extern int ioctl_table_size; | ||
| 50 | #endif | ||
| 51 | |||
| 52 | /* | ||
| 53 | * namespace.c | ||
| 54 | */ | ||
| 55 | extern int copy_mount_options(const void __user *, unsigned long *); | ||
diff --git a/fs/ioprio.c b/fs/ioprio.c index 78b1deae3fa2..6dc6721d9e82 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * fs/ioprio.c | 2 | * fs/ioprio.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2004 Jens Axboe <axboe@suse.de> | 4 | * Copyright (C) 2004 Jens Axboe <axboe@kernel.dk> |
| 5 | * | 5 | * |
| 6 | * Helper functions for setting/querying io priorities of processes. The | 6 | * Helper functions for setting/querying io priorities of processes. The |
| 7 | * system calls closely mimmick getpriority/setpriority, see the man page for | 7 | * system calls closely mimmick getpriority/setpriority, see the man page for |
| @@ -47,8 +47,8 @@ static int set_task_ioprio(struct task_struct *task, int ioprio) | |||
| 47 | /* see wmb() in current_io_context() */ | 47 | /* see wmb() in current_io_context() */ |
| 48 | smp_read_barrier_depends(); | 48 | smp_read_barrier_depends(); |
| 49 | 49 | ||
| 50 | if (ioc && ioc->set_ioprio) | 50 | if (ioc) |
| 51 | ioc->set_ioprio(ioc, ioprio); | 51 | ioc->ioprio_changed = 1; |
| 52 | 52 | ||
| 53 | task_unlock(task); | 53 | task_unlock(task); |
| 54 | return 0; | 54 | return 0; |
| @@ -81,7 +81,12 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) | |||
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | ret = -ESRCH; | 83 | ret = -ESRCH; |
| 84 | read_lock_irq(&tasklist_lock); | 84 | /* |
| 85 | * We want IOPRIO_WHO_PGRP/IOPRIO_WHO_USER to be "atomic", | ||
| 86 | * so we can't use rcu_read_lock(). See re-copy of ->ioprio | ||
| 87 | * in copy_process(). | ||
| 88 | */ | ||
| 89 | read_lock(&tasklist_lock); | ||
| 85 | switch (which) { | 90 | switch (which) { |
| 86 | case IOPRIO_WHO_PROCESS: | 91 | case IOPRIO_WHO_PROCESS: |
| 87 | if (!who) | 92 | if (!who) |
| @@ -124,7 +129,7 @@ free_uid: | |||
| 124 | ret = -EINVAL; | 129 | ret = -EINVAL; |
| 125 | } | 130 | } |
| 126 | 131 | ||
| 127 | read_unlock_irq(&tasklist_lock); | 132 | read_unlock(&tasklist_lock); |
| 128 | return ret; | 133 | return ret; |
| 129 | } | 134 | } |
| 130 | 135 | ||
| @@ -170,7 +175,7 @@ asmlinkage long sys_ioprio_get(int which, int who) | |||
| 170 | int ret = -ESRCH; | 175 | int ret = -ESRCH; |
| 171 | int tmpio; | 176 | int tmpio; |
| 172 | 177 | ||
| 173 | read_lock_irq(&tasklist_lock); | 178 | read_lock(&tasklist_lock); |
| 174 | switch (which) { | 179 | switch (which) { |
| 175 | case IOPRIO_WHO_PROCESS: | 180 | case IOPRIO_WHO_PROCESS: |
| 176 | if (!who) | 181 | if (!who) |
| @@ -221,7 +226,7 @@ asmlinkage long sys_ioprio_get(int which, int who) | |||
| 221 | ret = -EINVAL; | 226 | ret = -EINVAL; |
| 222 | } | 227 | } |
| 223 | 228 | ||
| 224 | read_unlock_irq(&tasklist_lock); | 229 | read_unlock(&tasklist_lock); |
| 225 | return ret; | 230 | return ret; |
| 226 | } | 231 | } |
| 227 | 232 | ||
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index 67b3774820eb..37db52488262 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
| 9 | #include <linux/ext2_fs.h> | ||
| 10 | #include <linux/ctype.h> | 9 | #include <linux/ctype.h> |
| 11 | #include <linux/capability.h> | 10 | #include <linux/capability.h> |
| 12 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| @@ -22,13 +21,13 @@ static struct { | |||
| 22 | long jfs_flag; | 21 | long jfs_flag; |
| 23 | long ext2_flag; | 22 | long ext2_flag; |
| 24 | } jfs_map[] = { | 23 | } jfs_map[] = { |
| 25 | {JFS_NOATIME_FL, EXT2_NOATIME_FL}, | 24 | {JFS_NOATIME_FL, FS_NOATIME_FL}, |
| 26 | {JFS_DIRSYNC_FL, EXT2_DIRSYNC_FL}, | 25 | {JFS_DIRSYNC_FL, FS_DIRSYNC_FL}, |
| 27 | {JFS_SYNC_FL, EXT2_SYNC_FL}, | 26 | {JFS_SYNC_FL, FS_SYNC_FL}, |
| 28 | {JFS_SECRM_FL, EXT2_SECRM_FL}, | 27 | {JFS_SECRM_FL, FS_SECRM_FL}, |
| 29 | {JFS_UNRM_FL, EXT2_UNRM_FL}, | 28 | {JFS_UNRM_FL, FS_UNRM_FL}, |
| 30 | {JFS_APPEND_FL, EXT2_APPEND_FL}, | 29 | {JFS_APPEND_FL, FS_APPEND_FL}, |
| 31 | {JFS_IMMUTABLE_FL, EXT2_IMMUTABLE_FL}, | 30 | {JFS_IMMUTABLE_FL, FS_IMMUTABLE_FL}, |
| 32 | {0, 0}, | 31 | {0, 0}, |
| 33 | }; | 32 | }; |
| 34 | 33 | ||
diff --git a/fs/mpage.c b/fs/mpage.c index 1e4598247d0b..692a3e578fc8 100644 --- a/fs/mpage.c +++ b/fs/mpage.c | |||
| @@ -693,6 +693,8 @@ out: | |||
| 693 | * the call was made get new I/O started against them. If wbc->sync_mode is | 693 | * the call was made get new I/O started against them. If wbc->sync_mode is |
| 694 | * WB_SYNC_ALL then we were called for data integrity and we must wait for | 694 | * WB_SYNC_ALL then we were called for data integrity and we must wait for |
| 695 | * existing IO to complete. | 695 | * existing IO to complete. |
| 696 | * | ||
| 697 | * If you fix this you should check generic_writepages() also! | ||
| 696 | */ | 698 | */ |
| 697 | int | 699 | int |
| 698 | mpage_writepages(struct address_space *mapping, | 700 | mpage_writepages(struct address_space *mapping, |
diff --git a/fs/namespace.c b/fs/namespace.c index 6ede3a539ed8..66d921e14fee 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -24,12 +24,11 @@ | |||
| 24 | #include <linux/namei.h> | 24 | #include <linux/namei.h> |
| 25 | #include <linux/security.h> | 25 | #include <linux/security.h> |
| 26 | #include <linux/mount.h> | 26 | #include <linux/mount.h> |
| 27 | #include <linux/ramfs.h> | ||
| 27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
| 28 | #include <asm/unistd.h> | 29 | #include <asm/unistd.h> |
| 29 | #include "pnode.h" | 30 | #include "pnode.h" |
| 30 | 31 | ||
| 31 | extern int __init init_rootfs(void); | ||
| 32 | |||
| 33 | /* spinlock for vfsmount related operations, inplace of dcache_lock */ | 32 | /* spinlock for vfsmount related operations, inplace of dcache_lock */ |
| 34 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); | 33 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); |
| 35 | 34 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index b674462793d3..f6675d2c386c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -51,7 +51,6 @@ | |||
| 51 | #include <linux/mm.h> | 51 | #include <linux/mm.h> |
| 52 | #include <linux/pagemap.h> | 52 | #include <linux/pagemap.h> |
| 53 | #include <linux/file.h> | 53 | #include <linux/file.h> |
| 54 | #include <linux/mpage.h> | ||
| 55 | #include <linux/writeback.h> | 54 | #include <linux/writeback.h> |
| 56 | 55 | ||
| 57 | #include <linux/sunrpc/clnt.h> | 56 | #include <linux/sunrpc/clnt.h> |
diff --git a/fs/no-block.c b/fs/no-block.c new file mode 100644 index 000000000000..d269a93d3467 --- /dev/null +++ b/fs/no-block.c | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* no-block.c: implementation of routines required for non-BLOCK configuration | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/fs.h> | ||
| 14 | |||
| 15 | static int no_blkdev_open(struct inode * inode, struct file * filp) | ||
| 16 | { | ||
| 17 | return -ENODEV; | ||
| 18 | } | ||
| 19 | |||
| 20 | const struct file_operations def_blk_fops = { | ||
| 21 | .open = no_blkdev_open, | ||
| 22 | }; | ||
diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile index d713ce6b3e12..67e665fdb7fc 100644 --- a/fs/partitions/Makefile +++ b/fs/partitions/Makefile | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y := check.o | 5 | obj-$(CONFIG_BLOCK) := check.o |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_ACORN_PARTITION) += acorn.o | 7 | obj-$(CONFIG_ACORN_PARTITION) += acorn.o |
| 8 | obj-$(CONFIG_AMIGA_PARTITION) += amiga.o | 8 | obj-$(CONFIG_AMIGA_PARTITION) += amiga.o |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 5bbd60896050..66bc425f2f3d 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
| @@ -277,12 +277,15 @@ static int devinfo_show(struct seq_file *f, void *v) | |||
| 277 | if (i == 0) | 277 | if (i == 0) |
| 278 | seq_printf(f, "Character devices:\n"); | 278 | seq_printf(f, "Character devices:\n"); |
| 279 | chrdev_show(f, i); | 279 | chrdev_show(f, i); |
| 280 | } else { | 280 | } |
| 281 | #ifdef CONFIG_BLOCK | ||
| 282 | else { | ||
| 281 | i -= CHRDEV_MAJOR_HASH_SIZE; | 283 | i -= CHRDEV_MAJOR_HASH_SIZE; |
| 282 | if (i == 0) | 284 | if (i == 0) |
| 283 | seq_printf(f, "\nBlock devices:\n"); | 285 | seq_printf(f, "\nBlock devices:\n"); |
| 284 | blkdev_show(f, i); | 286 | blkdev_show(f, i); |
| 285 | } | 287 | } |
| 288 | #endif | ||
| 286 | return 0; | 289 | return 0; |
| 287 | } | 290 | } |
| 288 | 291 | ||
| @@ -355,6 +358,7 @@ static int stram_read_proc(char *page, char **start, off_t off, | |||
| 355 | } | 358 | } |
| 356 | #endif | 359 | #endif |
| 357 | 360 | ||
| 361 | #ifdef CONFIG_BLOCK | ||
| 358 | extern struct seq_operations partitions_op; | 362 | extern struct seq_operations partitions_op; |
| 359 | static int partitions_open(struct inode *inode, struct file *file) | 363 | static int partitions_open(struct inode *inode, struct file *file) |
| 360 | { | 364 | { |
| @@ -378,6 +382,7 @@ static struct file_operations proc_diskstats_operations = { | |||
| 378 | .llseek = seq_lseek, | 382 | .llseek = seq_lseek, |
| 379 | .release = seq_release, | 383 | .release = seq_release, |
| 380 | }; | 384 | }; |
| 385 | #endif | ||
| 381 | 386 | ||
| 382 | #ifdef CONFIG_MODULES | 387 | #ifdef CONFIG_MODULES |
| 383 | extern struct seq_operations modules_op; | 388 | extern struct seq_operations modules_op; |
| @@ -695,7 +700,9 @@ void __init proc_misc_init(void) | |||
| 695 | entry->proc_fops = &proc_kmsg_operations; | 700 | entry->proc_fops = &proc_kmsg_operations; |
| 696 | create_seq_entry("devices", 0, &proc_devinfo_operations); | 701 | create_seq_entry("devices", 0, &proc_devinfo_operations); |
| 697 | create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); | 702 | create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); |
| 703 | #ifdef CONFIG_BLOCK | ||
| 698 | create_seq_entry("partitions", 0, &proc_partitions_operations); | 704 | create_seq_entry("partitions", 0, &proc_partitions_operations); |
| 705 | #endif | ||
| 699 | create_seq_entry("stat", 0, &proc_stat_operations); | 706 | create_seq_entry("stat", 0, &proc_stat_operations); |
| 700 | create_seq_entry("interrupts", 0, &proc_interrupts_operations); | 707 | create_seq_entry("interrupts", 0, &proc_interrupts_operations); |
| 701 | #ifdef CONFIG_SLAB | 708 | #ifdef CONFIG_SLAB |
| @@ -707,7 +714,9 @@ void __init proc_misc_init(void) | |||
| 707 | create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); | 714 | create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); |
| 708 | create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); | 715 | create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); |
| 709 | create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations); | 716 | create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations); |
| 717 | #ifdef CONFIG_BLOCK | ||
| 710 | create_seq_entry("diskstats", 0, &proc_diskstats_operations); | 718 | create_seq_entry("diskstats", 0, &proc_diskstats_operations); |
| 719 | #endif | ||
| 711 | #ifdef CONFIG_MODULES | 720 | #ifdef CONFIG_MODULES |
| 712 | create_seq_entry("modules", 0, &proc_modules_operations); | 721 | create_seq_entry("modules", 0, &proc_modules_operations); |
| 713 | #endif | 722 | #endif |
diff --git a/fs/quota.c b/fs/quota.c index d6a2be826e29..b9dae76a0b6e 100644 --- a/fs/quota.c +++ b/fs/quota.c | |||
| @@ -338,6 +338,34 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void | |||
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | /* | 340 | /* |
| 341 | * look up a superblock on which quota ops will be performed | ||
| 342 | * - use the name of a block device to find the superblock thereon | ||
| 343 | */ | ||
| 344 | static inline struct super_block *quotactl_block(const char __user *special) | ||
| 345 | { | ||
| 346 | #ifdef CONFIG_BLOCK | ||
| 347 | struct block_device *bdev; | ||
| 348 | struct super_block *sb; | ||
| 349 | char *tmp = getname(special); | ||
| 350 | |||
| 351 | if (IS_ERR(tmp)) | ||
| 352 | return ERR_PTR(PTR_ERR(tmp)); | ||
| 353 | bdev = lookup_bdev(tmp); | ||
| 354 | putname(tmp); | ||
| 355 | if (IS_ERR(bdev)) | ||
| 356 | return ERR_PTR(PTR_ERR(bdev)); | ||
| 357 | sb = get_super(bdev); | ||
| 358 | bdput(bdev); | ||
| 359 | if (!sb) | ||
| 360 | return ERR_PTR(-ENODEV); | ||
| 361 | |||
| 362 | return sb; | ||
| 363 | #else | ||
| 364 | return ERR_PTR(-ENODEV); | ||
| 365 | #endif | ||
| 366 | } | ||
| 367 | |||
| 368 | /* | ||
| 341 | * This is the system call interface. This communicates with | 369 | * This is the system call interface. This communicates with |
| 342 | * the user-level programs. Currently this only supports diskquota | 370 | * the user-level programs. Currently this only supports diskquota |
| 343 | * calls. Maybe we need to add the process quotas etc. in the future, | 371 | * calls. Maybe we need to add the process quotas etc. in the future, |
| @@ -347,25 +375,15 @@ asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t | |||
| 347 | { | 375 | { |
| 348 | uint cmds, type; | 376 | uint cmds, type; |
| 349 | struct super_block *sb = NULL; | 377 | struct super_block *sb = NULL; |
| 350 | struct block_device *bdev; | ||
| 351 | char *tmp; | ||
| 352 | int ret; | 378 | int ret; |
| 353 | 379 | ||
| 354 | cmds = cmd >> SUBCMDSHIFT; | 380 | cmds = cmd >> SUBCMDSHIFT; |
| 355 | type = cmd & SUBCMDMASK; | 381 | type = cmd & SUBCMDMASK; |
| 356 | 382 | ||
| 357 | if (cmds != Q_SYNC || special) { | 383 | if (cmds != Q_SYNC || special) { |
| 358 | tmp = getname(special); | 384 | sb = quotactl_block(special); |
| 359 | if (IS_ERR(tmp)) | 385 | if (IS_ERR(sb)) |
| 360 | return PTR_ERR(tmp); | 386 | return PTR_ERR(sb); |
| 361 | bdev = lookup_bdev(tmp); | ||
| 362 | putname(tmp); | ||
| 363 | if (IS_ERR(bdev)) | ||
| 364 | return PTR_ERR(bdev); | ||
| 365 | sb = get_super(bdev); | ||
| 366 | bdput(bdev); | ||
| 367 | if (!sb) | ||
| 368 | return -ENODEV; | ||
| 369 | } | 387 | } |
| 370 | 388 | ||
| 371 | ret = check_quotactl_valid(sb, type, cmds, id); | 389 | ret = check_quotactl_valid(sb, type, cmds, id); |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 9aabcc0ccd2d..657050ad7430 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
| @@ -22,6 +22,9 @@ const struct file_operations reiserfs_dir_operations = { | |||
| 22 | .readdir = reiserfs_readdir, | 22 | .readdir = reiserfs_readdir, |
| 23 | .fsync = reiserfs_dir_fsync, | 23 | .fsync = reiserfs_dir_fsync, |
| 24 | .ioctl = reiserfs_ioctl, | 24 | .ioctl = reiserfs_ioctl, |
| 25 | #ifdef CONFIG_COMPAT | ||
| 26 | .compat_ioctl = reiserfs_compat_ioctl, | ||
| 27 | #endif | ||
| 25 | }; | 28 | }; |
| 26 | 29 | ||
| 27 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, | 30 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 1cfbe857ba27..3e08f7161a3d 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README | 2 | * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README |
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | #include <linux/config.h> | ||
| 5 | #include <linux/time.h> | 6 | #include <linux/time.h> |
| 6 | #include <linux/reiserfs_fs.h> | 7 | #include <linux/reiserfs_fs.h> |
| 7 | #include <linux/reiserfs_acl.h> | 8 | #include <linux/reiserfs_acl.h> |
| @@ -1568,6 +1569,9 @@ const struct file_operations reiserfs_file_operations = { | |||
| 1568 | .read = generic_file_read, | 1569 | .read = generic_file_read, |
| 1569 | .write = reiserfs_file_write, | 1570 | .write = reiserfs_file_write, |
| 1570 | .ioctl = reiserfs_ioctl, | 1571 | .ioctl = reiserfs_ioctl, |
| 1572 | #ifdef CONFIG_COMPAT | ||
| 1573 | .compat_ioctl = reiserfs_compat_ioctl, | ||
| 1574 | #endif | ||
| 1571 | .mmap = generic_file_mmap, | 1575 | .mmap = generic_file_mmap, |
| 1572 | .release = reiserfs_file_release, | 1576 | .release = reiserfs_file_release, |
| 1573 | .fsync = reiserfs_sync_file, | 1577 | .fsync = reiserfs_sync_file, |
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index a986b5e1e288..9c57578cb831 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
| 10 | #include <linux/pagemap.h> | 10 | #include <linux/pagemap.h> |
| 11 | #include <linux/smp_lock.h> | 11 | #include <linux/smp_lock.h> |
| 12 | #include <linux/compat.h> | ||
| 12 | 13 | ||
| 13 | static int reiserfs_unpack(struct inode *inode, struct file *filp); | 14 | static int reiserfs_unpack(struct inode *inode, struct file *filp); |
| 14 | 15 | ||
| @@ -94,6 +95,40 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
| 94 | } | 95 | } |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 98 | #ifdef CONFIG_COMPAT | ||
| 99 | long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, | ||
| 100 | unsigned long arg) | ||
| 101 | { | ||
| 102 | struct inode *inode = file->f_dentry->d_inode; | ||
| 103 | int ret; | ||
| 104 | |||
| 105 | /* These are just misnamed, they actually get/put from/to user an int */ | ||
| 106 | switch (cmd) { | ||
| 107 | case REISERFS_IOC32_UNPACK: | ||
| 108 | cmd = REISERFS_IOC_UNPACK; | ||
| 109 | break; | ||
| 110 | case REISERFS_IOC32_GETFLAGS: | ||
| 111 | cmd = REISERFS_IOC_GETFLAGS; | ||
| 112 | break; | ||
| 113 | case REISERFS_IOC32_SETFLAGS: | ||
| 114 | cmd = REISERFS_IOC_SETFLAGS; | ||
| 115 | break; | ||
| 116 | case REISERFS_IOC32_GETVERSION: | ||
| 117 | cmd = REISERFS_IOC_GETVERSION; | ||
| 118 | break; | ||
| 119 | case REISERFS_IOC32_SETVERSION: | ||
| 120 | cmd = REISERFS_IOC_SETVERSION; | ||
| 121 | break; | ||
| 122 | default: | ||
| 123 | return -ENOIOCTLCMD; | ||
| 124 | } | ||
| 125 | lock_kernel(); | ||
| 126 | ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); | ||
| 127 | unlock_kernel(); | ||
| 128 | return ret; | ||
| 129 | } | ||
| 130 | #endif | ||
| 131 | |||
| 97 | /* | 132 | /* |
| 98 | ** reiserfs_unpack | 133 | ** reiserfs_unpack |
| 99 | ** Function try to convert tail from direct item into indirect. | 134 | ** Function try to convert tail from direct item into indirect. |
diff --git a/fs/splice.c b/fs/splice.c index 684bca3d3a10..13e92dd19fbb 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | * Jens to support splicing to files, network, direct splicing, etc and | 12 | * Jens to support splicing to files, network, direct splicing, etc and |
| 13 | * fixing lots of bugs. | 13 | * fixing lots of bugs. |
| 14 | * | 14 | * |
| 15 | * Copyright (C) 2005-2006 Jens Axboe <axboe@suse.de> | 15 | * Copyright (C) 2005-2006 Jens Axboe <axboe@kernel.dk> |
| 16 | * Copyright (C) 2005-2006 Linus Torvalds <torvalds@osdl.org> | 16 | * Copyright (C) 2005-2006 Linus Torvalds <torvalds@osdl.org> |
| 17 | * Copyright (C) 2006 Ingo Molnar <mingo@elte.hu> | 17 | * Copyright (C) 2006 Ingo Molnar <mingo@elte.hu> |
| 18 | * | 18 | * |
diff --git a/fs/super.c b/fs/super.c index 6987824d0dce..aec99ddbe53f 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -220,6 +220,37 @@ static int grab_super(struct super_block *s) __releases(sb_lock) | |||
| 220 | return 0; | 220 | return 0; |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | /* | ||
| 224 | * Write out and wait upon all dirty data associated with this | ||
| 225 | * superblock. Filesystem data as well as the underlying block | ||
| 226 | * device. Takes the superblock lock. Requires a second blkdev | ||
| 227 | * flush by the caller to complete the operation. | ||
| 228 | */ | ||
| 229 | void __fsync_super(struct super_block *sb) | ||
| 230 | { | ||
| 231 | sync_inodes_sb(sb, 0); | ||
| 232 | DQUOT_SYNC(sb); | ||
| 233 | lock_super(sb); | ||
| 234 | if (sb->s_dirt && sb->s_op->write_super) | ||
| 235 | sb->s_op->write_super(sb); | ||
| 236 | unlock_super(sb); | ||
| 237 | if (sb->s_op->sync_fs) | ||
| 238 | sb->s_op->sync_fs(sb, 1); | ||
| 239 | sync_blockdev(sb->s_bdev); | ||
| 240 | sync_inodes_sb(sb, 1); | ||
| 241 | } | ||
| 242 | |||
| 243 | /* | ||
| 244 | * Write out and wait upon all dirty data associated with this | ||
| 245 | * superblock. Filesystem data as well as the underlying block | ||
| 246 | * device. Takes the superblock lock. | ||
| 247 | */ | ||
| 248 | int fsync_super(struct super_block *sb) | ||
| 249 | { | ||
| 250 | __fsync_super(sb); | ||
| 251 | return sync_blockdev(sb->s_bdev); | ||
| 252 | } | ||
| 253 | |||
| 223 | /** | 254 | /** |
| 224 | * generic_shutdown_super - common helper for ->kill_sb() | 255 | * generic_shutdown_super - common helper for ->kill_sb() |
| 225 | * @sb: superblock to kill | 256 | * @sb: superblock to kill |
| @@ -540,8 +571,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
| 540 | { | 571 | { |
| 541 | int retval; | 572 | int retval; |
| 542 | 573 | ||
| 574 | #ifdef CONFIG_BLOCK | ||
| 543 | if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) | 575 | if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) |
| 544 | return -EACCES; | 576 | return -EACCES; |
| 577 | #endif | ||
| 545 | if (flags & MS_RDONLY) | 578 | if (flags & MS_RDONLY) |
| 546 | acct_auto_close(sb); | 579 | acct_auto_close(sb); |
| 547 | shrink_dcache_sb(sb); | 580 | shrink_dcache_sb(sb); |
| @@ -661,6 +694,7 @@ void kill_litter_super(struct super_block *sb) | |||
| 661 | 694 | ||
| 662 | EXPORT_SYMBOL(kill_litter_super); | 695 | EXPORT_SYMBOL(kill_litter_super); |
| 663 | 696 | ||
| 697 | #ifdef CONFIG_BLOCK | ||
| 664 | static int set_bdev_super(struct super_block *s, void *data) | 698 | static int set_bdev_super(struct super_block *s, void *data) |
| 665 | { | 699 | { |
| 666 | s->s_bdev = data; | 700 | s->s_bdev = data; |
| @@ -756,6 +790,7 @@ void kill_block_super(struct super_block *sb) | |||
| 756 | } | 790 | } |
| 757 | 791 | ||
| 758 | EXPORT_SYMBOL(kill_block_super); | 792 | EXPORT_SYMBOL(kill_block_super); |
| 793 | #endif | ||
| 759 | 794 | ||
| 760 | int get_sb_nodev(struct file_system_type *fs_type, | 795 | int get_sb_nodev(struct file_system_type *fs_type, |
| 761 | int flags, void *data, | 796 | int flags, void *data, |
| @@ -10,11 +10,124 @@ | |||
| 10 | #include <linux/syscalls.h> | 10 | #include <linux/syscalls.h> |
| 11 | #include <linux/linkage.h> | 11 | #include <linux/linkage.h> |
| 12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
| 13 | #include <linux/quotaops.h> | ||
| 14 | #include <linux/buffer_head.h> | ||
| 13 | 15 | ||
| 14 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ | 16 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ |
| 15 | SYNC_FILE_RANGE_WAIT_AFTER) | 17 | SYNC_FILE_RANGE_WAIT_AFTER) |
| 16 | 18 | ||
| 17 | /* | 19 | /* |
| 20 | * sync everything. Start out by waking pdflush, because that writes back | ||
| 21 | * all queues in parallel. | ||
| 22 | */ | ||
| 23 | static void do_sync(unsigned long wait) | ||
| 24 | { | ||
| 25 | wakeup_pdflush(0); | ||
| 26 | sync_inodes(0); /* All mappings, inodes and their blockdevs */ | ||
| 27 | DQUOT_SYNC(NULL); | ||
| 28 | sync_supers(); /* Write the superblocks */ | ||
| 29 | sync_filesystems(0); /* Start syncing the filesystems */ | ||
| 30 | sync_filesystems(wait); /* Waitingly sync the filesystems */ | ||
| 31 | sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */ | ||
| 32 | if (!wait) | ||
| 33 | printk("Emergency Sync complete\n"); | ||
| 34 | if (unlikely(laptop_mode)) | ||
| 35 | laptop_sync_completion(); | ||
| 36 | } | ||
| 37 | |||
| 38 | asmlinkage long sys_sync(void) | ||
| 39 | { | ||
| 40 | do_sync(1); | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | void emergency_sync(void) | ||
| 45 | { | ||
| 46 | pdflush_operation(do_sync, 0); | ||
| 47 | } | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Generic function to fsync a file. | ||
| 51 | * | ||
| 52 | * filp may be NULL if called via the msync of a vma. | ||
| 53 | */ | ||
| 54 | int file_fsync(struct file *filp, struct dentry *dentry, int datasync) | ||
| 55 | { | ||
| 56 | struct inode * inode = dentry->d_inode; | ||
| 57 | struct super_block * sb; | ||
| 58 | int ret, err; | ||
| 59 | |||
| 60 | /* sync the inode to buffers */ | ||
| 61 | ret = write_inode_now(inode, 0); | ||
| 62 | |||
| 63 | /* sync the superblock to buffers */ | ||
| 64 | sb = inode->i_sb; | ||
| 65 | lock_super(sb); | ||
| 66 | if (sb->s_op->write_super) | ||
| 67 | sb->s_op->write_super(sb); | ||
| 68 | unlock_super(sb); | ||
| 69 | |||
| 70 | /* .. finally sync the buffers to disk */ | ||
| 71 | err = sync_blockdev(sb->s_bdev); | ||
| 72 | if (!ret) | ||
| 73 | ret = err; | ||
| 74 | return ret; | ||
| 75 | } | ||
| 76 | |||
| 77 | long do_fsync(struct file *file, int datasync) | ||
| 78 | { | ||
| 79 | int ret; | ||
| 80 | int err; | ||
| 81 | struct address_space *mapping = file->f_mapping; | ||
| 82 | |||
| 83 | if (!file->f_op || !file->f_op->fsync) { | ||
| 84 | /* Why? We can still call filemap_fdatawrite */ | ||
| 85 | ret = -EINVAL; | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | |||
| 89 | ret = filemap_fdatawrite(mapping); | ||
| 90 | |||
| 91 | /* | ||
| 92 | * We need to protect against concurrent writers, which could cause | ||
| 93 | * livelocks in fsync_buffers_list(). | ||
| 94 | */ | ||
| 95 | mutex_lock(&mapping->host->i_mutex); | ||
| 96 | err = file->f_op->fsync(file, file->f_dentry, datasync); | ||
| 97 | if (!ret) | ||
| 98 | ret = err; | ||
| 99 | mutex_unlock(&mapping->host->i_mutex); | ||
| 100 | err = filemap_fdatawait(mapping); | ||
| 101 | if (!ret) | ||
| 102 | ret = err; | ||
| 103 | out: | ||
| 104 | return ret; | ||
| 105 | } | ||
| 106 | |||
| 107 | static long __do_fsync(unsigned int fd, int datasync) | ||
| 108 | { | ||
| 109 | struct file *file; | ||
| 110 | int ret = -EBADF; | ||
| 111 | |||
| 112 | file = fget(fd); | ||
| 113 | if (file) { | ||
| 114 | ret = do_fsync(file, datasync); | ||
| 115 | fput(file); | ||
| 116 | } | ||
| 117 | return ret; | ||
| 118 | } | ||
| 119 | |||
| 120 | asmlinkage long sys_fsync(unsigned int fd) | ||
| 121 | { | ||
| 122 | return __do_fsync(fd, 0); | ||
| 123 | } | ||
| 124 | |||
| 125 | asmlinkage long sys_fdatasync(unsigned int fd) | ||
| 126 | { | ||
| 127 | return __do_fsync(fd, 1); | ||
| 128 | } | ||
| 129 | |||
| 130 | /* | ||
| 18 | * sys_sync_file_range() permits finely controlled syncing over a segment of | 131 | * sys_sync_file_range() permits finely controlled syncing over a segment of |
| 19 | * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is | 132 | * a file in the range offset .. (offset+nbytes-1) inclusive. If nbytes is |
| 20 | * zero then sys_sync_file_range() will operate from offset out to EOF. | 133 | * zero then sys_sync_file_range() will operate from offset out to EOF. |
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig index 26b364c9d62c..35115bca036e 100644 --- a/fs/xfs/Kconfig +++ b/fs/xfs/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | config XFS_FS | 1 | config XFS_FS |
| 2 | tristate "XFS filesystem support" | 2 | tristate "XFS filesystem support" |
| 3 | depends on BLOCK | ||
| 3 | help | 4 | help |
| 4 | XFS is a high performance journaling filesystem which originated | 5 | XFS is a high performance journaling filesystem which originated |
| 5 | on the SGI IRIX platform. It is completely multi-threaded, can | 6 | on the SGI IRIX platform. It is completely multi-threaded, can |
diff --git a/include/linux/bio.h b/include/linux/bio.h index 76bdaeab6f62..711c321a7011 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
| @@ -148,6 +148,7 @@ struct bio { | |||
| 148 | #define BIO_RW_BARRIER 2 | 148 | #define BIO_RW_BARRIER 2 |
| 149 | #define BIO_RW_FAILFAST 3 | 149 | #define BIO_RW_FAILFAST 3 |
| 150 | #define BIO_RW_SYNC 4 | 150 | #define BIO_RW_SYNC 4 |
| 151 | #define BIO_RW_META 5 | ||
| 151 | 152 | ||
| 152 | /* | 153 | /* |
| 153 | * upper 16 bits of bi_rw define the io priority of this bio | 154 | * upper 16 bits of bi_rw define the io priority of this bio |
| @@ -178,6 +179,7 @@ struct bio { | |||
| 178 | #define bio_sync(bio) ((bio)->bi_rw & (1 << BIO_RW_SYNC)) | 179 | #define bio_sync(bio) ((bio)->bi_rw & (1 << BIO_RW_SYNC)) |
| 179 | #define bio_failfast(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST)) | 180 | #define bio_failfast(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST)) |
| 180 | #define bio_rw_ahead(bio) ((bio)->bi_rw & (1 << BIO_RW_AHEAD)) | 181 | #define bio_rw_ahead(bio) ((bio)->bi_rw & (1 << BIO_RW_AHEAD)) |
| 182 | #define bio_rw_meta(bio) ((bio)->bi_rw & (1 << BIO_RW_META)) | ||
| 181 | 183 | ||
| 182 | /* | 184 | /* |
| 183 | * will die | 185 | * will die |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index cfde8b3ee919..1d79b8d4ca6d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef _LINUX_BLKDEV_H | 1 | #ifndef _LINUX_BLKDEV_H |
| 2 | #define _LINUX_BLKDEV_H | 2 | #define _LINUX_BLKDEV_H |
| 3 | 3 | ||
| 4 | #include <linux/sched.h> | ||
| 4 | #include <linux/major.h> | 5 | #include <linux/major.h> |
| 5 | #include <linux/genhd.h> | 6 | #include <linux/genhd.h> |
| 6 | #include <linux/list.h> | 7 | #include <linux/list.h> |
| @@ -16,6 +17,22 @@ | |||
| 16 | 17 | ||
| 17 | #include <asm/scatterlist.h> | 18 | #include <asm/scatterlist.h> |
| 18 | 19 | ||
| 20 | #ifdef CONFIG_LBD | ||
| 21 | # include <asm/div64.h> | ||
| 22 | # define sector_div(a, b) do_div(a, b) | ||
| 23 | #else | ||
| 24 | # define sector_div(n, b)( \ | ||
| 25 | { \ | ||
| 26 | int _res; \ | ||
| 27 | _res = (n) % (b); \ | ||
| 28 | (n) /= (b); \ | ||
| 29 | _res; \ | ||
| 30 | } \ | ||
| 31 | ) | ||
| 32 | #endif | ||
| 33 | |||
| 34 | #ifdef CONFIG_BLOCK | ||
| 35 | |||
| 19 | struct scsi_ioctl_command; | 36 | struct scsi_ioctl_command; |
| 20 | 37 | ||
| 21 | struct request_queue; | 38 | struct request_queue; |
| @@ -90,7 +107,7 @@ struct io_context { | |||
| 90 | atomic_t refcount; | 107 | atomic_t refcount; |
| 91 | struct task_struct *task; | 108 | struct task_struct *task; |
| 92 | 109 | ||
| 93 | int (*set_ioprio)(struct io_context *, unsigned int); | 110 | unsigned int ioprio_changed; |
| 94 | 111 | ||
| 95 | /* | 112 | /* |
| 96 | * For request batching | 113 | * For request batching |
| @@ -104,8 +121,7 @@ struct io_context { | |||
| 104 | 121 | ||
| 105 | void put_io_context(struct io_context *ioc); | 122 | void put_io_context(struct io_context *ioc); |
| 106 | void exit_io_context(void); | 123 | void exit_io_context(void); |
| 107 | struct io_context *current_io_context(gfp_t gfp_flags); | 124 | struct io_context *get_io_context(gfp_t gfp_flags, int node); |
| 108 | struct io_context *get_io_context(gfp_t gfp_flags); | ||
| 109 | void copy_io_context(struct io_context **pdst, struct io_context **psrc); | 125 | void copy_io_context(struct io_context **pdst, struct io_context **psrc); |
| 110 | void swap_io_context(struct io_context **ioc1, struct io_context **ioc2); | 126 | void swap_io_context(struct io_context **ioc1, struct io_context **ioc2); |
| 111 | 127 | ||
| @@ -120,6 +136,90 @@ struct request_list { | |||
| 120 | wait_queue_head_t wait[2]; | 136 | wait_queue_head_t wait[2]; |
| 121 | }; | 137 | }; |
| 122 | 138 | ||
| 139 | /* | ||
| 140 | * request command types | ||
| 141 | */ | ||
| 142 | enum rq_cmd_type_bits { | ||
| 143 | REQ_TYPE_FS = 1, /* fs request */ | ||
| 144 | REQ_TYPE_BLOCK_PC, /* scsi command */ | ||
| 145 | REQ_TYPE_SENSE, /* sense request */ | ||
| 146 | REQ_TYPE_PM_SUSPEND, /* suspend request */ | ||
| 147 | REQ_TYPE_PM_RESUME, /* resume request */ | ||
| 148 | REQ_TYPE_PM_SHUTDOWN, /* shutdown request */ | ||
| 149 | REQ_TYPE_FLUSH, /* flush request */ | ||
| 150 | REQ_TYPE_SPECIAL, /* driver defined type */ | ||
| 151 | REQ_TYPE_LINUX_BLOCK, /* generic block layer message */ | ||
| 152 | /* | ||
| 153 | * for ATA/ATAPI devices. this really doesn't belong here, ide should | ||
| 154 | * use REQ_TYPE_SPECIAL and use rq->cmd[0] with the range of driver | ||
| 155 | * private REQ_LB opcodes to differentiate what type of request this is | ||
| 156 | */ | ||
| 157 | REQ_TYPE_ATA_CMD, | ||
| 158 | REQ_TYPE_ATA_TASK, | ||
| 159 | REQ_TYPE_ATA_TASKFILE, | ||
| 160 | }; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * For request of type REQ_TYPE_LINUX_BLOCK, rq->cmd[0] is the opcode being | ||
| 164 | * sent down (similar to how REQ_TYPE_BLOCK_PC means that ->cmd[] holds a | ||
| 165 | * SCSI cdb. | ||
| 166 | * | ||
| 167 | * 0x00 -> 0x3f are driver private, to be used for whatever purpose they need, | ||
| 168 | * typically to differentiate REQ_TYPE_SPECIAL requests. | ||
| 169 | * | ||
| 170 | */ | ||
| 171 | enum { | ||
| 172 | /* | ||
| 173 | * just examples for now | ||
| 174 | */ | ||
| 175 | REQ_LB_OP_EJECT = 0x40, /* eject request */ | ||
| 176 | REQ_LB_OP_FLUSH = 0x41, /* flush device */ | ||
| 177 | }; | ||
| 178 | |||
| 179 | /* | ||
| 180 | * request type modified bits. first three bits match BIO_RW* bits, important | ||
| 181 | */ | ||
| 182 | enum rq_flag_bits { | ||
| 183 | __REQ_RW, /* not set, read. set, write */ | ||
| 184 | __REQ_FAILFAST, /* no low level driver retries */ | ||
| 185 | __REQ_SORTED, /* elevator knows about this request */ | ||
| 186 | __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ | ||
| 187 | __REQ_HARDBARRIER, /* may not be passed by drive either */ | ||
| 188 | __REQ_FUA, /* forced unit access */ | ||
| 189 | __REQ_NOMERGE, /* don't touch this for merging */ | ||
| 190 | __REQ_STARTED, /* drive already may have started this one */ | ||
| 191 | __REQ_DONTPREP, /* don't call prep for this one */ | ||
| 192 | __REQ_QUEUED, /* uses queueing */ | ||
| 193 | __REQ_ELVPRIV, /* elevator private data attached */ | ||
| 194 | __REQ_FAILED, /* set if the request failed */ | ||
| 195 | __REQ_QUIET, /* don't worry about errors */ | ||
| 196 | __REQ_PREEMPT, /* set for "ide_preempt" requests */ | ||
| 197 | __REQ_ORDERED_COLOR, /* is before or after barrier */ | ||
| 198 | __REQ_RW_SYNC, /* request is sync (O_DIRECT) */ | ||
| 199 | __REQ_ALLOCED, /* request came from our alloc pool */ | ||
| 200 | __REQ_RW_META, /* metadata io request */ | ||
| 201 | __REQ_NR_BITS, /* stops here */ | ||
| 202 | }; | ||
| 203 | |||
| 204 | #define REQ_RW (1 << __REQ_RW) | ||
| 205 | #define REQ_FAILFAST (1 << __REQ_FAILFAST) | ||
| 206 | #define REQ_SORTED (1 << __REQ_SORTED) | ||
| 207 | #define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER) | ||
| 208 | #define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER) | ||
| 209 | #define REQ_FUA (1 << __REQ_FUA) | ||
| 210 | #define REQ_NOMERGE (1 << __REQ_NOMERGE) | ||
| 211 | #define REQ_STARTED (1 << __REQ_STARTED) | ||
| 212 | #define REQ_DONTPREP (1 << __REQ_DONTPREP) | ||
| 213 | #define REQ_QUEUED (1 << __REQ_QUEUED) | ||
| 214 | #define REQ_ELVPRIV (1 << __REQ_ELVPRIV) | ||
| 215 | #define REQ_FAILED (1 << __REQ_FAILED) | ||
| 216 | #define REQ_QUIET (1 << __REQ_QUIET) | ||
| 217 | #define REQ_PREEMPT (1 << __REQ_PREEMPT) | ||
| 218 | #define REQ_ORDERED_COLOR (1 << __REQ_ORDERED_COLOR) | ||
| 219 | #define REQ_RW_SYNC (1 << __REQ_RW_SYNC) | ||
| 220 | #define REQ_ALLOCED (1 << __REQ_ALLOCED) | ||
| 221 | #define REQ_RW_META (1 << __REQ_RW_META) | ||
| 222 | |||
| 123 | #define BLK_MAX_CDB 16 | 223 | #define BLK_MAX_CDB 16 |
| 124 | 224 | ||
| 125 | /* | 225 | /* |
| @@ -129,30 +229,46 @@ struct request { | |||
| 129 | struct list_head queuelist; | 229 | struct list_head queuelist; |
| 130 | struct list_head donelist; | 230 | struct list_head donelist; |
| 131 | 231 | ||
| 132 | unsigned long flags; /* see REQ_ bits below */ | 232 | request_queue_t *q; |
| 233 | |||
| 234 | unsigned int cmd_flags; | ||
| 235 | enum rq_cmd_type_bits cmd_type; | ||
| 133 | 236 | ||
| 134 | /* Maintain bio traversal state for part by part I/O submission. | 237 | /* Maintain bio traversal state for part by part I/O submission. |
| 135 | * hard_* are block layer internals, no driver should touch them! | 238 | * hard_* are block layer internals, no driver should touch them! |
| 136 | */ | 239 | */ |
| 137 | 240 | ||
| 138 | sector_t sector; /* next sector to submit */ | 241 | sector_t sector; /* next sector to submit */ |
| 242 | sector_t hard_sector; /* next sector to complete */ | ||
| 139 | unsigned long nr_sectors; /* no. of sectors left to submit */ | 243 | unsigned long nr_sectors; /* no. of sectors left to submit */ |
| 244 | unsigned long hard_nr_sectors; /* no. of sectors left to complete */ | ||
| 140 | /* no. of sectors left to submit in the current segment */ | 245 | /* no. of sectors left to submit in the current segment */ |
| 141 | unsigned int current_nr_sectors; | 246 | unsigned int current_nr_sectors; |
| 142 | 247 | ||
| 143 | sector_t hard_sector; /* next sector to complete */ | ||
| 144 | unsigned long hard_nr_sectors; /* no. of sectors left to complete */ | ||
| 145 | /* no. of sectors left to complete in the current segment */ | 248 | /* no. of sectors left to complete in the current segment */ |
| 146 | unsigned int hard_cur_sectors; | 249 | unsigned int hard_cur_sectors; |
| 147 | 250 | ||
| 148 | struct bio *bio; | 251 | struct bio *bio; |
| 149 | struct bio *biotail; | 252 | struct bio *biotail; |
| 150 | 253 | ||
| 254 | struct hlist_node hash; /* merge hash */ | ||
| 255 | /* | ||
| 256 | * The rb_node is only used inside the io scheduler, requests | ||
| 257 | * are pruned when moved to the dispatch queue. So let the | ||
| 258 | * completion_data share space with the rb_node. | ||
| 259 | */ | ||
| 260 | union { | ||
| 261 | struct rb_node rb_node; /* sort/lookup */ | ||
| 262 | void *completion_data; | ||
| 263 | }; | ||
| 264 | |||
| 265 | /* | ||
| 266 | * two pointers are available for the IO schedulers, if they need | ||
| 267 | * more they have to dynamically allocate it. | ||
| 268 | */ | ||
| 151 | void *elevator_private; | 269 | void *elevator_private; |
| 152 | void *completion_data; | 270 | void *elevator_private2; |
| 153 | 271 | ||
| 154 | int rq_status; /* should split this into a few status bits */ | ||
| 155 | int errors; | ||
| 156 | struct gendisk *rq_disk; | 272 | struct gendisk *rq_disk; |
| 157 | unsigned long start_time; | 273 | unsigned long start_time; |
| 158 | 274 | ||
| @@ -170,15 +286,13 @@ struct request { | |||
| 170 | 286 | ||
| 171 | unsigned short ioprio; | 287 | unsigned short ioprio; |
| 172 | 288 | ||
| 289 | void *special; | ||
| 290 | char *buffer; | ||
| 291 | |||
| 173 | int tag; | 292 | int tag; |
| 293 | int errors; | ||
| 174 | 294 | ||
| 175 | int ref_count; | 295 | int ref_count; |
| 176 | request_queue_t *q; | ||
| 177 | struct request_list *rl; | ||
| 178 | |||
| 179 | struct completion *waiting; | ||
| 180 | void *special; | ||
| 181 | char *buffer; | ||
| 182 | 296 | ||
| 183 | /* | 297 | /* |
| 184 | * when request is used as a packet command carrier | 298 | * when request is used as a packet command carrier |
| @@ -195,80 +309,14 @@ struct request { | |||
| 195 | int retries; | 309 | int retries; |
| 196 | 310 | ||
| 197 | /* | 311 | /* |
| 198 | * completion callback. end_io_data should be folded in with waiting | 312 | * completion callback. |
| 199 | */ | 313 | */ |
| 200 | rq_end_io_fn *end_io; | 314 | rq_end_io_fn *end_io; |
| 201 | void *end_io_data; | 315 | void *end_io_data; |
| 202 | }; | 316 | }; |
| 203 | 317 | ||
| 204 | /* | 318 | /* |
| 205 | * first three bits match BIO_RW* bits, important | 319 | * State information carried for REQ_TYPE_PM_SUSPEND and REQ_TYPE_PM_RESUME |
| 206 | */ | ||
| 207 | enum rq_flag_bits { | ||
| 208 | __REQ_RW, /* not set, read. set, write */ | ||
| 209 | __REQ_FAILFAST, /* no low level driver retries */ | ||
| 210 | __REQ_SORTED, /* elevator knows about this request */ | ||
| 211 | __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ | ||
| 212 | __REQ_HARDBARRIER, /* may not be passed by drive either */ | ||
| 213 | __REQ_FUA, /* forced unit access */ | ||
| 214 | __REQ_CMD, /* is a regular fs rw request */ | ||
| 215 | __REQ_NOMERGE, /* don't touch this for merging */ | ||
| 216 | __REQ_STARTED, /* drive already may have started this one */ | ||
| 217 | __REQ_DONTPREP, /* don't call prep for this one */ | ||
| 218 | __REQ_QUEUED, /* uses queueing */ | ||
| 219 | __REQ_ELVPRIV, /* elevator private data attached */ | ||
| 220 | /* | ||
| 221 | * for ATA/ATAPI devices | ||
| 222 | */ | ||
| 223 | __REQ_PC, /* packet command (special) */ | ||
| 224 | __REQ_BLOCK_PC, /* queued down pc from block layer */ | ||
| 225 | __REQ_SENSE, /* sense retrival */ | ||
| 226 | |||
| 227 | __REQ_FAILED, /* set if the request failed */ | ||
| 228 | __REQ_QUIET, /* don't worry about errors */ | ||
| 229 | __REQ_SPECIAL, /* driver suplied command */ | ||
| 230 | __REQ_DRIVE_CMD, | ||
| 231 | __REQ_DRIVE_TASK, | ||
| 232 | __REQ_DRIVE_TASKFILE, | ||
| 233 | __REQ_PREEMPT, /* set for "ide_preempt" requests */ | ||
| 234 | __REQ_PM_SUSPEND, /* suspend request */ | ||
| 235 | __REQ_PM_RESUME, /* resume request */ | ||
| 236 | __REQ_PM_SHUTDOWN, /* shutdown request */ | ||
| 237 | __REQ_ORDERED_COLOR, /* is before or after barrier */ | ||
| 238 | __REQ_RW_SYNC, /* request is sync (O_DIRECT) */ | ||
| 239 | __REQ_NR_BITS, /* stops here */ | ||
| 240 | }; | ||
| 241 | |||
| 242 | #define REQ_RW (1 << __REQ_RW) | ||
| 243 | #define REQ_FAILFAST (1 << __REQ_FAILFAST) | ||
| 244 | #define REQ_SORTED (1 << __REQ_SORTED) | ||
| 245 | #define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER) | ||
| 246 | #define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER) | ||
| 247 | #define REQ_FUA (1 << __REQ_FUA) | ||
| 248 | #define REQ_CMD (1 << __REQ_CMD) | ||
| 249 | #define REQ_NOMERGE (1 << __REQ_NOMERGE) | ||
| 250 | #define REQ_STARTED (1 << __REQ_STARTED) | ||
| 251 | #define REQ_DONTPREP (1 << __REQ_DONTPREP) | ||
| 252 | #define REQ_QUEUED (1 << __REQ_QUEUED) | ||
| 253 | #define REQ_ELVPRIV (1 << __REQ_ELVPRIV) | ||
| 254 | #define REQ_PC (1 << __REQ_PC) | ||
| 255 | #define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC) | ||
| 256 | #define REQ_SENSE (1 << __REQ_SENSE) | ||
| 257 | #define REQ_FAILED (1 << __REQ_FAILED) | ||
| 258 | #define REQ_QUIET (1 << __REQ_QUIET) | ||
| 259 | #define REQ_SPECIAL (1 << __REQ_SPECIAL) | ||
| 260 | #define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD) | ||
| 261 | #define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK) | ||
| 262 | #define REQ_DRIVE_TASKFILE (1 << __REQ_DRIVE_TASKFILE) | ||
| 263 | #define REQ_PREEMPT (1 << __REQ_PREEMPT) | ||
| 264 | #define REQ_PM_SUSPEND (1 << __REQ_PM_SUSPEND) | ||
| 265 | #define REQ_PM_RESUME (1 << __REQ_PM_RESUME) | ||
| 266 | #define REQ_PM_SHUTDOWN (1 << __REQ_PM_SHUTDOWN) | ||
| 267 | #define REQ_ORDERED_COLOR (1 << __REQ_ORDERED_COLOR) | ||
| 268 | #define REQ_RW_SYNC (1 << __REQ_RW_SYNC) | ||
| 269 | |||
| 270 | /* | ||
| 271 | * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME | ||
| 272 | * requests. Some step values could eventually be made generic. | 320 | * requests. Some step values could eventually be made generic. |
| 273 | */ | 321 | */ |
| 274 | struct request_pm_state | 322 | struct request_pm_state |
| @@ -432,9 +480,6 @@ struct request_queue | |||
| 432 | struct mutex sysfs_lock; | 480 | struct mutex sysfs_lock; |
| 433 | }; | 481 | }; |
| 434 | 482 | ||
| 435 | #define RQ_INACTIVE (-1) | ||
| 436 | #define RQ_ACTIVE 1 | ||
| 437 | |||
| 438 | #define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */ | 483 | #define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */ |
| 439 | #define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */ | 484 | #define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */ |
| 440 | #define QUEUE_FLAG_STOPPED 2 /* queue is stopped */ | 485 | #define QUEUE_FLAG_STOPPED 2 /* queue is stopped */ |
| @@ -490,25 +535,34 @@ enum { | |||
| 490 | #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) | 535 | #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) |
| 491 | #define blk_queue_flushing(q) ((q)->ordseq) | 536 | #define blk_queue_flushing(q) ((q)->ordseq) |
| 492 | 537 | ||
| 493 | #define blk_fs_request(rq) ((rq)->flags & REQ_CMD) | 538 | #define blk_fs_request(rq) ((rq)->cmd_type == REQ_TYPE_FS) |
| 494 | #define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC) | 539 | #define blk_pc_request(rq) ((rq)->cmd_type == REQ_TYPE_BLOCK_PC) |
| 495 | #define blk_noretry_request(rq) ((rq)->flags & REQ_FAILFAST) | 540 | #define blk_special_request(rq) ((rq)->cmd_type == REQ_TYPE_SPECIAL) |
| 496 | #define blk_rq_started(rq) ((rq)->flags & REQ_STARTED) | 541 | #define blk_sense_request(rq) ((rq)->cmd_type == REQ_TYPE_SENSE) |
| 542 | |||
| 543 | #define blk_noretry_request(rq) ((rq)->cmd_flags & REQ_FAILFAST) | ||
| 544 | #define blk_rq_started(rq) ((rq)->cmd_flags & REQ_STARTED) | ||
| 497 | 545 | ||
| 498 | #define blk_account_rq(rq) (blk_rq_started(rq) && blk_fs_request(rq)) | 546 | #define blk_account_rq(rq) (blk_rq_started(rq) && blk_fs_request(rq)) |
| 499 | 547 | ||
| 500 | #define blk_pm_suspend_request(rq) ((rq)->flags & REQ_PM_SUSPEND) | 548 | #define blk_pm_suspend_request(rq) ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND) |
| 501 | #define blk_pm_resume_request(rq) ((rq)->flags & REQ_PM_RESUME) | 549 | #define blk_pm_resume_request(rq) ((rq)->cmd_type == REQ_TYPE_PM_RESUME) |
| 502 | #define blk_pm_request(rq) \ | 550 | #define blk_pm_request(rq) \ |
| 503 | ((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME)) | 551 | (blk_pm_suspend_request(rq) || blk_pm_resume_request(rq)) |
| 504 | 552 | ||
| 505 | #define blk_sorted_rq(rq) ((rq)->flags & REQ_SORTED) | 553 | #define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED) |
| 506 | #define blk_barrier_rq(rq) ((rq)->flags & REQ_HARDBARRIER) | 554 | #define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER) |
| 507 | #define blk_fua_rq(rq) ((rq)->flags & REQ_FUA) | 555 | #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) |
| 508 | 556 | ||
| 509 | #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) | 557 | #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) |
| 510 | 558 | ||
| 511 | #define rq_data_dir(rq) ((rq)->flags & 1) | 559 | #define rq_data_dir(rq) ((rq)->cmd_flags & 1) |
| 560 | |||
| 561 | /* | ||
| 562 | * We regard a request as sync, if it's a READ or a SYNC write. | ||
| 563 | */ | ||
| 564 | #define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC) | ||
| 565 | #define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META) | ||
| 512 | 566 | ||
| 513 | static inline int blk_queue_full(struct request_queue *q, int rw) | 567 | static inline int blk_queue_full(struct request_queue *q, int rw) |
| 514 | { | 568 | { |
| @@ -541,13 +595,7 @@ static inline void blk_clear_queue_full(struct request_queue *q, int rw) | |||
| 541 | #define RQ_NOMERGE_FLAGS \ | 595 | #define RQ_NOMERGE_FLAGS \ |
| 542 | (REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER) | 596 | (REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER) |
| 543 | #define rq_mergeable(rq) \ | 597 | #define rq_mergeable(rq) \ |
| 544 | (!((rq)->flags & RQ_NOMERGE_FLAGS) && blk_fs_request((rq))) | 598 | (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && blk_fs_request((rq))) |
| 545 | |||
| 546 | /* | ||
| 547 | * noop, requests are automagically marked as active/inactive by I/O | ||
| 548 | * scheduler -- see elv_next_request | ||
| 549 | */ | ||
| 550 | #define blk_queue_headactive(q, head_active) | ||
| 551 | 599 | ||
| 552 | /* | 600 | /* |
| 553 | * q->prep_rq_fn return values | 601 | * q->prep_rq_fn return values |
| @@ -586,11 +634,6 @@ static inline void blk_queue_bounce(request_queue_t *q, struct bio **bio) | |||
| 586 | if ((rq->bio)) \ | 634 | if ((rq->bio)) \ |
| 587 | for (_bio = (rq)->bio; _bio; _bio = _bio->bi_next) | 635 | for (_bio = (rq)->bio; _bio; _bio = _bio->bi_next) |
| 588 | 636 | ||
| 589 | struct sec_size { | ||
| 590 | unsigned block_size; | ||
| 591 | unsigned block_size_bits; | ||
| 592 | }; | ||
| 593 | |||
| 594 | extern int blk_register_queue(struct gendisk *disk); | 637 | extern int blk_register_queue(struct gendisk *disk); |
| 595 | extern void blk_unregister_queue(struct gendisk *disk); | 638 | extern void blk_unregister_queue(struct gendisk *disk); |
| 596 | extern void register_disk(struct gendisk *dev); | 639 | extern void register_disk(struct gendisk *dev); |
| @@ -612,6 +655,7 @@ extern void blk_stop_queue(request_queue_t *q); | |||
| 612 | extern void blk_sync_queue(struct request_queue *q); | 655 | extern void blk_sync_queue(struct request_queue *q); |
| 613 | extern void __blk_stop_queue(request_queue_t *q); | 656 | extern void __blk_stop_queue(request_queue_t *q); |
| 614 | extern void blk_run_queue(request_queue_t *); | 657 | extern void blk_run_queue(request_queue_t *); |
| 658 | extern void blk_start_queueing(request_queue_t *); | ||
| 615 | extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *); | 659 | extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *); |
| 616 | extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int); | 660 | extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int); |
| 617 | extern int blk_rq_unmap_user(struct bio *, unsigned int); | 661 | extern int blk_rq_unmap_user(struct bio *, unsigned int); |
| @@ -655,16 +699,6 @@ extern void end_that_request_last(struct request *, int); | |||
| 655 | extern void end_request(struct request *req, int uptodate); | 699 | extern void end_request(struct request *req, int uptodate); |
| 656 | extern void blk_complete_request(struct request *); | 700 | extern void blk_complete_request(struct request *); |
| 657 | 701 | ||
| 658 | static inline int rq_all_done(struct request *rq, unsigned int nr_bytes) | ||
| 659 | { | ||
| 660 | if (blk_fs_request(rq)) | ||
| 661 | return (nr_bytes >= (rq->hard_nr_sectors << 9)); | ||
| 662 | else if (blk_pc_request(rq)) | ||
| 663 | return nr_bytes >= rq->data_len; | ||
| 664 | |||
| 665 | return 0; | ||
| 666 | } | ||
| 667 | |||
| 668 | /* | 702 | /* |
| 669 | * end_that_request_first/chunk() takes an uptodate argument. we account | 703 | * end_that_request_first/chunk() takes an uptodate argument. we account |
| 670 | * any value <= as an io error. 0 means -EIO for compatability reasons, | 704 | * any value <= as an io error. 0 means -EIO for compatability reasons, |
| @@ -679,21 +713,6 @@ static inline void blkdev_dequeue_request(struct request *req) | |||
| 679 | } | 713 | } |
| 680 | 714 | ||
| 681 | /* | 715 | /* |
| 682 | * This should be in elevator.h, but that requires pulling in rq and q | ||
| 683 | */ | ||
| 684 | static inline void elv_dispatch_add_tail(struct request_queue *q, | ||
| 685 | struct request *rq) | ||
| 686 | { | ||
| 687 | if (q->last_merge == rq) | ||
| 688 | q->last_merge = NULL; | ||
| 689 | q->nr_sorted--; | ||
| 690 | |||
| 691 | q->end_sector = rq_end_sector(rq); | ||
| 692 | q->boundary_rq = rq; | ||
| 693 | list_add_tail(&rq->queuelist, &q->queue_head); | ||
| 694 | } | ||
| 695 | |||
| 696 | /* | ||
| 697 | * Access functions for manipulating queue properties | 716 | * Access functions for manipulating queue properties |
| 698 | */ | 717 | */ |
| 699 | extern request_queue_t *blk_init_queue_node(request_fn_proc *rfn, | 718 | extern request_queue_t *blk_init_queue_node(request_fn_proc *rfn, |
| @@ -737,7 +756,7 @@ extern void blk_put_queue(request_queue_t *); | |||
| 737 | */ | 756 | */ |
| 738 | #define blk_queue_tag_depth(q) ((q)->queue_tags->busy) | 757 | #define blk_queue_tag_depth(q) ((q)->queue_tags->busy) |
| 739 | #define blk_queue_tag_queue(q) ((q)->queue_tags->busy < (q)->queue_tags->max_depth) | 758 | #define blk_queue_tag_queue(q) ((q)->queue_tags->busy < (q)->queue_tags->max_depth) |
| 740 | #define blk_rq_tagged(rq) ((rq)->flags & REQ_QUEUED) | 759 | #define blk_rq_tagged(rq) ((rq)->cmd_flags & REQ_QUEUED) |
| 741 | extern int blk_queue_start_tag(request_queue_t *, struct request *); | 760 | extern int blk_queue_start_tag(request_queue_t *, struct request *); |
| 742 | extern struct request *blk_queue_find_tag(request_queue_t *, int); | 761 | extern struct request *blk_queue_find_tag(request_queue_t *, int); |
| 743 | extern void blk_queue_end_tag(request_queue_t *, struct request *); | 762 | extern void blk_queue_end_tag(request_queue_t *, struct request *); |
| @@ -787,14 +806,6 @@ static inline int queue_dma_alignment(request_queue_t *q) | |||
| 787 | return retval; | 806 | return retval; |
| 788 | } | 807 | } |
| 789 | 808 | ||
| 790 | static inline int bdev_dma_aligment(struct block_device *bdev) | ||
| 791 | { | ||
| 792 | return queue_dma_alignment(bdev_get_queue(bdev)); | ||
| 793 | } | ||
| 794 | |||
| 795 | #define blk_finished_io(nsects) do { } while (0) | ||
| 796 | #define blk_started_io(nsects) do { } while (0) | ||
| 797 | |||
| 798 | /* assumes size > 256 */ | 809 | /* assumes size > 256 */ |
| 799 | static inline unsigned int blksize_bits(unsigned int size) | 810 | static inline unsigned int blksize_bits(unsigned int size) |
| 800 | { | 811 | { |
| @@ -824,24 +835,32 @@ struct work_struct; | |||
| 824 | int kblockd_schedule_work(struct work_struct *work); | 835 | int kblockd_schedule_work(struct work_struct *work); |
| 825 | void kblockd_flush(void); | 836 | void kblockd_flush(void); |
| 826 | 837 | ||
| 827 | #ifdef CONFIG_LBD | ||
| 828 | # include <asm/div64.h> | ||
| 829 | # define sector_div(a, b) do_div(a, b) | ||
| 830 | #else | ||
| 831 | # define sector_div(n, b)( \ | ||
| 832 | { \ | ||
| 833 | int _res; \ | ||
| 834 | _res = (n) % (b); \ | ||
| 835 | (n) /= (b); \ | ||
| 836 | _res; \ | ||
| 837 | } \ | ||
| 838 | ) | ||
| 839 | #endif | ||
| 840 | |||
| 841 | #define MODULE_ALIAS_BLOCKDEV(major,minor) \ | 838 | #define MODULE_ALIAS_BLOCKDEV(major,minor) \ |
| 842 | MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor)) | 839 | MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor)) |
| 843 | #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \ | 840 | #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \ |
| 844 | MODULE_ALIAS("block-major-" __stringify(major) "-*") | 841 | MODULE_ALIAS("block-major-" __stringify(major) "-*") |
| 845 | 842 | ||
| 846 | 843 | ||
| 844 | #else /* CONFIG_BLOCK */ | ||
| 845 | /* | ||
| 846 | * stubs for when the block layer is configured out | ||
| 847 | */ | ||
| 848 | #define buffer_heads_over_limit 0 | ||
| 849 | |||
| 850 | static inline long blk_congestion_wait(int rw, long timeout) | ||
| 851 | { | ||
| 852 | return io_schedule_timeout(timeout); | ||
| 853 | } | ||
| 854 | |||
| 855 | static inline long nr_blockdev_pages(void) | ||
| 856 | { | ||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | static inline void exit_io_context(void) | ||
| 861 | { | ||
| 862 | } | ||
| 863 | |||
| 864 | #endif /* CONFIG_BLOCK */ | ||
| 865 | |||
| 847 | #endif | 866 | #endif |
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 7520cc1ff9e2..b99a714fcac6 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h | |||
| @@ -20,6 +20,7 @@ enum blktrace_cat { | |||
| 20 | BLK_TC_PC = 1 << 9, /* pc requests */ | 20 | BLK_TC_PC = 1 << 9, /* pc requests */ |
| 21 | BLK_TC_NOTIFY = 1 << 10, /* special message */ | 21 | BLK_TC_NOTIFY = 1 << 10, /* special message */ |
| 22 | BLK_TC_AHEAD = 1 << 11, /* readahead */ | 22 | BLK_TC_AHEAD = 1 << 11, /* readahead */ |
| 23 | BLK_TC_META = 1 << 12, /* metadata */ | ||
| 23 | 24 | ||
| 24 | BLK_TC_END = 1 << 15, /* only 16-bits, reminder */ | 25 | BLK_TC_END = 1 << 15, /* only 16-bits, reminder */ |
| 25 | }; | 26 | }; |
| @@ -148,7 +149,7 @@ static inline void blk_add_trace_rq(struct request_queue *q, struct request *rq, | |||
| 148 | u32 what) | 149 | u32 what) |
| 149 | { | 150 | { |
| 150 | struct blk_trace *bt = q->blk_trace; | 151 | struct blk_trace *bt = q->blk_trace; |
| 151 | int rw = rq->flags & 0x03; | 152 | int rw = rq->cmd_flags & 0x03; |
| 152 | 153 | ||
| 153 | if (likely(!bt)) | 154 | if (likely(!bt)) |
| 154 | return; | 155 | return; |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 737e407d0cd1..131ffd37e716 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include <linux/wait.h> | 14 | #include <linux/wait.h> |
| 15 | #include <asm/atomic.h> | 15 | #include <asm/atomic.h> |
| 16 | 16 | ||
| 17 | #ifdef CONFIG_BLOCK | ||
| 18 | |||
| 17 | enum bh_state_bits { | 19 | enum bh_state_bits { |
| 18 | BH_Uptodate, /* Contains valid data */ | 20 | BH_Uptodate, /* Contains valid data */ |
| 19 | BH_Dirty, /* Is dirty */ | 21 | BH_Dirty, /* Is dirty */ |
| @@ -190,9 +192,7 @@ extern int buffer_heads_over_limit; | |||
| 190 | * Generic address_space_operations implementations for buffer_head-backed | 192 | * Generic address_space_operations implementations for buffer_head-backed |
| 191 | * address_spaces. | 193 | * address_spaces. |
| 192 | */ | 194 | */ |
| 193 | int try_to_release_page(struct page * page, gfp_t gfp_mask); | ||
| 194 | void block_invalidatepage(struct page *page, unsigned long offset); | 195 | void block_invalidatepage(struct page *page, unsigned long offset); |
| 195 | void do_invalidatepage(struct page *page, unsigned long offset); | ||
| 196 | int block_write_full_page(struct page *page, get_block_t *get_block, | 196 | int block_write_full_page(struct page *page, get_block_t *get_block, |
| 197 | struct writeback_control *wbc); | 197 | struct writeback_control *wbc); |
| 198 | int block_read_full_page(struct page*, get_block_t*); | 198 | int block_read_full_page(struct page*, get_block_t*); |
| @@ -302,4 +302,19 @@ static inline void lock_buffer(struct buffer_head *bh) | |||
| 302 | __lock_buffer(bh); | 302 | __lock_buffer(bh); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | extern int __set_page_dirty_buffers(struct page *page); | ||
| 306 | |||
| 307 | #else /* CONFIG_BLOCK */ | ||
| 308 | |||
| 309 | static inline void buffer_init(void) {} | ||
| 310 | static inline int try_to_free_buffers(struct page *page) { return 1; } | ||
| 311 | static inline int sync_blockdev(struct block_device *bdev) { return 0; } | ||
| 312 | static inline int inode_has_buffers(struct inode *inode) { return 0; } | ||
| 313 | static inline void invalidate_inode_buffers(struct inode *inode) {} | ||
| 314 | static inline int remove_inode_buffers(struct inode *inode) { return 1; } | ||
| 315 | static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } | ||
| 316 | static inline void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) {} | ||
| 317 | |||
| 318 | |||
| 319 | #endif /* CONFIG_BLOCK */ | ||
| 305 | #endif /* _LINUX_BUFFER_HEAD_H */ | 320 | #endif /* _LINUX_BUFFER_HEAD_H */ |
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index bea0255196c4..d61ef5951538 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h | |||
| @@ -90,6 +90,7 @@ COMPATIBLE_IOCTL(FDTWADDLE) | |||
| 90 | COMPATIBLE_IOCTL(FDFMTTRK) | 90 | COMPATIBLE_IOCTL(FDFMTTRK) |
| 91 | COMPATIBLE_IOCTL(FDRAWCMD) | 91 | COMPATIBLE_IOCTL(FDRAWCMD) |
| 92 | /* 0x12 */ | 92 | /* 0x12 */ |
| 93 | #ifdef CONFIG_BLOCK | ||
| 93 | COMPATIBLE_IOCTL(BLKRASET) | 94 | COMPATIBLE_IOCTL(BLKRASET) |
| 94 | COMPATIBLE_IOCTL(BLKROSET) | 95 | COMPATIBLE_IOCTL(BLKROSET) |
| 95 | COMPATIBLE_IOCTL(BLKROGET) | 96 | COMPATIBLE_IOCTL(BLKROGET) |
| @@ -103,6 +104,7 @@ COMPATIBLE_IOCTL(BLKTRACESETUP) | |||
| 103 | COMPATIBLE_IOCTL(BLKTRACETEARDOWN) | 104 | COMPATIBLE_IOCTL(BLKTRACETEARDOWN) |
| 104 | ULONG_IOCTL(BLKRASET) | 105 | ULONG_IOCTL(BLKRASET) |
| 105 | ULONG_IOCTL(BLKFRASET) | 106 | ULONG_IOCTL(BLKFRASET) |
| 107 | #endif | ||
| 106 | /* RAID */ | 108 | /* RAID */ |
| 107 | COMPATIBLE_IOCTL(RAID_VERSION) | 109 | COMPATIBLE_IOCTL(RAID_VERSION) |
| 108 | COMPATIBLE_IOCTL(GET_ARRAY_INFO) | 110 | COMPATIBLE_IOCTL(GET_ARRAY_INFO) |
| @@ -395,12 +397,6 @@ COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) | |||
| 395 | COMPATIBLE_IOCTL(DVD_AUTH) | 397 | COMPATIBLE_IOCTL(DVD_AUTH) |
| 396 | /* pktcdvd */ | 398 | /* pktcdvd */ |
| 397 | COMPATIBLE_IOCTL(PACKET_CTRL_CMD) | 399 | COMPATIBLE_IOCTL(PACKET_CTRL_CMD) |
| 398 | /* Big L */ | ||
| 399 | ULONG_IOCTL(LOOP_SET_FD) | ||
| 400 | ULONG_IOCTL(LOOP_CHANGE_FD) | ||
| 401 | COMPATIBLE_IOCTL(LOOP_CLR_FD) | ||
| 402 | COMPATIBLE_IOCTL(LOOP_GET_STATUS64) | ||
| 403 | COMPATIBLE_IOCTL(LOOP_SET_STATUS64) | ||
| 404 | /* Big A */ | 400 | /* Big A */ |
| 405 | /* sparc only */ | 401 | /* sparc only */ |
| 406 | /* Big Q for sound/OSS */ | 402 | /* Big Q for sound/OSS */ |
diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 1713ace808bf..b3370ef5164d 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h | |||
| @@ -1,12 +1,16 @@ | |||
| 1 | #ifndef _LINUX_ELEVATOR_H | 1 | #ifndef _LINUX_ELEVATOR_H |
| 2 | #define _LINUX_ELEVATOR_H | 2 | #define _LINUX_ELEVATOR_H |
| 3 | 3 | ||
| 4 | #include <linux/percpu.h> | ||
| 5 | |||
| 6 | #ifdef CONFIG_BLOCK | ||
| 7 | |||
| 4 | typedef int (elevator_merge_fn) (request_queue_t *, struct request **, | 8 | typedef int (elevator_merge_fn) (request_queue_t *, struct request **, |
| 5 | struct bio *); | 9 | struct bio *); |
| 6 | 10 | ||
| 7 | typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *); | 11 | typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *); |
| 8 | 12 | ||
| 9 | typedef void (elevator_merged_fn) (request_queue_t *, struct request *); | 13 | typedef void (elevator_merged_fn) (request_queue_t *, struct request *, int); |
| 10 | 14 | ||
| 11 | typedef int (elevator_dispatch_fn) (request_queue_t *, int); | 15 | typedef int (elevator_dispatch_fn) (request_queue_t *, int); |
| 12 | 16 | ||
| @@ -14,9 +18,9 @@ typedef void (elevator_add_req_fn) (request_queue_t *, struct request *); | |||
| 14 | typedef int (elevator_queue_empty_fn) (request_queue_t *); | 18 | typedef int (elevator_queue_empty_fn) (request_queue_t *); |
| 15 | typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); | 19 | typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); |
| 16 | typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); | 20 | typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); |
| 17 | typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *); | 21 | typedef int (elevator_may_queue_fn) (request_queue_t *, int); |
| 18 | 22 | ||
| 19 | typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, gfp_t); | 23 | typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, gfp_t); |
| 20 | typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); | 24 | typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); |
| 21 | typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *); | 25 | typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *); |
| 22 | typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *); | 26 | typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *); |
| @@ -82,19 +86,21 @@ struct elevator_queue | |||
| 82 | struct kobject kobj; | 86 | struct kobject kobj; |
| 83 | struct elevator_type *elevator_type; | 87 | struct elevator_type *elevator_type; |
| 84 | struct mutex sysfs_lock; | 88 | struct mutex sysfs_lock; |
| 89 | struct hlist_head *hash; | ||
| 85 | }; | 90 | }; |
| 86 | 91 | ||
| 87 | /* | 92 | /* |
| 88 | * block elevator interface | 93 | * block elevator interface |
| 89 | */ | 94 | */ |
| 90 | extern void elv_dispatch_sort(request_queue_t *, struct request *); | 95 | extern void elv_dispatch_sort(request_queue_t *, struct request *); |
| 96 | extern void elv_dispatch_add_tail(request_queue_t *, struct request *); | ||
| 91 | extern void elv_add_request(request_queue_t *, struct request *, int, int); | 97 | extern void elv_add_request(request_queue_t *, struct request *, int, int); |
| 92 | extern void __elv_add_request(request_queue_t *, struct request *, int, int); | 98 | extern void __elv_add_request(request_queue_t *, struct request *, int, int); |
| 93 | extern void elv_insert(request_queue_t *, struct request *, int); | 99 | extern void elv_insert(request_queue_t *, struct request *, int); |
| 94 | extern int elv_merge(request_queue_t *, struct request **, struct bio *); | 100 | extern int elv_merge(request_queue_t *, struct request **, struct bio *); |
| 95 | extern void elv_merge_requests(request_queue_t *, struct request *, | 101 | extern void elv_merge_requests(request_queue_t *, struct request *, |
| 96 | struct request *); | 102 | struct request *); |
| 97 | extern void elv_merged_request(request_queue_t *, struct request *); | 103 | extern void elv_merged_request(request_queue_t *, struct request *, int); |
| 98 | extern void elv_dequeue_request(request_queue_t *, struct request *); | 104 | extern void elv_dequeue_request(request_queue_t *, struct request *); |
| 99 | extern void elv_requeue_request(request_queue_t *, struct request *); | 105 | extern void elv_requeue_request(request_queue_t *, struct request *); |
| 100 | extern int elv_queue_empty(request_queue_t *); | 106 | extern int elv_queue_empty(request_queue_t *); |
| @@ -103,9 +109,9 @@ extern struct request *elv_former_request(request_queue_t *, struct request *); | |||
| 103 | extern struct request *elv_latter_request(request_queue_t *, struct request *); | 109 | extern struct request *elv_latter_request(request_queue_t *, struct request *); |
| 104 | extern int elv_register_queue(request_queue_t *q); | 110 | extern int elv_register_queue(request_queue_t *q); |
| 105 | extern void elv_unregister_queue(request_queue_t *q); | 111 | extern void elv_unregister_queue(request_queue_t *q); |
| 106 | extern int elv_may_queue(request_queue_t *, int, struct bio *); | 112 | extern int elv_may_queue(request_queue_t *, int); |
| 107 | extern void elv_completed_request(request_queue_t *, struct request *); | 113 | extern void elv_completed_request(request_queue_t *, struct request *); |
| 108 | extern int elv_set_request(request_queue_t *, struct request *, struct bio *, gfp_t); | 114 | extern int elv_set_request(request_queue_t *, struct request *, gfp_t); |
| 109 | extern void elv_put_request(request_queue_t *, struct request *); | 115 | extern void elv_put_request(request_queue_t *, struct request *); |
| 110 | 116 | ||
| 111 | /* | 117 | /* |
| @@ -125,6 +131,19 @@ extern void elevator_exit(elevator_t *); | |||
| 125 | extern int elv_rq_merge_ok(struct request *, struct bio *); | 131 | extern int elv_rq_merge_ok(struct request *, struct bio *); |
| 126 | 132 | ||
| 127 | /* | 133 | /* |
| 134 | * Helper functions. | ||
| 135 | */ | ||
| 136 | extern struct request *elv_rb_former_request(request_queue_t *, struct request *); | ||
| 137 | extern struct request *elv_rb_latter_request(request_queue_t *, struct request *); | ||
| 138 | |||
| 139 | /* | ||
| 140 | * rb support functions. | ||
| 141 | */ | ||
| 142 | extern struct request *elv_rb_add(struct rb_root *, struct request *); | ||
| 143 | extern void elv_rb_del(struct rb_root *, struct request *); | ||
| 144 | extern struct request *elv_rb_find(struct rb_root *, sector_t); | ||
| 145 | |||
| 146 | /* | ||
| 128 | * Return values from elevator merger | 147 | * Return values from elevator merger |
| 129 | */ | 148 | */ |
| 130 | #define ELEVATOR_NO_MERGE 0 | 149 | #define ELEVATOR_NO_MERGE 0 |
| @@ -149,5 +168,42 @@ enum { | |||
| 149 | }; | 168 | }; |
| 150 | 169 | ||
| 151 | #define rq_end_sector(rq) ((rq)->sector + (rq)->nr_sectors) | 170 | #define rq_end_sector(rq) ((rq)->sector + (rq)->nr_sectors) |
| 171 | #define rb_entry_rq(node) rb_entry((node), struct request, rb_node) | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Hack to reuse the donelist list_head as the fifo time holder while | ||
| 175 | * the request is in the io scheduler. Saves an unsigned long in rq. | ||
| 176 | */ | ||
| 177 | #define rq_fifo_time(rq) ((unsigned long) (rq)->donelist.next) | ||
| 178 | #define rq_set_fifo_time(rq,exp) ((rq)->donelist.next = (void *) (exp)) | ||
| 179 | #define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) | ||
| 180 | #define rq_fifo_clear(rq) do { \ | ||
| 181 | list_del_init(&(rq)->queuelist); \ | ||
| 182 | INIT_LIST_HEAD(&(rq)->donelist); \ | ||
| 183 | } while (0) | ||
| 152 | 184 | ||
| 185 | /* | ||
| 186 | * io context count accounting | ||
| 187 | */ | ||
| 188 | #define elv_ioc_count_mod(name, __val) \ | ||
| 189 | do { \ | ||
| 190 | preempt_disable(); \ | ||
| 191 | __get_cpu_var(name) += (__val); \ | ||
| 192 | preempt_enable(); \ | ||
| 193 | } while (0) | ||
| 194 | |||
| 195 | #define elv_ioc_count_inc(name) elv_ioc_count_mod(name, 1) | ||
| 196 | #define elv_ioc_count_dec(name) elv_ioc_count_mod(name, -1) | ||
| 197 | |||
| 198 | #define elv_ioc_count_read(name) \ | ||
| 199 | ({ \ | ||
| 200 | unsigned long __val = 0; \ | ||
| 201 | int __cpu; \ | ||
| 202 | smp_wmb(); \ | ||
| 203 | for_each_possible_cpu(__cpu) \ | ||
| 204 | __val += per_cpu(name, __cpu); \ | ||
| 205 | __val; \ | ||
| 206 | }) | ||
| 207 | |||
| 208 | #endif /* CONFIG_BLOCK */ | ||
| 153 | #endif | 209 | #endif |
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index 33a1aa107329..153d755376a4 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h | |||
| @@ -165,41 +165,49 @@ struct ext2_group_desc | |||
| 165 | #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) | 165 | #define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) |
| 166 | 166 | ||
| 167 | /* | 167 | /* |
| 168 | * Inode flags | 168 | * Inode flags (GETFLAGS/SETFLAGS) |
| 169 | */ | 169 | */ |
| 170 | #define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ | 170 | #define EXT2_SECRM_FL FS_SECRM_FL /* Secure deletion */ |
| 171 | #define EXT2_UNRM_FL 0x00000002 /* Undelete */ | 171 | #define EXT2_UNRM_FL FS_UNRM_FL /* Undelete */ |
| 172 | #define EXT2_COMPR_FL 0x00000004 /* Compress file */ | 172 | #define EXT2_COMPR_FL FS_COMPR_FL /* Compress file */ |
| 173 | #define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ | 173 | #define EXT2_SYNC_FL FS_SYNC_FL /* Synchronous updates */ |
| 174 | #define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ | 174 | #define EXT2_IMMUTABLE_FL FS_IMMUTABLE_FL /* Immutable file */ |
| 175 | #define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ | 175 | #define EXT2_APPEND_FL FS_APPEND_FL /* writes to file may only append */ |
| 176 | #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ | 176 | #define EXT2_NODUMP_FL FS_NODUMP_FL /* do not dump file */ |
| 177 | #define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ | 177 | #define EXT2_NOATIME_FL FS_NOATIME_FL /* do not update atime */ |
| 178 | /* Reserved for compression usage... */ | 178 | /* Reserved for compression usage... */ |
| 179 | #define EXT2_DIRTY_FL 0x00000100 | 179 | #define EXT2_DIRTY_FL FS_DIRTY_FL |
| 180 | #define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ | 180 | #define EXT2_COMPRBLK_FL FS_COMPRBLK_FL /* One or more compressed clusters */ |
| 181 | #define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */ | 181 | #define EXT2_NOCOMP_FL FS_NOCOMP_FL /* Don't compress */ |
| 182 | #define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ | 182 | #define EXT2_ECOMPR_FL FS_ECOMPR_FL /* Compression error */ |
| 183 | /* End compression flags --- maybe not all used */ | 183 | /* End compression flags --- maybe not all used */ |
| 184 | #define EXT2_BTREE_FL 0x00001000 /* btree format dir */ | 184 | #define EXT2_BTREE_FL FS_BTREE_FL /* btree format dir */ |
| 185 | #define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ | 185 | #define EXT2_INDEX_FL FS_INDEX_FL /* hash-indexed directory */ |
| 186 | #define EXT2_IMAGIC_FL 0x00002000 /* AFS directory */ | 186 | #define EXT2_IMAGIC_FL FS_IMAGIC_FL /* AFS directory */ |
| 187 | #define EXT2_JOURNAL_DATA_FL 0x00004000 /* Reserved for ext3 */ | 187 | #define EXT2_JOURNAL_DATA_FL FS_JOURNAL_DATA_FL /* Reserved for ext3 */ |
| 188 | #define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ | 188 | #define EXT2_NOTAIL_FL FS_NOTAIL_FL /* file tail should not be merged */ |
| 189 | #define EXT2_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ | 189 | #define EXT2_DIRSYNC_FL FS_DIRSYNC_FL /* dirsync behaviour (directories only) */ |
| 190 | #define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ | 190 | #define EXT2_TOPDIR_FL FS_TOPDIR_FL /* Top of directory hierarchies*/ |
| 191 | #define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ | 191 | #define EXT2_RESERVED_FL FS_RESERVED_FL /* reserved for ext2 lib */ |
| 192 | 192 | ||
| 193 | #define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ | 193 | #define EXT2_FL_USER_VISIBLE FS_FL_USER_VISIBLE /* User visible flags */ |
| 194 | #define EXT2_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ | 194 | #define EXT2_FL_USER_MODIFIABLE FS_FL_USER_MODIFIABLE /* User modifiable flags */ |
| 195 | 195 | ||
| 196 | /* | 196 | /* |
| 197 | * ioctl commands | 197 | * ioctl commands |
| 198 | */ | 198 | */ |
| 199 | #define EXT2_IOC_GETFLAGS _IOR('f', 1, long) | 199 | #define EXT2_IOC_GETFLAGS FS_IOC_GETFLAGS |
| 200 | #define EXT2_IOC_SETFLAGS _IOW('f', 2, long) | 200 | #define EXT2_IOC_SETFLAGS FS_IOC_SETFLAGS |
| 201 | #define EXT2_IOC_GETVERSION _IOR('v', 1, long) | 201 | #define EXT2_IOC_GETVERSION FS_IOC_GETVERSION |
| 202 | #define EXT2_IOC_SETVERSION _IOW('v', 2, long) | 202 | #define EXT2_IOC_SETVERSION FS_IOC_SETVERSION |
| 203 | |||
| 204 | /* | ||
| 205 | * ioctl commands in 32 bit emulation | ||
| 206 | */ | ||
| 207 | #define EXT2_IOC32_GETFLAGS FS_IOC32_GETFLAGS | ||
| 208 | #define EXT2_IOC32_SETFLAGS FS_IOC32_SETFLAGS | ||
| 209 | #define EXT2_IOC32_GETVERSION FS_IOC32_GETVERSION | ||
| 210 | #define EXT2_IOC32_SETVERSION FS_IOC32_SETVERSION | ||
| 203 | 211 | ||
| 204 | /* | 212 | /* |
| 205 | * Structure of an inode on the disk | 213 | * Structure of an inode on the disk |
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index cc08f56750da..11cca1bdc0c7 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h | |||
| @@ -216,14 +216,14 @@ struct ext3_new_group_data { | |||
| 216 | /* | 216 | /* |
| 217 | * ioctl commands | 217 | * ioctl commands |
| 218 | */ | 218 | */ |
| 219 | #define EXT3_IOC_GETFLAGS _IOR('f', 1, long) | 219 | #define EXT3_IOC_GETFLAGS FS_IOC_GETFLAGS |
| 220 | #define EXT3_IOC_SETFLAGS _IOW('f', 2, long) | 220 | #define EXT3_IOC_SETFLAGS FS_IOC_SETFLAGS |
| 221 | #define EXT3_IOC_GETVERSION _IOR('f', 3, long) | 221 | #define EXT3_IOC_GETVERSION _IOR('f', 3, long) |
| 222 | #define EXT3_IOC_SETVERSION _IOW('f', 4, long) | 222 | #define EXT3_IOC_SETVERSION _IOW('f', 4, long) |
| 223 | #define EXT3_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long) | 223 | #define EXT3_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long) |
| 224 | #define EXT3_IOC_GROUP_ADD _IOW('f', 8,struct ext3_new_group_input) | 224 | #define EXT3_IOC_GROUP_ADD _IOW('f', 8,struct ext3_new_group_input) |
| 225 | #define EXT3_IOC_GETVERSION_OLD _IOR('v', 1, long) | 225 | #define EXT3_IOC_GETVERSION_OLD FS_IOC_GETVERSION |
| 226 | #define EXT3_IOC_SETVERSION_OLD _IOW('v', 2, long) | 226 | #define EXT3_IOC_SETVERSION_OLD FS_IOC_SETVERSION |
| 227 | #ifdef CONFIG_JBD_DEBUG | 227 | #ifdef CONFIG_JBD_DEBUG |
| 228 | #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long) | 228 | #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long) |
| 229 | #endif | 229 | #endif |
| @@ -231,6 +231,23 @@ struct ext3_new_group_data { | |||
| 231 | #define EXT3_IOC_SETRSVSZ _IOW('f', 6, long) | 231 | #define EXT3_IOC_SETRSVSZ _IOW('f', 6, long) |
| 232 | 232 | ||
| 233 | /* | 233 | /* |
| 234 | * ioctl commands in 32 bit emulation | ||
| 235 | */ | ||
| 236 | #define EXT3_IOC32_GETFLAGS FS_IOC32_GETFLAGS | ||
| 237 | #define EXT3_IOC32_SETFLAGS FS_IOC32_SETFLAGS | ||
| 238 | #define EXT3_IOC32_GETVERSION _IOR('f', 3, int) | ||
| 239 | #define EXT3_IOC32_SETVERSION _IOW('f', 4, int) | ||
| 240 | #define EXT3_IOC32_GETRSVSZ _IOR('f', 5, int) | ||
| 241 | #define EXT3_IOC32_SETRSVSZ _IOW('f', 6, int) | ||
| 242 | #define EXT3_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int) | ||
| 243 | #ifdef CONFIG_JBD_DEBUG | ||
| 244 | #define EXT3_IOC32_WAIT_FOR_READONLY _IOR('f', 99, int) | ||
| 245 | #endif | ||
| 246 | #define EXT3_IOC32_GETVERSION_OLD FS_IOC32_GETVERSION | ||
| 247 | #define EXT3_IOC32_SETVERSION_OLD FS_IOC32_SETVERSION | ||
| 248 | |||
| 249 | |||
| 250 | /* | ||
| 234 | * Mount options | 251 | * Mount options |
| 235 | */ | 252 | */ |
| 236 | struct ext3_mount_options { | 253 | struct ext3_mount_options { |
| @@ -812,6 +829,7 @@ extern void ext3_set_aops(struct inode *inode); | |||
| 812 | /* ioctl.c */ | 829 | /* ioctl.c */ |
| 813 | extern int ext3_ioctl (struct inode *, struct file *, unsigned int, | 830 | extern int ext3_ioctl (struct inode *, struct file *, unsigned int, |
| 814 | unsigned long); | 831 | unsigned long); |
| 832 | extern long ext3_compat_ioctl (struct file *, unsigned int, unsigned long); | ||
| 815 | 833 | ||
| 816 | /* namei.c */ | 834 | /* namei.c */ |
| 817 | extern int ext3_orphan_add(handle_t *, struct inode *); | 835 | extern int ext3_orphan_add(handle_t *, struct inode *); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 6eafbe309483..5baf3a153403 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -79,8 +79,8 @@ extern int dir_notify_enable; | |||
| 79 | #define WRITE 1 | 79 | #define WRITE 1 |
| 80 | #define READA 2 /* read-ahead - don't block if no resources */ | 80 | #define READA 2 /* read-ahead - don't block if no resources */ |
| 81 | #define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ | 81 | #define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ |
| 82 | #define SPECIAL 4 /* For non-blockdevice requests in request queue */ | ||
| 83 | #define READ_SYNC (READ | (1 << BIO_RW_SYNC)) | 82 | #define READ_SYNC (READ | (1 << BIO_RW_SYNC)) |
| 83 | #define READ_META (READ | (1 << BIO_RW_META)) | ||
| 84 | #define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC)) | 84 | #define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC)) |
| 85 | #define WRITE_BARRIER ((1 << BIO_RW) | (1 << BIO_RW_BARRIER)) | 85 | #define WRITE_BARRIER ((1 << BIO_RW) | (1 << BIO_RW_BARRIER)) |
| 86 | 86 | ||
| @@ -217,6 +217,45 @@ extern int dir_notify_enable; | |||
| 217 | #define FIBMAP _IO(0x00,1) /* bmap access */ | 217 | #define FIBMAP _IO(0x00,1) /* bmap access */ |
| 218 | #define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ | 218 | #define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ |
| 219 | 219 | ||
| 220 | #define FS_IOC_GETFLAGS _IOR('f', 1, long) | ||
| 221 | #define FS_IOC_SETFLAGS _IOW('f', 2, long) | ||
| 222 | #define FS_IOC_GETVERSION _IOR('v', 1, long) | ||
| 223 | #define FS_IOC_SETVERSION _IOW('v', 2, long) | ||
| 224 | #define FS_IOC32_GETFLAGS _IOR('f', 1, int) | ||
| 225 | #define FS_IOC32_SETFLAGS _IOW('f', 2, int) | ||
| 226 | #define FS_IOC32_GETVERSION _IOR('v', 1, int) | ||
| 227 | #define FS_IOC32_SETVERSION _IOW('v', 2, int) | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS) | ||
| 231 | */ | ||
| 232 | #define FS_SECRM_FL 0x00000001 /* Secure deletion */ | ||
| 233 | #define FS_UNRM_FL 0x00000002 /* Undelete */ | ||
| 234 | #define FS_COMPR_FL 0x00000004 /* Compress file */ | ||
| 235 | #define FS_SYNC_FL 0x00000008 /* Synchronous updates */ | ||
| 236 | #define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */ | ||
| 237 | #define FS_APPEND_FL 0x00000020 /* writes to file may only append */ | ||
| 238 | #define FS_NODUMP_FL 0x00000040 /* do not dump file */ | ||
| 239 | #define FS_NOATIME_FL 0x00000080 /* do not update atime */ | ||
| 240 | /* Reserved for compression usage... */ | ||
| 241 | #define FS_DIRTY_FL 0x00000100 | ||
| 242 | #define FS_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ | ||
| 243 | #define FS_NOCOMP_FL 0x00000400 /* Don't compress */ | ||
| 244 | #define FS_ECOMPR_FL 0x00000800 /* Compression error */ | ||
| 245 | /* End compression flags --- maybe not all used */ | ||
| 246 | #define FS_BTREE_FL 0x00001000 /* btree format dir */ | ||
| 247 | #define FS_INDEX_FL 0x00001000 /* hash-indexed directory */ | ||
| 248 | #define FS_IMAGIC_FL 0x00002000 /* AFS directory */ | ||
| 249 | #define FS_JOURNAL_DATA_FL 0x00004000 /* Reserved for ext3 */ | ||
| 250 | #define FS_NOTAIL_FL 0x00008000 /* file tail should not be merged */ | ||
| 251 | #define FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ | ||
| 252 | #define FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ | ||
| 253 | #define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ | ||
| 254 | |||
| 255 | #define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ | ||
| 256 | #define FS_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ | ||
| 257 | |||
| 258 | |||
| 220 | #define SYNC_FILE_RANGE_WAIT_BEFORE 1 | 259 | #define SYNC_FILE_RANGE_WAIT_BEFORE 1 |
| 221 | #define SYNC_FILE_RANGE_WRITE 2 | 260 | #define SYNC_FILE_RANGE_WRITE 2 |
| 222 | #define SYNC_FILE_RANGE_WAIT_AFTER 4 | 261 | #define SYNC_FILE_RANGE_WAIT_AFTER 4 |
| @@ -1443,6 +1482,7 @@ extern void __init vfs_caches_init(unsigned long); | |||
| 1443 | extern void putname(const char *name); | 1482 | extern void putname(const char *name); |
| 1444 | #endif | 1483 | #endif |
| 1445 | 1484 | ||
| 1485 | #ifdef CONFIG_BLOCK | ||
| 1446 | extern int register_blkdev(unsigned int, const char *); | 1486 | extern int register_blkdev(unsigned int, const char *); |
| 1447 | extern int unregister_blkdev(unsigned int, const char *); | 1487 | extern int unregister_blkdev(unsigned int, const char *); |
| 1448 | extern struct block_device *bdget(dev_t); | 1488 | extern struct block_device *bdget(dev_t); |
| @@ -1451,11 +1491,15 @@ extern void bd_forget(struct inode *inode); | |||
| 1451 | extern void bdput(struct block_device *); | 1491 | extern void bdput(struct block_device *); |
| 1452 | extern struct block_device *open_by_devnum(dev_t, unsigned); | 1492 | extern struct block_device *open_by_devnum(dev_t, unsigned); |
| 1453 | extern struct block_device *open_partition_by_devnum(dev_t, unsigned); | 1493 | extern struct block_device *open_partition_by_devnum(dev_t, unsigned); |
| 1454 | extern const struct file_operations def_blk_fops; | ||
| 1455 | extern const struct address_space_operations def_blk_aops; | 1494 | extern const struct address_space_operations def_blk_aops; |
| 1495 | #else | ||
| 1496 | static inline void bd_forget(struct inode *inode) {} | ||
| 1497 | #endif | ||
| 1498 | extern const struct file_operations def_blk_fops; | ||
| 1456 | extern const struct file_operations def_chr_fops; | 1499 | extern const struct file_operations def_chr_fops; |
| 1457 | extern const struct file_operations bad_sock_fops; | 1500 | extern const struct file_operations bad_sock_fops; |
| 1458 | extern const struct file_operations def_fifo_fops; | 1501 | extern const struct file_operations def_fifo_fops; |
| 1502 | #ifdef CONFIG_BLOCK | ||
| 1459 | extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); | 1503 | extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); |
| 1460 | extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); | 1504 | extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); |
| 1461 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); | 1505 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); |
| @@ -1471,6 +1515,7 @@ extern void bd_release_from_disk(struct block_device *, struct gendisk *); | |||
| 1471 | #define bd_claim_by_disk(bdev, holder, disk) bd_claim(bdev, holder) | 1515 | #define bd_claim_by_disk(bdev, holder, disk) bd_claim(bdev, holder) |
| 1472 | #define bd_release_from_disk(bdev, disk) bd_release(bdev) | 1516 | #define bd_release_from_disk(bdev, disk) bd_release(bdev) |
| 1473 | #endif | 1517 | #endif |
| 1518 | #endif | ||
| 1474 | 1519 | ||
| 1475 | /* fs/char_dev.c */ | 1520 | /* fs/char_dev.c */ |
| 1476 | #define CHRDEV_MAJOR_HASH_SIZE 255 | 1521 | #define CHRDEV_MAJOR_HASH_SIZE 255 |
| @@ -1484,14 +1529,19 @@ extern int chrdev_open(struct inode *, struct file *); | |||
| 1484 | extern void chrdev_show(struct seq_file *,off_t); | 1529 | extern void chrdev_show(struct seq_file *,off_t); |
| 1485 | 1530 | ||
| 1486 | /* fs/block_dev.c */ | 1531 | /* fs/block_dev.c */ |
| 1487 | #define BLKDEV_MAJOR_HASH_SIZE 255 | ||
| 1488 | #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ | 1532 | #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ |
| 1533 | |||
| 1534 | #ifdef CONFIG_BLOCK | ||
| 1535 | #define BLKDEV_MAJOR_HASH_SIZE 255 | ||
| 1489 | extern const char *__bdevname(dev_t, char *buffer); | 1536 | extern const char *__bdevname(dev_t, char *buffer); |
| 1490 | extern const char *bdevname(struct block_device *bdev, char *buffer); | 1537 | extern const char *bdevname(struct block_device *bdev, char *buffer); |
| 1491 | extern struct block_device *lookup_bdev(const char *); | 1538 | extern struct block_device *lookup_bdev(const char *); |
| 1492 | extern struct block_device *open_bdev_excl(const char *, int, void *); | 1539 | extern struct block_device *open_bdev_excl(const char *, int, void *); |
| 1493 | extern void close_bdev_excl(struct block_device *); | 1540 | extern void close_bdev_excl(struct block_device *); |
| 1494 | extern void blkdev_show(struct seq_file *,off_t); | 1541 | extern void blkdev_show(struct seq_file *,off_t); |
| 1542 | #else | ||
| 1543 | #define BLKDEV_MAJOR_HASH_SIZE 0 | ||
| 1544 | #endif | ||
| 1495 | 1545 | ||
| 1496 | extern void init_special_inode(struct inode *, umode_t, dev_t); | 1546 | extern void init_special_inode(struct inode *, umode_t, dev_t); |
| 1497 | 1547 | ||
| @@ -1505,6 +1555,7 @@ extern const struct file_operations rdwr_fifo_fops; | |||
| 1505 | 1555 | ||
| 1506 | extern int fs_may_remount_ro(struct super_block *); | 1556 | extern int fs_may_remount_ro(struct super_block *); |
| 1507 | 1557 | ||
| 1558 | #ifdef CONFIG_BLOCK | ||
| 1508 | /* | 1559 | /* |
| 1509 | * return READ, READA, or WRITE | 1560 | * return READ, READA, or WRITE |
| 1510 | */ | 1561 | */ |
| @@ -1516,9 +1567,10 @@ extern int fs_may_remount_ro(struct super_block *); | |||
| 1516 | #define bio_data_dir(bio) ((bio)->bi_rw & 1) | 1567 | #define bio_data_dir(bio) ((bio)->bi_rw & 1) |
| 1517 | 1568 | ||
| 1518 | extern int check_disk_change(struct block_device *); | 1569 | extern int check_disk_change(struct block_device *); |
| 1519 | extern int invalidate_inodes(struct super_block *); | ||
| 1520 | extern int __invalidate_device(struct block_device *); | 1570 | extern int __invalidate_device(struct block_device *); |
| 1521 | extern int invalidate_partition(struct gendisk *, int); | 1571 | extern int invalidate_partition(struct gendisk *, int); |
| 1572 | #endif | ||
| 1573 | extern int invalidate_inodes(struct super_block *); | ||
| 1522 | unsigned long invalidate_mapping_pages(struct address_space *mapping, | 1574 | unsigned long invalidate_mapping_pages(struct address_space *mapping, |
| 1523 | pgoff_t start, pgoff_t end); | 1575 | pgoff_t start, pgoff_t end); |
| 1524 | unsigned long invalidate_inode_pages(struct address_space *mapping); | 1576 | unsigned long invalidate_inode_pages(struct address_space *mapping); |
| @@ -1546,11 +1598,14 @@ extern int __filemap_fdatawrite_range(struct address_space *mapping, | |||
| 1546 | extern long do_fsync(struct file *file, int datasync); | 1598 | extern long do_fsync(struct file *file, int datasync); |
| 1547 | extern void sync_supers(void); | 1599 | extern void sync_supers(void); |
| 1548 | extern void sync_filesystems(int wait); | 1600 | extern void sync_filesystems(int wait); |
| 1601 | extern void __fsync_super(struct super_block *sb); | ||
| 1549 | extern void emergency_sync(void); | 1602 | extern void emergency_sync(void); |
| 1550 | extern void emergency_remount(void); | 1603 | extern void emergency_remount(void); |
| 1551 | extern int do_remount_sb(struct super_block *sb, int flags, | 1604 | extern int do_remount_sb(struct super_block *sb, int flags, |
| 1552 | void *data, int force); | 1605 | void *data, int force); |
| 1606 | #ifdef CONFIG_BLOCK | ||
| 1553 | extern sector_t bmap(struct inode *, sector_t); | 1607 | extern sector_t bmap(struct inode *, sector_t); |
| 1608 | #endif | ||
| 1554 | extern int notify_change(struct dentry *, struct iattr *); | 1609 | extern int notify_change(struct dentry *, struct iattr *); |
| 1555 | extern int permission(struct inode *, int, struct nameidata *); | 1610 | extern int permission(struct inode *, int, struct nameidata *); |
| 1556 | extern int generic_permission(struct inode *, int, | 1611 | extern int generic_permission(struct inode *, int, |
| @@ -1633,9 +1688,11 @@ static inline void insert_inode_hash(struct inode *inode) { | |||
| 1633 | extern struct file * get_empty_filp(void); | 1688 | extern struct file * get_empty_filp(void); |
| 1634 | extern void file_move(struct file *f, struct list_head *list); | 1689 | extern void file_move(struct file *f, struct list_head *list); |
| 1635 | extern void file_kill(struct file *f); | 1690 | extern void file_kill(struct file *f); |
| 1691 | #ifdef CONFIG_BLOCK | ||
| 1636 | struct bio; | 1692 | struct bio; |
| 1637 | extern void submit_bio(int, struct bio *); | 1693 | extern void submit_bio(int, struct bio *); |
| 1638 | extern int bdev_read_only(struct block_device *); | 1694 | extern int bdev_read_only(struct block_device *); |
| 1695 | #endif | ||
| 1639 | extern int set_blocksize(struct block_device *, int); | 1696 | extern int set_blocksize(struct block_device *, int); |
| 1640 | extern int sb_set_blocksize(struct super_block *, int); | 1697 | extern int sb_set_blocksize(struct super_block *, int); |
| 1641 | extern int sb_min_blocksize(struct super_block *, int); | 1698 | extern int sb_min_blocksize(struct super_block *, int); |
| @@ -1716,6 +1773,7 @@ static inline void do_generic_file_read(struct file * filp, loff_t *ppos, | |||
| 1716 | actor); | 1773 | actor); |
| 1717 | } | 1774 | } |
| 1718 | 1775 | ||
| 1776 | #ifdef CONFIG_BLOCK | ||
| 1719 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | 1777 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
| 1720 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | 1778 | struct block_device *bdev, const struct iovec *iov, loff_t offset, |
| 1721 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | 1779 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, |
| @@ -1753,6 +1811,7 @@ static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb, | |||
| 1753 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, | 1811 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, |
| 1754 | nr_segs, get_block, end_io, DIO_OWN_LOCKING); | 1812 | nr_segs, get_block, end_io, DIO_OWN_LOCKING); |
| 1755 | } | 1813 | } |
| 1814 | #endif | ||
| 1756 | 1815 | ||
| 1757 | extern const struct file_operations generic_ro_fops; | 1816 | extern const struct file_operations generic_ro_fops; |
| 1758 | 1817 | ||
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index e4af57e87c17..41f276fdd185 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | 13 | ||
| 14 | #ifdef CONFIG_BLOCK | ||
| 15 | |||
| 14 | enum { | 16 | enum { |
| 15 | /* These three have identical behaviour; use the second one if DOS FDISK gets | 17 | /* These three have identical behaviour; use the second one if DOS FDISK gets |
| 16 | confused about extended/logical partitions starting past cylinder 1023. */ | 18 | confused about extended/logical partitions starting past cylinder 1023. */ |
| @@ -420,3 +422,5 @@ static inline struct block_device *bdget_disk(struct gendisk *disk, int index) | |||
| 420 | #endif | 422 | #endif |
| 421 | 423 | ||
| 422 | #endif | 424 | #endif |
| 425 | |||
| 426 | #endif | ||
diff --git a/include/linux/mm.h b/include/linux/mm.h index 7b703b6d4358..4edf1934e5ca 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -743,7 +743,9 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long | |||
| 743 | int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); | 743 | int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); |
| 744 | void print_bad_pte(struct vm_area_struct *, pte_t, unsigned long); | 744 | void print_bad_pte(struct vm_area_struct *, pte_t, unsigned long); |
| 745 | 745 | ||
| 746 | int __set_page_dirty_buffers(struct page *page); | 746 | extern int try_to_release_page(struct page * page, gfp_t gfp_mask); |
| 747 | extern void do_invalidatepage(struct page *page, unsigned long offset); | ||
| 748 | |||
| 747 | int __set_page_dirty_nobuffers(struct page *page); | 749 | int __set_page_dirty_nobuffers(struct page *page); |
| 748 | int redirty_page_for_writepage(struct writeback_control *wbc, | 750 | int redirty_page_for_writepage(struct writeback_control *wbc, |
| 749 | struct page *page); | 751 | struct page *page); |
diff --git a/include/linux/mpage.h b/include/linux/mpage.h index 3ca880463c47..cc5fb75af78a 100644 --- a/include/linux/mpage.h +++ b/include/linux/mpage.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * (And no, it doesn't do the #ifdef __MPAGE_H thing, and it doesn't do | 9 | * (And no, it doesn't do the #ifdef __MPAGE_H thing, and it doesn't do |
| 10 | * nested includes. Get it right in the .c file). | 10 | * nested includes. Get it right in the .c file). |
| 11 | */ | 11 | */ |
| 12 | #ifdef CONFIG_BLOCK | ||
| 12 | 13 | ||
| 13 | struct writeback_control; | 14 | struct writeback_control; |
| 14 | typedef int (writepage_t)(struct page *page, struct writeback_control *wbc); | 15 | typedef int (writepage_t)(struct page *page, struct writeback_control *wbc); |
| @@ -21,8 +22,4 @@ int mpage_writepages(struct address_space *mapping, | |||
| 21 | int mpage_writepage(struct page *page, get_block_t *get_block, | 22 | int mpage_writepage(struct page *page, get_block_t *get_block, |
| 22 | struct writeback_control *wbc); | 23 | struct writeback_control *wbc); |
| 23 | 24 | ||
| 24 | static inline int | 25 | #endif |
| 25 | generic_writepages(struct address_space *mapping, struct writeback_control *wbc) | ||
| 26 | { | ||
| 27 | return mpage_writepages(mapping, wbc, NULL); | ||
| 28 | } | ||
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index eb3e547c8fee..c588709acbbc 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h | |||
| @@ -53,6 +53,8 @@ | |||
| 53 | #include <linux/raid/md_u.h> | 53 | #include <linux/raid/md_u.h> |
| 54 | #include <linux/raid/md_k.h> | 54 | #include <linux/raid/md_k.h> |
| 55 | 55 | ||
| 56 | #ifdef CONFIG_MD | ||
| 57 | |||
| 56 | /* | 58 | /* |
| 57 | * Different major versions are not compatible. | 59 | * Different major versions are not compatible. |
| 58 | * Different minor versions are only downward compatible. | 60 | * Different minor versions are only downward compatible. |
| @@ -95,5 +97,6 @@ extern void md_new_event(mddev_t *mddev); | |||
| 95 | 97 | ||
| 96 | extern void md_update_sb(mddev_t * mddev); | 98 | extern void md_update_sb(mddev_t * mddev); |
| 97 | 99 | ||
| 100 | #endif /* CONFIG_MD */ | ||
| 98 | #endif | 101 | #endif |
| 99 | 102 | ||
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index d28890295852..920b94fe31fa 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | /* and dm-bio-list.h is not under include/linux because.... ??? */ | 18 | /* and dm-bio-list.h is not under include/linux because.... ??? */ |
| 19 | #include "../../../drivers/md/dm-bio-list.h" | 19 | #include "../../../drivers/md/dm-bio-list.h" |
| 20 | 20 | ||
| 21 | #ifdef CONFIG_BLOCK | ||
| 22 | |||
| 21 | #define LEVEL_MULTIPATH (-4) | 23 | #define LEVEL_MULTIPATH (-4) |
| 22 | #define LEVEL_LINEAR (-1) | 24 | #define LEVEL_LINEAR (-1) |
| 23 | #define LEVEL_FAULTY (-5) | 25 | #define LEVEL_FAULTY (-5) |
| @@ -362,5 +364,6 @@ static inline void safe_put_page(struct page *p) | |||
| 362 | if (p) put_page(p); | 364 | if (p) put_page(p); |
| 363 | } | 365 | } |
| 364 | 366 | ||
| 367 | #endif /* CONFIG_BLOCK */ | ||
| 365 | #endif | 368 | #endif |
| 366 | 369 | ||
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 00b340ba6612..b160fb18e8d6 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h | |||
| @@ -17,5 +17,6 @@ extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma); | |||
| 17 | 17 | ||
| 18 | extern const struct file_operations ramfs_file_operations; | 18 | extern const struct file_operations ramfs_file_operations; |
| 19 | extern struct vm_operations_struct generic_file_vm_ops; | 19 | extern struct vm_operations_struct generic_file_vm_ops; |
| 20 | extern int __init init_rootfs(void); | ||
| 20 | 21 | ||
| 21 | #endif | 22 | #endif |
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 8d5382e62c08..344bc3495ddb 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h | |||
| @@ -133,7 +133,7 @@ static inline void rb_set_color(struct rb_node *rb, int color) | |||
| 133 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) | 133 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) |
| 134 | 134 | ||
| 135 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) | 135 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) |
| 136 | #define RB_EMPTY_NODE(node) (rb_parent(node) != node) | 136 | #define RB_EMPTY_NODE(node) (rb_parent(node) == node) |
| 137 | #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) | 137 | #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) |
| 138 | 138 | ||
| 139 | extern void rb_insert_color(struct rb_node *, struct rb_root *); | 139 | extern void rb_insert_color(struct rb_node *, struct rb_root *); |
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 28493ffaafe7..9c63abffd7b2 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h | |||
| @@ -807,21 +807,19 @@ struct stat_data_v1 { | |||
| 807 | #define set_sd_v1_first_direct_byte(sdp,v) \ | 807 | #define set_sd_v1_first_direct_byte(sdp,v) \ |
| 808 | ((sdp)->sd_first_direct_byte = cpu_to_le32(v)) | 808 | ((sdp)->sd_first_direct_byte = cpu_to_le32(v)) |
| 809 | 809 | ||
| 810 | #include <linux/ext2_fs.h> | ||
| 811 | |||
| 812 | /* inode flags stored in sd_attrs (nee sd_reserved) */ | 810 | /* inode flags stored in sd_attrs (nee sd_reserved) */ |
| 813 | 811 | ||
| 814 | /* we want common flags to have the same values as in ext2, | 812 | /* we want common flags to have the same values as in ext2, |
| 815 | so chattr(1) will work without problems */ | 813 | so chattr(1) will work without problems */ |
| 816 | #define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL | 814 | #define REISERFS_IMMUTABLE_FL FS_IMMUTABLE_FL |
| 817 | #define REISERFS_APPEND_FL EXT2_APPEND_FL | 815 | #define REISERFS_APPEND_FL FS_APPEND_FL |
| 818 | #define REISERFS_SYNC_FL EXT2_SYNC_FL | 816 | #define REISERFS_SYNC_FL FS_SYNC_FL |
| 819 | #define REISERFS_NOATIME_FL EXT2_NOATIME_FL | 817 | #define REISERFS_NOATIME_FL FS_NOATIME_FL |
| 820 | #define REISERFS_NODUMP_FL EXT2_NODUMP_FL | 818 | #define REISERFS_NODUMP_FL FS_NODUMP_FL |
| 821 | #define REISERFS_SECRM_FL EXT2_SECRM_FL | 819 | #define REISERFS_SECRM_FL FS_SECRM_FL |
| 822 | #define REISERFS_UNRM_FL EXT2_UNRM_FL | 820 | #define REISERFS_UNRM_FL FS_UNRM_FL |
| 823 | #define REISERFS_COMPR_FL EXT2_COMPR_FL | 821 | #define REISERFS_COMPR_FL FS_COMPR_FL |
| 824 | #define REISERFS_NOTAIL_FL EXT2_NOTAIL_FL | 822 | #define REISERFS_NOTAIL_FL FS_NOTAIL_FL |
| 825 | 823 | ||
| 826 | /* persistent flags that file inherits from the parent directory */ | 824 | /* persistent flags that file inherits from the parent directory */ |
| 827 | #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL | \ | 825 | #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL | \ |
| @@ -2163,15 +2161,24 @@ __u32 r5_hash(const signed char *msg, int len); | |||
| 2163 | /* prototypes from ioctl.c */ | 2161 | /* prototypes from ioctl.c */ |
| 2164 | int reiserfs_ioctl(struct inode *inode, struct file *filp, | 2162 | int reiserfs_ioctl(struct inode *inode, struct file *filp, |
| 2165 | unsigned int cmd, unsigned long arg); | 2163 | unsigned int cmd, unsigned long arg); |
| 2164 | long reiserfs_compat_ioctl(struct file *filp, | ||
| 2165 | unsigned int cmd, unsigned long arg); | ||
| 2166 | 2166 | ||
| 2167 | /* ioctl's command */ | 2167 | /* ioctl's command */ |
| 2168 | #define REISERFS_IOC_UNPACK _IOW(0xCD,1,long) | 2168 | #define REISERFS_IOC_UNPACK _IOW(0xCD,1,long) |
| 2169 | /* define following flags to be the same as in ext2, so that chattr(1), | 2169 | /* define following flags to be the same as in ext2, so that chattr(1), |
| 2170 | lsattr(1) will work with us. */ | 2170 | lsattr(1) will work with us. */ |
| 2171 | #define REISERFS_IOC_GETFLAGS EXT2_IOC_GETFLAGS | 2171 | #define REISERFS_IOC_GETFLAGS FS_IOC_GETFLAGS |
| 2172 | #define REISERFS_IOC_SETFLAGS EXT2_IOC_SETFLAGS | 2172 | #define REISERFS_IOC_SETFLAGS FS_IOC_SETFLAGS |
| 2173 | #define REISERFS_IOC_GETVERSION EXT2_IOC_GETVERSION | 2173 | #define REISERFS_IOC_GETVERSION FS_IOC_GETVERSION |
| 2174 | #define REISERFS_IOC_SETVERSION EXT2_IOC_SETVERSION | 2174 | #define REISERFS_IOC_SETVERSION FS_IOC_SETVERSION |
| 2175 | |||
| 2176 | /* the 32 bit compat definitions with int argument */ | ||
| 2177 | #define REISERFS_IOC32_UNPACK _IOW(0xCD, 1, int) | ||
| 2178 | #define REISERFS_IOC32_GETFLAGS FS_IOC32_GETFLAGS | ||
| 2179 | #define REISERFS_IOC32_SETFLAGS FS_IOC32_SETFLAGS | ||
| 2180 | #define REISERFS_IOC32_GETVERSION FS_IOC32_GETVERSION | ||
| 2181 | #define REISERFS_IOC32_SETVERSION FS_IOC32_SETVERSION | ||
| 2175 | 2182 | ||
| 2176 | /* Locking primitives */ | 2183 | /* Locking primitives */ |
| 2177 | /* Right now we are still falling back to (un)lock_kernel, but eventually that | 2184 | /* Right now we are still falling back to (un)lock_kernel, but eventually that |
diff --git a/include/linux/sched.h b/include/linux/sched.h index a06fc89cf6e5..fc4a9873ec10 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -710,7 +710,6 @@ extern unsigned int max_cache_size; | |||
| 710 | 710 | ||
| 711 | 711 | ||
| 712 | struct io_context; /* See blkdev.h */ | 712 | struct io_context; /* See blkdev.h */ |
| 713 | void exit_io_context(void); | ||
| 714 | struct cpuset; | 713 | struct cpuset; |
| 715 | 714 | ||
| 716 | #define NGROUPS_SMALL 32 | 715 | #define NGROUPS_SMALL 32 |
diff --git a/include/linux/tty.h b/include/linux/tty.h index ea4c2605f8da..44091c0db0b4 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -307,6 +307,9 @@ extern void tty_ldisc_put(int); | |||
| 307 | extern void tty_wakeup(struct tty_struct *tty); | 307 | extern void tty_wakeup(struct tty_struct *tty); |
| 308 | extern void tty_ldisc_flush(struct tty_struct *tty); | 308 | extern void tty_ldisc_flush(struct tty_struct *tty); |
| 309 | 309 | ||
| 310 | extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
| 311 | unsigned long arg); | ||
| 312 | |||
| 310 | extern struct mutex tty_mutex; | 313 | extern struct mutex tty_mutex; |
| 311 | 314 | ||
| 312 | /* n_tty.c */ | 315 | /* n_tty.c */ |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 9d4074ecd0cd..4f4d98addb44 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
| @@ -111,6 +111,8 @@ balance_dirty_pages_ratelimited(struct address_space *mapping) | |||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); | 113 | int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); |
| 114 | extern int generic_writepages(struct address_space *mapping, | ||
| 115 | struct writeback_control *wbc); | ||
| 114 | int do_writepages(struct address_space *mapping, struct writeback_control *wbc); | 116 | int do_writepages(struct address_space *mapping, struct writeback_control *wbc); |
| 115 | int sync_page_range(struct inode *inode, struct address_space *mapping, | 117 | int sync_page_range(struct inode *inode, struct address_space *mapping, |
| 116 | loff_t pos, loff_t count); | 118 | loff_t pos, loff_t count); |
diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h index d04d05adfa9b..c247a28259bc 100644 --- a/include/scsi/scsi_tcq.h +++ b/include/scsi/scsi_tcq.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include <scsi/scsi_device.h> | 6 | #include <scsi/scsi_device.h> |
| 7 | #include <scsi/scsi_host.h> | 7 | #include <scsi/scsi_host.h> |
| 8 | 8 | ||
| 9 | |||
| 10 | #define MSG_SIMPLE_TAG 0x20 | 9 | #define MSG_SIMPLE_TAG 0x20 |
| 11 | #define MSG_HEAD_TAG 0x21 | 10 | #define MSG_HEAD_TAG 0x21 |
| 12 | #define MSG_ORDERED_TAG 0x22 | 11 | #define MSG_ORDERED_TAG 0x22 |
| @@ -14,6 +13,7 @@ | |||
| 14 | #define SCSI_NO_TAG (-1) /* identify no tag in use */ | 13 | #define SCSI_NO_TAG (-1) /* identify no tag in use */ |
| 15 | 14 | ||
| 16 | 15 | ||
| 16 | #ifdef CONFIG_BLOCK | ||
| 17 | 17 | ||
| 18 | /** | 18 | /** |
| 19 | * scsi_get_tag_type - get the type of tag the device supports | 19 | * scsi_get_tag_type - get the type of tag the device supports |
| @@ -100,7 +100,7 @@ static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg) | |||
| 100 | struct scsi_device *sdev = cmd->device; | 100 | struct scsi_device *sdev = cmd->device; |
| 101 | 101 | ||
| 102 | if (blk_rq_tagged(req)) { | 102 | if (blk_rq_tagged(req)) { |
| 103 | if (sdev->ordered_tags && req->flags & REQ_HARDBARRIER) | 103 | if (sdev->ordered_tags && req->cmd_flags & REQ_HARDBARRIER) |
| 104 | *msg++ = MSG_ORDERED_TAG; | 104 | *msg++ = MSG_ORDERED_TAG; |
| 105 | else | 105 | else |
| 106 | *msg++ = MSG_SIMPLE_TAG; | 106 | *msg++ = MSG_SIMPLE_TAG; |
| @@ -144,4 +144,5 @@ static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth) | |||
| 144 | return shost->bqt ? 0 : -ENOMEM; | 144 | return shost->bqt ? 0 : -ENOMEM; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | #endif /* CONFIG_BLOCK */ | ||
| 147 | #endif /* _SCSI_SCSI_TCQ_H */ | 148 | #endif /* _SCSI_SCSI_TCQ_H */ |
diff --git a/init/Kconfig b/init/Kconfig index 4381006dd666..d2eb7a84a264 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
| @@ -92,7 +92,7 @@ config LOCALVERSION_AUTO | |||
| 92 | 92 | ||
| 93 | config SWAP | 93 | config SWAP |
| 94 | bool "Support for paging of anonymous memory (swap)" | 94 | bool "Support for paging of anonymous memory (swap)" |
| 95 | depends on MMU | 95 | depends on MMU && BLOCK |
| 96 | default y | 96 | default y |
| 97 | help | 97 | help |
| 98 | This option allows you to choose whether you want to have support | 98 | This option allows you to choose whether you want to have support |
diff --git a/init/do_mounts.c b/init/do_mounts.c index b290aadb1d3f..dc1ec0803ef9 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
| @@ -285,7 +285,11 @@ void __init mount_block_root(char *name, int flags) | |||
| 285 | { | 285 | { |
| 286 | char *fs_names = __getname(); | 286 | char *fs_names = __getname(); |
| 287 | char *p; | 287 | char *p; |
| 288 | #ifdef CONFIG_BLOCK | ||
| 288 | char b[BDEVNAME_SIZE]; | 289 | char b[BDEVNAME_SIZE]; |
| 290 | #else | ||
| 291 | const char *b = name; | ||
| 292 | #endif | ||
| 289 | 293 | ||
| 290 | get_fs_names(fs_names); | 294 | get_fs_names(fs_names); |
| 291 | retry: | 295 | retry: |
| @@ -304,7 +308,9 @@ retry: | |||
| 304 | * Allow the user to distinguish between failed sys_open | 308 | * Allow the user to distinguish between failed sys_open |
| 305 | * and bad superblock on root device. | 309 | * and bad superblock on root device. |
| 306 | */ | 310 | */ |
| 311 | #ifdef CONFIG_BLOCK | ||
| 307 | __bdevname(ROOT_DEV, b); | 312 | __bdevname(ROOT_DEV, b); |
| 313 | #endif | ||
| 308 | printk("VFS: Cannot open root device \"%s\" or %s\n", | 314 | printk("VFS: Cannot open root device \"%s\" or %s\n", |
| 309 | root_device_name, b); | 315 | root_device_name, b); |
| 310 | printk("Please append a correct \"root=\" boot option\n"); | 316 | printk("Please append a correct \"root=\" boot option\n"); |
| @@ -316,7 +322,10 @@ retry: | |||
| 316 | for (p = fs_names; *p; p += strlen(p)+1) | 322 | for (p = fs_names; *p; p += strlen(p)+1) |
| 317 | printk(" %s", p); | 323 | printk(" %s", p); |
| 318 | printk("\n"); | 324 | printk("\n"); |
| 319 | panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b)); | 325 | #ifdef CONFIG_BLOCK |
| 326 | __bdevname(ROOT_DEV, b); | ||
| 327 | #endif | ||
| 328 | panic("VFS: Unable to mount root fs on %s", b); | ||
| 320 | out: | 329 | out: |
| 321 | putname(fs_names); | 330 | putname(fs_names); |
| 322 | } | 331 | } |
| @@ -387,8 +396,10 @@ void __init mount_root(void) | |||
| 387 | change_floppy("root floppy"); | 396 | change_floppy("root floppy"); |
| 388 | } | 397 | } |
| 389 | #endif | 398 | #endif |
| 399 | #ifdef CONFIG_BLOCK | ||
| 390 | create_dev("/dev/root", ROOT_DEV); | 400 | create_dev("/dev/root", ROOT_DEV); |
| 391 | mount_block_root("/dev/root", root_mountflags); | 401 | mount_block_root("/dev/root", root_mountflags); |
| 402 | #endif | ||
| 392 | } | 403 | } |
| 393 | 404 | ||
| 394 | /* | 405 | /* |
diff --git a/kernel/compat.c b/kernel/compat.c index 75573e5d27b0..b4fbd838cd77 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | 26 | ||
| 27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 28 | 28 | ||
| 29 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | ||
| 30 | |||
| 29 | int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) | 31 | int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) |
| 30 | { | 32 | { |
| 31 | return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || | 33 | return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || |
diff --git a/kernel/exit.c b/kernel/exit.c index 2e4c13cba95a..c189de2927ab 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/pipe_fs_i.h> | 38 | #include <linux/pipe_fs_i.h> |
| 39 | #include <linux/audit.h> /* for audit_free() */ | 39 | #include <linux/audit.h> /* for audit_free() */ |
| 40 | #include <linux/resource.h> | 40 | #include <linux/resource.h> |
| 41 | #include <linux/blkdev.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
| 43 | #include <asm/unistd.h> | 44 | #include <asm/unistd.h> |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 6991bece67e8..7a3b2e75f040 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -134,3 +134,8 @@ cond_syscall(sys_madvise); | |||
| 134 | cond_syscall(sys_mremap); | 134 | cond_syscall(sys_mremap); |
| 135 | cond_syscall(sys_remap_file_pages); | 135 | cond_syscall(sys_remap_file_pages); |
| 136 | cond_syscall(compat_sys_move_pages); | 136 | cond_syscall(compat_sys_move_pages); |
| 137 | |||
| 138 | /* block-layer dependent */ | ||
| 139 | cond_syscall(sys_bdflush); | ||
| 140 | cond_syscall(sys_ioprio_set); | ||
| 141 | cond_syscall(sys_ioprio_get); | ||
diff --git a/lib/rbtree.c b/lib/rbtree.c index 1e55ba1c2edf..48499c2d88cc 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c | |||
| @@ -322,6 +322,9 @@ struct rb_node *rb_next(struct rb_node *node) | |||
| 322 | { | 322 | { |
| 323 | struct rb_node *parent; | 323 | struct rb_node *parent; |
| 324 | 324 | ||
| 325 | if (rb_parent(node) == node) | ||
| 326 | return NULL; | ||
| 327 | |||
| 325 | /* If we have a right-hand child, go down and then left as far | 328 | /* If we have a right-hand child, go down and then left as far |
| 326 | as we can. */ | 329 | as we can. */ |
| 327 | if (node->rb_right) { | 330 | if (node->rb_right) { |
| @@ -348,6 +351,9 @@ struct rb_node *rb_prev(struct rb_node *node) | |||
| 348 | { | 351 | { |
| 349 | struct rb_node *parent; | 352 | struct rb_node *parent; |
| 350 | 353 | ||
| 354 | if (rb_parent(node) == node) | ||
| 355 | return NULL; | ||
| 356 | |||
| 351 | /* If we have a left-hand child, go down and then right as far | 357 | /* If we have a left-hand child, go down and then right as far |
| 352 | as we can. */ | 358 | as we can. */ |
| 353 | if (node->rb_left) { | 359 | if (node->rb_left) { |
diff --git a/mm/Makefile b/mm/Makefile index 6200c6d6afd2..12b3a4eee88d 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
| @@ -12,6 +12,9 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ | |||
| 12 | readahead.o swap.o truncate.o vmscan.o \ | 12 | readahead.o swap.o truncate.o vmscan.o \ |
| 13 | prio_tree.o util.o mmzone.o vmstat.o $(mmu-y) | 13 | prio_tree.o util.o mmzone.o vmstat.o $(mmu-y) |
| 14 | 14 | ||
| 15 | ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy) | ||
| 16 | obj-y += bounce.o | ||
| 17 | endif | ||
| 15 | obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o | 18 | obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o |
| 16 | obj-$(CONFIG_HUGETLBFS) += hugetlb.o | 19 | obj-$(CONFIG_HUGETLBFS) += hugetlb.o |
| 17 | obj-$(CONFIG_NUMA) += mempolicy.o | 20 | obj-$(CONFIG_NUMA) += mempolicy.o |
diff --git a/mm/bounce.c b/mm/bounce.c new file mode 100644 index 000000000000..e4b62d2a4024 --- /dev/null +++ b/mm/bounce.c | |||
| @@ -0,0 +1,302 @@ | |||
| 1 | /* bounce buffer handling for block devices | ||
| 2 | * | ||
| 3 | * - Split from highmem.c | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/mm.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/swap.h> | ||
| 9 | #include <linux/bio.h> | ||
| 10 | #include <linux/pagemap.h> | ||
| 11 | #include <linux/mempool.h> | ||
| 12 | #include <linux/blkdev.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/hash.h> | ||
| 15 | #include <linux/highmem.h> | ||
| 16 | #include <linux/blktrace_api.h> | ||
| 17 | #include <asm/tlbflush.h> | ||
| 18 | |||
| 19 | #define POOL_SIZE 64 | ||
| 20 | #define ISA_POOL_SIZE 16 | ||
| 21 | |||
| 22 | static mempool_t *page_pool, *isa_page_pool; | ||
| 23 | |||
| 24 | #ifdef CONFIG_HIGHMEM | ||
| 25 | static __init int init_emergency_pool(void) | ||
| 26 | { | ||
| 27 | struct sysinfo i; | ||
| 28 | si_meminfo(&i); | ||
| 29 | si_swapinfo(&i); | ||
| 30 | |||
| 31 | if (!i.totalhigh) | ||
| 32 | return 0; | ||
| 33 | |||
| 34 | page_pool = mempool_create_page_pool(POOL_SIZE, 0); | ||
| 35 | BUG_ON(!page_pool); | ||
| 36 | printk("highmem bounce pool size: %d pages\n", POOL_SIZE); | ||
| 37 | |||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | __initcall(init_emergency_pool); | ||
| 42 | |||
| 43 | /* | ||
| 44 | * highmem version, map in to vec | ||
| 45 | */ | ||
| 46 | static void bounce_copy_vec(struct bio_vec *to, unsigned char *vfrom) | ||
| 47 | { | ||
| 48 | unsigned long flags; | ||
| 49 | unsigned char *vto; | ||
| 50 | |||
| 51 | local_irq_save(flags); | ||
| 52 | vto = kmap_atomic(to->bv_page, KM_BOUNCE_READ); | ||
| 53 | memcpy(vto + to->bv_offset, vfrom, to->bv_len); | ||
| 54 | kunmap_atomic(vto, KM_BOUNCE_READ); | ||
| 55 | local_irq_restore(flags); | ||
| 56 | } | ||
| 57 | |||
| 58 | #else /* CONFIG_HIGHMEM */ | ||
| 59 | |||
| 60 | #define bounce_copy_vec(to, vfrom) \ | ||
| 61 | memcpy(page_address((to)->bv_page) + (to)->bv_offset, vfrom, (to)->bv_len) | ||
| 62 | |||
| 63 | #endif /* CONFIG_HIGHMEM */ | ||
| 64 | |||
| 65 | /* | ||
| 66 | * allocate pages in the DMA region for the ISA pool | ||
| 67 | */ | ||
| 68 | static void *mempool_alloc_pages_isa(gfp_t gfp_mask, void *data) | ||
| 69 | { | ||
| 70 | return mempool_alloc_pages(gfp_mask | GFP_DMA, data); | ||
| 71 | } | ||
| 72 | |||
| 73 | /* | ||
| 74 | * gets called "every" time someone init's a queue with BLK_BOUNCE_ISA | ||
| 75 | * as the max address, so check if the pool has already been created. | ||
| 76 | */ | ||
| 77 | int init_emergency_isa_pool(void) | ||
| 78 | { | ||
| 79 | if (isa_page_pool) | ||
| 80 | return 0; | ||
| 81 | |||
| 82 | isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa, | ||
| 83 | mempool_free_pages, (void *) 0); | ||
| 84 | BUG_ON(!isa_page_pool); | ||
| 85 | |||
| 86 | printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE); | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Simple bounce buffer support for highmem pages. Depending on the | ||
| 92 | * queue gfp mask set, *to may or may not be a highmem page. kmap it | ||
| 93 | * always, it will do the Right Thing | ||
| 94 | */ | ||
| 95 | static void copy_to_high_bio_irq(struct bio *to, struct bio *from) | ||
| 96 | { | ||
| 97 | unsigned char *vfrom; | ||
| 98 | struct bio_vec *tovec, *fromvec; | ||
| 99 | int i; | ||
| 100 | |||
| 101 | __bio_for_each_segment(tovec, to, i, 0) { | ||
| 102 | fromvec = from->bi_io_vec + i; | ||
| 103 | |||
| 104 | /* | ||
| 105 | * not bounced | ||
| 106 | */ | ||
| 107 | if (tovec->bv_page == fromvec->bv_page) | ||
| 108 | continue; | ||
| 109 | |||
| 110 | /* | ||
| 111 | * fromvec->bv_offset and fromvec->bv_len might have been | ||
| 112 | * modified by the block layer, so use the original copy, | ||
| 113 | * bounce_copy_vec already uses tovec->bv_len | ||
| 114 | */ | ||
| 115 | vfrom = page_address(fromvec->bv_page) + tovec->bv_offset; | ||
| 116 | |||
| 117 | flush_dcache_page(tovec->bv_page); | ||
| 118 | bounce_copy_vec(tovec, vfrom); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) | ||
| 123 | { | ||
| 124 | struct bio *bio_orig = bio->bi_private; | ||
| 125 | struct bio_vec *bvec, *org_vec; | ||
| 126 | int i; | ||
| 127 | |||
| 128 | if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags)) | ||
| 129 | set_bit(BIO_EOPNOTSUPP, &bio_orig->bi_flags); | ||
| 130 | |||
| 131 | /* | ||
| 132 | * free up bounce indirect pages used | ||
| 133 | */ | ||
| 134 | __bio_for_each_segment(bvec, bio, i, 0) { | ||
| 135 | org_vec = bio_orig->bi_io_vec + i; | ||
| 136 | if (bvec->bv_page == org_vec->bv_page) | ||
| 137 | continue; | ||
| 138 | |||
| 139 | dec_zone_page_state(bvec->bv_page, NR_BOUNCE); | ||
| 140 | mempool_free(bvec->bv_page, pool); | ||
| 141 | } | ||
| 142 | |||
| 143 | bio_endio(bio_orig, bio_orig->bi_size, err); | ||
| 144 | bio_put(bio); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err) | ||
| 148 | { | ||
| 149 | if (bio->bi_size) | ||
| 150 | return 1; | ||
| 151 | |||
| 152 | bounce_end_io(bio, page_pool, err); | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int bounce_end_io_write_isa(struct bio *bio, unsigned int bytes_done, int err) | ||
| 157 | { | ||
| 158 | if (bio->bi_size) | ||
| 159 | return 1; | ||
| 160 | |||
| 161 | bounce_end_io(bio, isa_page_pool, err); | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err) | ||
| 166 | { | ||
| 167 | struct bio *bio_orig = bio->bi_private; | ||
| 168 | |||
| 169 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) | ||
| 170 | copy_to_high_bio_irq(bio_orig, bio); | ||
| 171 | |||
| 172 | bounce_end_io(bio, pool, err); | ||
| 173 | } | ||
| 174 | |||
| 175 | static int bounce_end_io_read(struct bio *bio, unsigned int bytes_done, int err) | ||
| 176 | { | ||
| 177 | if (bio->bi_size) | ||
| 178 | return 1; | ||
| 179 | |||
| 180 | __bounce_end_io_read(bio, page_pool, err); | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int err) | ||
| 185 | { | ||
| 186 | if (bio->bi_size) | ||
| 187 | return 1; | ||
| 188 | |||
| 189 | __bounce_end_io_read(bio, isa_page_pool, err); | ||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, | ||
| 194 | mempool_t *pool) | ||
| 195 | { | ||
| 196 | struct page *page; | ||
| 197 | struct bio *bio = NULL; | ||
| 198 | int i, rw = bio_data_dir(*bio_orig); | ||
| 199 | struct bio_vec *to, *from; | ||
| 200 | |||
| 201 | bio_for_each_segment(from, *bio_orig, i) { | ||
| 202 | page = from->bv_page; | ||
| 203 | |||
| 204 | /* | ||
| 205 | * is destination page below bounce pfn? | ||
| 206 | */ | ||
| 207 | if (page_to_pfn(page) < q->bounce_pfn) | ||
| 208 | continue; | ||
| 209 | |||
| 210 | /* | ||
| 211 | * irk, bounce it | ||
| 212 | */ | ||
| 213 | if (!bio) | ||
| 214 | bio = bio_alloc(GFP_NOIO, (*bio_orig)->bi_vcnt); | ||
| 215 | |||
| 216 | to = bio->bi_io_vec + i; | ||
| 217 | |||
| 218 | to->bv_page = mempool_alloc(pool, q->bounce_gfp); | ||
| 219 | to->bv_len = from->bv_len; | ||
| 220 | to->bv_offset = from->bv_offset; | ||
| 221 | inc_zone_page_state(to->bv_page, NR_BOUNCE); | ||
| 222 | |||
| 223 | if (rw == WRITE) { | ||
| 224 | char *vto, *vfrom; | ||
| 225 | |||
| 226 | flush_dcache_page(from->bv_page); | ||
| 227 | vto = page_address(to->bv_page) + to->bv_offset; | ||
| 228 | vfrom = kmap(from->bv_page) + from->bv_offset; | ||
| 229 | memcpy(vto, vfrom, to->bv_len); | ||
| 230 | kunmap(from->bv_page); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | /* | ||
| 235 | * no pages bounced | ||
| 236 | */ | ||
| 237 | if (!bio) | ||
| 238 | return; | ||
| 239 | |||
| 240 | /* | ||
| 241 | * at least one page was bounced, fill in possible non-highmem | ||
| 242 | * pages | ||
| 243 | */ | ||
| 244 | __bio_for_each_segment(from, *bio_orig, i, 0) { | ||
| 245 | to = bio_iovec_idx(bio, i); | ||
| 246 | if (!to->bv_page) { | ||
| 247 | to->bv_page = from->bv_page; | ||
| 248 | to->bv_len = from->bv_len; | ||
| 249 | to->bv_offset = from->bv_offset; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | bio->bi_bdev = (*bio_orig)->bi_bdev; | ||
| 254 | bio->bi_flags |= (1 << BIO_BOUNCED); | ||
| 255 | bio->bi_sector = (*bio_orig)->bi_sector; | ||
| 256 | bio->bi_rw = (*bio_orig)->bi_rw; | ||
| 257 | |||
| 258 | bio->bi_vcnt = (*bio_orig)->bi_vcnt; | ||
| 259 | bio->bi_idx = (*bio_orig)->bi_idx; | ||
| 260 | bio->bi_size = (*bio_orig)->bi_size; | ||
| 261 | |||
| 262 | if (pool == page_pool) { | ||
| 263 | bio->bi_end_io = bounce_end_io_write; | ||
| 264 | if (rw == READ) | ||
| 265 | bio->bi_end_io = bounce_end_io_read; | ||
| 266 | } else { | ||
| 267 | bio->bi_end_io = bounce_end_io_write_isa; | ||
| 268 | if (rw == READ) | ||
| 269 | bio->bi_end_io = bounce_end_io_read_isa; | ||
| 270 | } | ||
| 271 | |||
| 272 | bio->bi_private = *bio_orig; | ||
| 273 | *bio_orig = bio; | ||
| 274 | } | ||
| 275 | |||
| 276 | void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) | ||
| 277 | { | ||
| 278 | mempool_t *pool; | ||
| 279 | |||
| 280 | /* | ||
| 281 | * for non-isa bounce case, just check if the bounce pfn is equal | ||
| 282 | * to or bigger than the highest pfn in the system -- in that case, | ||
| 283 | * don't waste time iterating over bio segments | ||
| 284 | */ | ||
| 285 | if (!(q->bounce_gfp & GFP_DMA)) { | ||
| 286 | if (q->bounce_pfn >= blk_max_pfn) | ||
| 287 | return; | ||
| 288 | pool = page_pool; | ||
| 289 | } else { | ||
| 290 | BUG_ON(!isa_page_pool); | ||
| 291 | pool = isa_page_pool; | ||
| 292 | } | ||
| 293 | |||
| 294 | blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE); | ||
| 295 | |||
| 296 | /* | ||
| 297 | * slow path | ||
| 298 | */ | ||
| 299 | __blk_queue_bounce(q, bio_orig, pool); | ||
| 300 | } | ||
| 301 | |||
| 302 | EXPORT_SYMBOL(blk_queue_bounce); | ||
diff --git a/mm/filemap.c b/mm/filemap.c index 3277f3b23524..c4fe97f5ace0 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -2020,6 +2020,7 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i | |||
| 2020 | if (unlikely(*pos + *count > inode->i_sb->s_maxbytes)) | 2020 | if (unlikely(*pos + *count > inode->i_sb->s_maxbytes)) |
| 2021 | *count = inode->i_sb->s_maxbytes - *pos; | 2021 | *count = inode->i_sb->s_maxbytes - *pos; |
| 2022 | } else { | 2022 | } else { |
| 2023 | #ifdef CONFIG_BLOCK | ||
| 2023 | loff_t isize; | 2024 | loff_t isize; |
| 2024 | if (bdev_read_only(I_BDEV(inode))) | 2025 | if (bdev_read_only(I_BDEV(inode))) |
| 2025 | return -EPERM; | 2026 | return -EPERM; |
| @@ -2031,6 +2032,9 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i | |||
| 2031 | 2032 | ||
| 2032 | if (*pos + *count > isize) | 2033 | if (*pos + *count > isize) |
| 2033 | *count = isize - *pos; | 2034 | *count = isize - *pos; |
| 2035 | #else | ||
| 2036 | return -EPERM; | ||
| 2037 | #endif | ||
| 2034 | } | 2038 | } |
| 2035 | return 0; | 2039 | return 0; |
| 2036 | } | 2040 | } |
| @@ -2491,3 +2495,33 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
| 2491 | } | 2495 | } |
| 2492 | return retval; | 2496 | return retval; |
| 2493 | } | 2497 | } |
| 2498 | |||
| 2499 | /** | ||
| 2500 | * try_to_release_page() - release old fs-specific metadata on a page | ||
| 2501 | * | ||
| 2502 | * @page: the page which the kernel is trying to free | ||
| 2503 | * @gfp_mask: memory allocation flags (and I/O mode) | ||
| 2504 | * | ||
| 2505 | * The address_space is to try to release any data against the page | ||
| 2506 | * (presumably at page->private). If the release was successful, return `1'. | ||
| 2507 | * Otherwise return zero. | ||
| 2508 | * | ||
| 2509 | * The @gfp_mask argument specifies whether I/O may be performed to release | ||
| 2510 | * this page (__GFP_IO), and whether the call may block (__GFP_WAIT). | ||
| 2511 | * | ||
| 2512 | * NOTE: @gfp_mask may go away, and this function may become non-blocking. | ||
| 2513 | */ | ||
| 2514 | int try_to_release_page(struct page *page, gfp_t gfp_mask) | ||
| 2515 | { | ||
| 2516 | struct address_space * const mapping = page->mapping; | ||
| 2517 | |||
| 2518 | BUG_ON(!PageLocked(page)); | ||
| 2519 | if (PageWriteback(page)) | ||
| 2520 | return 0; | ||
| 2521 | |||
| 2522 | if (mapping && mapping->a_ops->releasepage) | ||
| 2523 | return mapping->a_ops->releasepage(page, gfp_mask); | ||
| 2524 | return try_to_free_buffers(page); | ||
| 2525 | } | ||
| 2526 | |||
| 2527 | EXPORT_SYMBOL(try_to_release_page); | ||
diff --git a/mm/highmem.c b/mm/highmem.c index ee5519b176ee..0206e7e5018c 100644 --- a/mm/highmem.c +++ b/mm/highmem.c | |||
| @@ -29,13 +29,6 @@ | |||
| 29 | #include <linux/blktrace_api.h> | 29 | #include <linux/blktrace_api.h> |
| 30 | #include <asm/tlbflush.h> | 30 | #include <asm/tlbflush.h> |
| 31 | 31 | ||
| 32 | static mempool_t *page_pool, *isa_page_pool; | ||
| 33 | |||
| 34 | static void *mempool_alloc_pages_isa(gfp_t gfp_mask, void *data) | ||
| 35 | { | ||
| 36 | return mempool_alloc_pages(gfp_mask | GFP_DMA, data); | ||
| 37 | } | ||
| 38 | |||
| 39 | /* | 32 | /* |
| 40 | * Virtual_count is not a pure "count". | 33 | * Virtual_count is not a pure "count". |
| 41 | * 0 means that it is not mapped, and has not been mapped | 34 | * 0 means that it is not mapped, and has not been mapped |
| @@ -217,282 +210,8 @@ void fastcall kunmap_high(struct page *page) | |||
| 217 | } | 210 | } |
| 218 | 211 | ||
| 219 | EXPORT_SYMBOL(kunmap_high); | 212 | EXPORT_SYMBOL(kunmap_high); |
| 220 | |||
| 221 | #define POOL_SIZE 64 | ||
| 222 | |||
| 223 | static __init int init_emergency_pool(void) | ||
| 224 | { | ||
| 225 | struct sysinfo i; | ||
| 226 | si_meminfo(&i); | ||
| 227 | si_swapinfo(&i); | ||
| 228 | |||
| 229 | if (!i.totalhigh) | ||
| 230 | return 0; | ||
| 231 | |||
| 232 | page_pool = mempool_create_page_pool(POOL_SIZE, 0); | ||
| 233 | BUG_ON(!page_pool); | ||
| 234 | printk("highmem bounce pool size: %d pages\n", POOL_SIZE); | ||
| 235 | |||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | __initcall(init_emergency_pool); | ||
| 240 | |||
| 241 | /* | ||
| 242 | * highmem version, map in to vec | ||
| 243 | */ | ||
| 244 | static void bounce_copy_vec(struct bio_vec *to, unsigned char *vfrom) | ||
| 245 | { | ||
| 246 | unsigned long flags; | ||
| 247 | unsigned char *vto; | ||
| 248 | |||
| 249 | local_irq_save(flags); | ||
| 250 | vto = kmap_atomic(to->bv_page, KM_BOUNCE_READ); | ||
| 251 | memcpy(vto + to->bv_offset, vfrom, to->bv_len); | ||
| 252 | kunmap_atomic(vto, KM_BOUNCE_READ); | ||
| 253 | local_irq_restore(flags); | ||
| 254 | } | ||
| 255 | |||
| 256 | #else /* CONFIG_HIGHMEM */ | ||
| 257 | |||
| 258 | #define bounce_copy_vec(to, vfrom) \ | ||
| 259 | memcpy(page_address((to)->bv_page) + (to)->bv_offset, vfrom, (to)->bv_len) | ||
| 260 | |||
| 261 | #endif | 213 | #endif |
| 262 | 214 | ||
| 263 | #define ISA_POOL_SIZE 16 | ||
| 264 | |||
| 265 | /* | ||
| 266 | * gets called "every" time someone init's a queue with BLK_BOUNCE_ISA | ||
| 267 | * as the max address, so check if the pool has already been created. | ||
| 268 | */ | ||
| 269 | int init_emergency_isa_pool(void) | ||
| 270 | { | ||
| 271 | if (isa_page_pool) | ||
| 272 | return 0; | ||
| 273 | |||
| 274 | isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa, | ||
| 275 | mempool_free_pages, (void *) 0); | ||
| 276 | BUG_ON(!isa_page_pool); | ||
| 277 | |||
| 278 | printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE); | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | /* | ||
| 283 | * Simple bounce buffer support for highmem pages. Depending on the | ||
| 284 | * queue gfp mask set, *to may or may not be a highmem page. kmap it | ||
| 285 | * always, it will do the Right Thing | ||
| 286 | */ | ||
| 287 | static void copy_to_high_bio_irq(struct bio *to, struct bio *from) | ||
| 288 | { | ||
| 289 | unsigned char *vfrom; | ||
| 290 | struct bio_vec *tovec, *fromvec; | ||
| 291 | int i; | ||
| 292 | |||
| 293 | __bio_for_each_segment(tovec, to, i, 0) { | ||
| 294 | fromvec = from->bi_io_vec + i; | ||
| 295 | |||
| 296 | /* | ||
| 297 | * not bounced | ||
| 298 | */ | ||
| 299 | if (tovec->bv_page == fromvec->bv_page) | ||
| 300 | continue; | ||
| 301 | |||
| 302 | /* | ||
| 303 | * fromvec->bv_offset and fromvec->bv_len might have been | ||
| 304 | * modified by the block layer, so use the original copy, | ||
| 305 | * bounce_copy_vec already uses tovec->bv_len | ||
| 306 | */ | ||
| 307 | vfrom = page_address(fromvec->bv_page) + tovec->bv_offset; | ||
| 308 | |||
| 309 | flush_dcache_page(tovec->bv_page); | ||
| 310 | bounce_copy_vec(tovec, vfrom); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) | ||
| 315 | { | ||
| 316 | struct bio *bio_orig = bio->bi_private; | ||
| 317 | struct bio_vec *bvec, *org_vec; | ||
| 318 | int i; | ||
| 319 | |||
| 320 | if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags)) | ||
| 321 | set_bit(BIO_EOPNOTSUPP, &bio_orig->bi_flags); | ||
| 322 | |||
| 323 | /* | ||
| 324 | * free up bounce indirect pages used | ||
| 325 | */ | ||
| 326 | __bio_for_each_segment(bvec, bio, i, 0) { | ||
| 327 | org_vec = bio_orig->bi_io_vec + i; | ||
| 328 | if (bvec->bv_page == org_vec->bv_page) | ||
| 329 | continue; | ||
| 330 | |||
| 331 | dec_zone_page_state(bvec->bv_page, NR_BOUNCE); | ||
| 332 | mempool_free(bvec->bv_page, pool); | ||
| 333 | } | ||
| 334 | |||
| 335 | bio_endio(bio_orig, bio_orig->bi_size, err); | ||
| 336 | bio_put(bio); | ||
| 337 | } | ||
| 338 | |||
| 339 | static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err) | ||
| 340 | { | ||
| 341 | if (bio->bi_size) | ||
| 342 | return 1; | ||
| 343 | |||
| 344 | bounce_end_io(bio, page_pool, err); | ||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | static int bounce_end_io_write_isa(struct bio *bio, unsigned int bytes_done, int err) | ||
| 349 | { | ||
| 350 | if (bio->bi_size) | ||
| 351 | return 1; | ||
| 352 | |||
| 353 | bounce_end_io(bio, isa_page_pool, err); | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static void __bounce_end_io_read(struct bio *bio, mempool_t *pool, int err) | ||
| 358 | { | ||
| 359 | struct bio *bio_orig = bio->bi_private; | ||
| 360 | |||
| 361 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) | ||
| 362 | copy_to_high_bio_irq(bio_orig, bio); | ||
| 363 | |||
| 364 | bounce_end_io(bio, pool, err); | ||
| 365 | } | ||
| 366 | |||
| 367 | static int bounce_end_io_read(struct bio *bio, unsigned int bytes_done, int err) | ||
| 368 | { | ||
| 369 | if (bio->bi_size) | ||
| 370 | return 1; | ||
| 371 | |||
| 372 | __bounce_end_io_read(bio, page_pool, err); | ||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int err) | ||
| 377 | { | ||
| 378 | if (bio->bi_size) | ||
| 379 | return 1; | ||
| 380 | |||
| 381 | __bounce_end_io_read(bio, isa_page_pool, err); | ||
| 382 | return 0; | ||
| 383 | } | ||
| 384 | |||
| 385 | static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, | ||
| 386 | mempool_t *pool) | ||
| 387 | { | ||
| 388 | struct page *page; | ||
| 389 | struct bio *bio = NULL; | ||
| 390 | int i, rw = bio_data_dir(*bio_orig); | ||
| 391 | struct bio_vec *to, *from; | ||
| 392 | |||
| 393 | bio_for_each_segment(from, *bio_orig, i) { | ||
| 394 | page = from->bv_page; | ||
| 395 | |||
| 396 | /* | ||
| 397 | * is destination page below bounce pfn? | ||
| 398 | */ | ||
| 399 | if (page_to_pfn(page) < q->bounce_pfn) | ||
| 400 | continue; | ||
| 401 | |||
| 402 | /* | ||
| 403 | * irk, bounce it | ||
| 404 | */ | ||
| 405 | if (!bio) | ||
| 406 | bio = bio_alloc(GFP_NOIO, (*bio_orig)->bi_vcnt); | ||
| 407 | |||
| 408 | to = bio->bi_io_vec + i; | ||
| 409 | |||
| 410 | to->bv_page = mempool_alloc(pool, q->bounce_gfp); | ||
| 411 | to->bv_len = from->bv_len; | ||
| 412 | to->bv_offset = from->bv_offset; | ||
| 413 | inc_zone_page_state(to->bv_page, NR_BOUNCE); | ||
| 414 | |||
| 415 | if (rw == WRITE) { | ||
| 416 | char *vto, *vfrom; | ||
| 417 | |||
| 418 | flush_dcache_page(from->bv_page); | ||
| 419 | vto = page_address(to->bv_page) + to->bv_offset; | ||
| 420 | vfrom = kmap(from->bv_page) + from->bv_offset; | ||
| 421 | memcpy(vto, vfrom, to->bv_len); | ||
| 422 | kunmap(from->bv_page); | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | /* | ||
| 427 | * no pages bounced | ||
| 428 | */ | ||
| 429 | if (!bio) | ||
| 430 | return; | ||
| 431 | |||
| 432 | /* | ||
| 433 | * at least one page was bounced, fill in possible non-highmem | ||
| 434 | * pages | ||
| 435 | */ | ||
| 436 | __bio_for_each_segment(from, *bio_orig, i, 0) { | ||
| 437 | to = bio_iovec_idx(bio, i); | ||
| 438 | if (!to->bv_page) { | ||
| 439 | to->bv_page = from->bv_page; | ||
| 440 | to->bv_len = from->bv_len; | ||
| 441 | to->bv_offset = from->bv_offset; | ||
| 442 | } | ||
| 443 | } | ||
| 444 | |||
| 445 | bio->bi_bdev = (*bio_orig)->bi_bdev; | ||
| 446 | bio->bi_flags |= (1 << BIO_BOUNCED); | ||
| 447 | bio->bi_sector = (*bio_orig)->bi_sector; | ||
| 448 | bio->bi_rw = (*bio_orig)->bi_rw; | ||
| 449 | |||
| 450 | bio->bi_vcnt = (*bio_orig)->bi_vcnt; | ||
| 451 | bio->bi_idx = (*bio_orig)->bi_idx; | ||
| 452 | bio->bi_size = (*bio_orig)->bi_size; | ||
| 453 | |||
| 454 | if (pool == page_pool) { | ||
| 455 | bio->bi_end_io = bounce_end_io_write; | ||
| 456 | if (rw == READ) | ||
| 457 | bio->bi_end_io = bounce_end_io_read; | ||
| 458 | } else { | ||
| 459 | bio->bi_end_io = bounce_end_io_write_isa; | ||
| 460 | if (rw == READ) | ||
| 461 | bio->bi_end_io = bounce_end_io_read_isa; | ||
| 462 | } | ||
| 463 | |||
| 464 | bio->bi_private = *bio_orig; | ||
| 465 | *bio_orig = bio; | ||
| 466 | } | ||
| 467 | |||
| 468 | void blk_queue_bounce(request_queue_t *q, struct bio **bio_orig) | ||
| 469 | { | ||
| 470 | mempool_t *pool; | ||
| 471 | |||
| 472 | /* | ||
| 473 | * for non-isa bounce case, just check if the bounce pfn is equal | ||
| 474 | * to or bigger than the highest pfn in the system -- in that case, | ||
| 475 | * don't waste time iterating over bio segments | ||
| 476 | */ | ||
| 477 | if (!(q->bounce_gfp & GFP_DMA)) { | ||
| 478 | if (q->bounce_pfn >= blk_max_pfn) | ||
| 479 | return; | ||
| 480 | pool = page_pool; | ||
| 481 | } else { | ||
| 482 | BUG_ON(!isa_page_pool); | ||
| 483 | pool = isa_page_pool; | ||
| 484 | } | ||
| 485 | |||
| 486 | blk_add_trace_bio(q, *bio_orig, BLK_TA_BOUNCE); | ||
| 487 | |||
| 488 | /* | ||
| 489 | * slow path | ||
| 490 | */ | ||
| 491 | __blk_queue_bounce(q, bio_orig, pool); | ||
| 492 | } | ||
| 493 | |||
| 494 | EXPORT_SYMBOL(blk_queue_bounce); | ||
| 495 | |||
| 496 | #if defined(HASHED_PAGE_VIRTUAL) | 215 | #if defined(HASHED_PAGE_VIRTUAL) |
| 497 | 216 | ||
| 498 | #define PA_HASH_ORDER 7 | 217 | #define PA_HASH_ORDER 7 |
diff --git a/mm/migrate.c b/mm/migrate.c index 20a8c2687b1e..ba2453f9483d 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
| @@ -409,6 +409,7 @@ int migrate_page(struct address_space *mapping, | |||
| 409 | } | 409 | } |
| 410 | EXPORT_SYMBOL(migrate_page); | 410 | EXPORT_SYMBOL(migrate_page); |
| 411 | 411 | ||
| 412 | #ifdef CONFIG_BLOCK | ||
| 412 | /* | 413 | /* |
| 413 | * Migration function for pages with buffers. This function can only be used | 414 | * Migration function for pages with buffers. This function can only be used |
| 414 | * if the underlying filesystem guarantees that no other references to "page" | 415 | * if the underlying filesystem guarantees that no other references to "page" |
| @@ -466,6 +467,7 @@ int buffer_migrate_page(struct address_space *mapping, | |||
| 466 | return 0; | 467 | return 0; |
| 467 | } | 468 | } |
| 468 | EXPORT_SYMBOL(buffer_migrate_page); | 469 | EXPORT_SYMBOL(buffer_migrate_page); |
| 470 | #endif | ||
| 469 | 471 | ||
| 470 | /* | 472 | /* |
| 471 | * Writeback a page to clean the dirty state | 473 | * Writeback a page to clean the dirty state |
| @@ -525,7 +527,7 @@ static int fallback_migrate_page(struct address_space *mapping, | |||
| 525 | * Buffers may be managed in a filesystem specific way. | 527 | * Buffers may be managed in a filesystem specific way. |
| 526 | * We must have no buffers or drop them. | 528 | * We must have no buffers or drop them. |
| 527 | */ | 529 | */ |
| 528 | if (page_has_buffers(page) && | 530 | if (PagePrivate(page) && |
| 529 | !try_to_release_page(page, GFP_KERNEL)) | 531 | !try_to_release_page(page, GFP_KERNEL)) |
| 530 | return -EAGAIN; | 532 | return -EAGAIN; |
| 531 | 533 | ||
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 488b7088557c..c0d4ce144dec 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #include <linux/sysctl.h> | 30 | #include <linux/sysctl.h> |
| 31 | #include <linux/cpu.h> | 31 | #include <linux/cpu.h> |
| 32 | #include <linux/syscalls.h> | 32 | #include <linux/syscalls.h> |
| 33 | #include <linux/buffer_head.h> | ||
| 34 | #include <linux/pagevec.h> | ||
| 33 | 35 | ||
| 34 | /* | 36 | /* |
| 35 | * The maximum number of pages to writeout in a single bdflush/kupdate | 37 | * The maximum number of pages to writeout in a single bdflush/kupdate |
| @@ -550,6 +552,139 @@ void __init page_writeback_init(void) | |||
| 550 | register_cpu_notifier(&ratelimit_nb); | 552 | register_cpu_notifier(&ratelimit_nb); |
| 551 | } | 553 | } |
| 552 | 554 | ||
| 555 | /** | ||
| 556 | * generic_writepages - walk the list of dirty pages of the given | ||
| 557 | * address space and writepage() all of them. | ||
| 558 | * | ||
| 559 | * @mapping: address space structure to write | ||
| 560 | * @wbc: subtract the number of written pages from *@wbc->nr_to_write | ||
| 561 | * | ||
| 562 | * This is a library function, which implements the writepages() | ||
| 563 | * address_space_operation. | ||
| 564 | * | ||
| 565 | * If a page is already under I/O, generic_writepages() skips it, even | ||
| 566 | * if it's dirty. This is desirable behaviour for memory-cleaning writeback, | ||
| 567 | * but it is INCORRECT for data-integrity system calls such as fsync(). fsync() | ||
| 568 | * and msync() need to guarantee that all the data which was dirty at the time | ||
| 569 | * the call was made get new I/O started against them. If wbc->sync_mode is | ||
| 570 | * WB_SYNC_ALL then we were called for data integrity and we must wait for | ||
| 571 | * existing IO to complete. | ||
| 572 | * | ||
| 573 | * Derived from mpage_writepages() - if you fix this you should check that | ||
| 574 | * also! | ||
| 575 | */ | ||
| 576 | int generic_writepages(struct address_space *mapping, | ||
| 577 | struct writeback_control *wbc) | ||
| 578 | { | ||
| 579 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
| 580 | int ret = 0; | ||
| 581 | int done = 0; | ||
| 582 | int (*writepage)(struct page *page, struct writeback_control *wbc); | ||
| 583 | struct pagevec pvec; | ||
| 584 | int nr_pages; | ||
| 585 | pgoff_t index; | ||
| 586 | pgoff_t end; /* Inclusive */ | ||
| 587 | int scanned = 0; | ||
| 588 | int range_whole = 0; | ||
| 589 | |||
| 590 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
| 591 | wbc->encountered_congestion = 1; | ||
| 592 | return 0; | ||
| 593 | } | ||
| 594 | |||
| 595 | writepage = mapping->a_ops->writepage; | ||
| 596 | |||
| 597 | /* deal with chardevs and other special file */ | ||
| 598 | if (!writepage) | ||
| 599 | return 0; | ||
| 600 | |||
| 601 | pagevec_init(&pvec, 0); | ||
| 602 | if (wbc->range_cyclic) { | ||
| 603 | index = mapping->writeback_index; /* Start from prev offset */ | ||
| 604 | end = -1; | ||
| 605 | } else { | ||
| 606 | index = wbc->range_start >> PAGE_CACHE_SHIFT; | ||
| 607 | end = wbc->range_end >> PAGE_CACHE_SHIFT; | ||
| 608 | if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) | ||
| 609 | range_whole = 1; | ||
| 610 | scanned = 1; | ||
| 611 | } | ||
| 612 | retry: | ||
| 613 | while (!done && (index <= end) && | ||
| 614 | (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, | ||
| 615 | PAGECACHE_TAG_DIRTY, | ||
| 616 | min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { | ||
| 617 | unsigned i; | ||
| 618 | |||
| 619 | scanned = 1; | ||
| 620 | for (i = 0; i < nr_pages; i++) { | ||
| 621 | struct page *page = pvec.pages[i]; | ||
| 622 | |||
| 623 | /* | ||
| 624 | * At this point we hold neither mapping->tree_lock nor | ||
| 625 | * lock on the page itself: the page may be truncated or | ||
| 626 | * invalidated (changing page->mapping to NULL), or even | ||
| 627 | * swizzled back from swapper_space to tmpfs file | ||
| 628 | * mapping | ||
| 629 | */ | ||
| 630 | lock_page(page); | ||
| 631 | |||
| 632 | if (unlikely(page->mapping != mapping)) { | ||
| 633 | unlock_page(page); | ||
| 634 | continue; | ||
| 635 | } | ||
| 636 | |||
| 637 | if (!wbc->range_cyclic && page->index > end) { | ||
| 638 | done = 1; | ||
| 639 | unlock_page(page); | ||
| 640 | continue; | ||
| 641 | } | ||
| 642 | |||
| 643 | if (wbc->sync_mode != WB_SYNC_NONE) | ||
| 644 | wait_on_page_writeback(page); | ||
| 645 | |||
| 646 | if (PageWriteback(page) || | ||
| 647 | !clear_page_dirty_for_io(page)) { | ||
| 648 | unlock_page(page); | ||
| 649 | continue; | ||
| 650 | } | ||
| 651 | |||
| 652 | ret = (*writepage)(page, wbc); | ||
| 653 | if (ret) { | ||
| 654 | if (ret == -ENOSPC) | ||
| 655 | set_bit(AS_ENOSPC, &mapping->flags); | ||
| 656 | else | ||
| 657 | set_bit(AS_EIO, &mapping->flags); | ||
| 658 | } | ||
| 659 | |||
| 660 | if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) | ||
| 661 | unlock_page(page); | ||
| 662 | if (ret || (--(wbc->nr_to_write) <= 0)) | ||
| 663 | done = 1; | ||
| 664 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
| 665 | wbc->encountered_congestion = 1; | ||
| 666 | done = 1; | ||
| 667 | } | ||
| 668 | } | ||
| 669 | pagevec_release(&pvec); | ||
| 670 | cond_resched(); | ||
| 671 | } | ||
| 672 | if (!scanned && !done) { | ||
| 673 | /* | ||
| 674 | * We hit the last page and there is more work to be done: wrap | ||
| 675 | * back to the start of the file | ||
| 676 | */ | ||
| 677 | scanned = 1; | ||
| 678 | index = 0; | ||
| 679 | goto retry; | ||
| 680 | } | ||
| 681 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) | ||
| 682 | mapping->writeback_index = index; | ||
| 683 | return ret; | ||
| 684 | } | ||
| 685 | |||
| 686 | EXPORT_SYMBOL(generic_writepages); | ||
| 687 | |||
| 553 | int do_writepages(struct address_space *mapping, struct writeback_control *wbc) | 688 | int do_writepages(struct address_space *mapping, struct writeback_control *wbc) |
| 554 | { | 689 | { |
| 555 | int ret; | 690 | int ret; |
| @@ -672,9 +807,11 @@ int fastcall set_page_dirty(struct page *page) | |||
| 672 | 807 | ||
| 673 | if (likely(mapping)) { | 808 | if (likely(mapping)) { |
| 674 | int (*spd)(struct page *) = mapping->a_ops->set_page_dirty; | 809 | int (*spd)(struct page *) = mapping->a_ops->set_page_dirty; |
| 675 | if (spd) | 810 | #ifdef CONFIG_BLOCK |
| 676 | return (*spd)(page); | 811 | if (!spd) |
| 677 | return __set_page_dirty_buffers(page); | 812 | spd = __set_page_dirty_buffers; |
| 813 | #endif | ||
| 814 | return (*spd)(page); | ||
| 678 | } | 815 | } |
| 679 | if (!PageDirty(page)) { | 816 | if (!PageDirty(page)) { |
| 680 | if (!TestSetPageDirty(page)) | 817 | if (!TestSetPageDirty(page)) |
diff --git a/mm/truncate.c b/mm/truncate.c index a654928323dc..8fde6580657e 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
| @@ -17,6 +17,32 @@ | |||
| 17 | do_invalidatepage */ | 17 | do_invalidatepage */ |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | /** | ||
| 21 | * do_invalidatepage - invalidate part of all of a page | ||
| 22 | * @page: the page which is affected | ||
| 23 | * @offset: the index of the truncation point | ||
| 24 | * | ||
| 25 | * do_invalidatepage() is called when all or part of the page has become | ||
| 26 | * invalidated by a truncate operation. | ||
| 27 | * | ||
| 28 | * do_invalidatepage() does not have to release all buffers, but it must | ||
| 29 | * ensure that no dirty buffer is left outside @offset and that no I/O | ||
| 30 | * is underway against any of the blocks which are outside the truncation | ||
| 31 | * point. Because the caller is about to free (and possibly reuse) those | ||
| 32 | * blocks on-disk. | ||
| 33 | */ | ||
| 34 | void do_invalidatepage(struct page *page, unsigned long offset) | ||
| 35 | { | ||
| 36 | void (*invalidatepage)(struct page *, unsigned long); | ||
| 37 | invalidatepage = page->mapping->a_ops->invalidatepage; | ||
| 38 | #ifdef CONFIG_BLOCK | ||
| 39 | if (!invalidatepage) | ||
| 40 | invalidatepage = block_invalidatepage; | ||
| 41 | #endif | ||
| 42 | if (invalidatepage) | ||
| 43 | (*invalidatepage)(page, offset); | ||
| 44 | } | ||
| 45 | |||
| 20 | static inline void truncate_partial_page(struct page *page, unsigned partial) | 46 | static inline void truncate_partial_page(struct page *page, unsigned partial) |
| 21 | { | 47 | { |
| 22 | memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); | 48 | memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); |
