diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 23:58:06 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 23:58:06 -0800 |
| commit | e1e2cfc3fb42dbe54dd94fe97ba17a62cd7a265b (patch) | |
| tree | 2cd3cb5d9f2c43fb7939bd95bdef808d113bc042 /include/linux | |
| parent | 3735375e3fd2f2286c1dc2f0131f39d438ae9a5c (diff) | |
v2.5.0.1 -> v2.5.0.2
- Greg KH: USB update
- Richard Gooch: refcounting for devfs
- Jens Axboe: start of new block IO layer
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/bio.h | 230 | ||||
| -rw-r--r-- | include/linux/blk.h | 44 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 216 | ||||
| -rw-r--r-- | include/linux/bootmem.h | 5 | ||||
| -rw-r--r-- | include/linux/devfs_fs_kernel.h | 2 | ||||
| -rw-r--r-- | include/linux/elevator.h | 68 | ||||
| -rw-r--r-- | include/linux/fs.h | 43 | ||||
| -rw-r--r-- | include/linux/genhd.h | 33 | ||||
| -rw-r--r-- | include/linux/highmem.h | 42 | ||||
| -rw-r--r-- | include/linux/ide.h | 83 | ||||
| -rw-r--r-- | include/linux/iobuf.h | 12 | ||||
| -rw-r--r-- | include/linux/iso_fs.h | 2 | ||||
| -rw-r--r-- | include/linux/loop.h | 4 | ||||
| -rw-r--r-- | include/linux/lvm.h | 7 | ||||
| -rw-r--r-- | include/linux/nbd.h | 17 | ||||
| -rw-r--r-- | include/linux/raid/md_k.h | 2 | ||||
| -rw-r--r-- | include/linux/reiserfs_fs.h | 2 | ||||
| -rw-r--r-- | include/linux/slab.h | 2 | ||||
| -rw-r--r-- | include/linux/types.h | 11 |
19 files changed, 646 insertions, 179 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h new file mode 100644 index 000000000000..7e58544540ba --- /dev/null +++ b/include/linux/bio.h @@ -0,0 +1,230 @@ +/* + * New 2.5 block I/O model + * + * Copyright (C) 2001 Jens Axboe <axboe@suse.de> + * + * This program is free software; you can redistribute it and/or mo + * it under the terms of the GNU General Public License as publishe + * the Free Software Foundation; either version 2 of the License, o + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public Licens + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- + */ +#ifndef __LINUX_BIO_H +#define __LINUX_BIO_H + +#define BIO_DEBUG + +#ifdef BIO_DEBUG +#define BIO_BUG_ON BUG_ON +#else +#define BIO_BUG_ON +#endif + +/* + * hash profiling stuff.. + */ +#define BIO_HASH_PROFILING + +#define BLKHASHPROF _IOR(0x12,108,sizeof(struct bio_hash_stats)) +#define BLKHASHCLEAR _IO(0x12,109) + +#define MAX_PROFILE_BUCKETS 64 + +struct bio_hash_stats { + atomic_t nr_lookups; + atomic_t nr_hits; + atomic_t nr_inserts; + atomic_t nr_entries; + atomic_t max_entries; + atomic_t max_bucket_size; + atomic_t bucket_size[MAX_PROFILE_BUCKETS + 1]; +}; + +/* + * was unsigned short, but we might as well be ready for > 64kB I/O pages + */ +struct bio_vec { + struct page *bv_page; + unsigned int bv_len; + unsigned int bv_offset; +}; + +struct bio_vec_list { + unsigned int bvl_cnt; /* how may bio_vec's */ + unsigned int bvl_idx; /* current index into bvl_vec */ + unsigned int bvl_size; /* total size in bytes */ + unsigned int bvl_max; /* max bvl_vecs we can hold, used + as index into pool */ + struct bio_vec bvl_vec[0]; /* the iovec array */ +}; + +typedef struct bio_hash_s { + struct bio_hash_s *next_hash; + struct bio_hash_s **pprev_hash; + unsigned long valid_counter; +} bio_hash_t; + +struct bio_hash_bucket { + rwlock_t lock; + bio_hash_t *hash; +} __attribute__((__aligned__(16))); + +#define BIO_HASH_BITS (bio_hash_bits) +#define BIO_HASH_SIZE (1UL << BIO_HASH_BITS) + +/* + * shamelessly stolen from the list.h implementation + */ +#define hash_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) +#define bio_hash_entry(ptr) \ + hash_entry((ptr), struct bio, bi_hash) + +/* + * main unit of I/O for the block layer and lower layers (ie drivers and + * stacking drivers) + */ +struct bio { + sector_t bi_sector; + struct bio *bi_next; /* request queue link */ + bio_hash_t bi_hash; + atomic_t bi_cnt; /* pin count */ + kdev_t bi_dev; /* will be block device */ + struct bio_vec_list *bi_io_vec; + unsigned long bi_flags; /* status, command, etc */ + unsigned long bi_rw; /* bottom bits READ/WRITE, + * top bits priority + */ + int (*bi_end_io)(struct bio *bio, int nr_sectors); + void *bi_private; + + void *bi_hash_desc; /* cookie for hash */ + + void (*bi_destructor)(struct bio *); /* destructor */ +}; + +#define BIO_SECTOR_BITS 9 +#define BIO_OFFSET_MASK ((1UL << (PAGE_CACHE_SHIFT - BIO_SECTOR_BITS)) - 1) +#define BIO_PAGE_MASK (PAGE_CACHE_SIZE - 1) + +/* + * bio flags + */ +#define BIO_UPTODATE 0 /* ok after I/O completion */ +#define BIO_RW_BLOCK 1 /* RW_AHEAD set, and read/write would block */ +#define BIO_EOF 2 /* out-out-bounds error */ +#define BIO_PREBUILT 3 /* not merged big */ +#define BIO_CLONED 4 /* doesn't own data */ + +#define bio_is_hashed(bio) ((bio)->bi_hash.pprev_hash) + +/* + * bio bi_rw flags + * + * bit 0 -- read (not set) or write (set) + * bit 1 -- rw-ahead when set + * bit 2 -- barrier + */ +#define BIO_RW 0 +#define BIO_RW_AHEAD 1 +#define BIO_BARRIER 2 + +/* + * various member access, note that bio_data should of course not be used + * on highmem page vectors + */ +#define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec->bvl_vec[(idx)])) +#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_io_vec->bvl_idx) +#define bio_page(bio) bio_iovec((bio))->bv_page +#define bio_size(bio) ((bio)->bi_io_vec->bvl_size) +#define bio_offset(bio) bio_iovec((bio))->bv_offset +#define bio_sectors(bio) (bio_size((bio)) >> BIO_SECTOR_BITS) +#define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio))) +#define bio_barrier(bio) ((bio)->bi_rw & (1 << BIO_BARRIER)) + +/* + * will die + */ +#define bio_to_phys(bio) (page_to_phys(bio_page((bio))) + bio_offset((bio))) +#define bvec_to_phys(bv) (page_to_phys((bv)->bv_page) + (bv)->bv_offset) + +/* + * hack to avoid doing 64-bit calculations on 32-bit archs, instead use a + * pseudo-pfn check to do segment coalescing + */ +#define bio_sec_pfn(bio) \ + ((((bio_page(bio) - bio_page(bio)->zone->zone_mem_map) << PAGE_SHIFT) / bio_size(bio)) + (bio_offset(bio) >> 9)) + +/* + * queues that have highmem support enabled may still need to revert to + * PIO transfers occasionally and thus map high pages temporarily. For + * permanent PIO fall back, user is probably better off disabling highmem + * I/O completely on that queue (see ide-dma for example) + */ +#define bio_kmap(bio) kmap(bio_page((bio))) + bio_offset((bio)) +#define bio_kunmap(bio) kunmap(bio_page((bio))) + +#define BIO_CONTIG(bio, nxt) \ + (bio_to_phys((bio)) + bio_size((bio)) == bio_to_phys((nxt))) +#define __BIO_PHYS_4G(addr1, addr2) \ + (((addr1) | 0xffffffff) == (((addr2) -1 ) | 0xffffffff)) +#define BIO_PHYS_4G(b1, b2) \ + __BIO_PHYS_4G(bio_to_phys((b1)), bio_to_phys((b2)) + bio_size((b2))) + +typedef int (bio_end_io_t) (struct bio *, int); +typedef void (bio_destructor_t) (struct bio *); + +#define bio_io_error(bio) bio_endio((bio), 0, bio_sectors((bio))) + +#define bio_for_each_segment(bvl, bio, i) \ + for (bvl = bio_iovec((bio)), i = (bio)->bi_io_vec->bvl_idx; \ + i < (bio)->bi_io_vec->bvl_cnt; \ + bvl++, i++) + +/* + * get a reference to a bio, so it won't disappear. the intended use is + * something like: + * + * bio_get(bio); + * submit_bio(rw, bio); + * if (bio->bi_flags ...) + * do_something + * bio_put(bio); + * + * without the bio_get(), it could potentially complete I/O before submit_bio + * returns. and then bio would be freed memory when if (bio->bi_flags ...) + * runs + */ +#define bio_get(bio) atomic_inc(&(bio)->bi_cnt) + +extern struct bio *bio_alloc(int, int); +extern void bio_put(struct bio *); + +/* + * the hash stuff is pretty closely tied to the request queue (needed for + * locking etc anyway, and it's in no way an attempt at a generic hash) + */ +struct request_queue; + +extern inline void bio_hash_remove(struct bio *); +extern inline void bio_hash_add(struct bio *, void *, unsigned int); +extern inline struct bio *bio_hash_find(kdev_t, sector_t, unsigned int); +extern inline int bio_hash_add_unique(struct bio *, void *, unsigned int); +extern void bio_hash_invalidate(struct request_queue *, kdev_t); +extern int bio_endio(struct bio *, int, int); + +extern struct bio *bio_clone(struct bio *, int); +extern struct bio *bio_copy(struct bio *, int); + +extern int bio_ioctl(kdev_t, unsigned int, unsigned long); + +#endif /* __LINUX_BIO_H */ diff --git a/include/linux/blk.h b/include/linux/blk.h index b09f5afa9156..863ace44fde8 100644 --- a/include/linux/blk.h +++ b/include/linux/blk.h @@ -5,13 +5,7 @@ #include <linux/locks.h> #include <linux/config.h> #include <linux/spinlock.h> - -/* - * Spinlock for protecting the request queue which - * is mucked around with in interrupts on potentially - * multiple CPU's.. - */ -extern spinlock_t io_request_lock; +#include <linux/compiler.h> /* * Initialization functions. @@ -87,13 +81,18 @@ void initrd_init(void); * code duplication in drivers. */ -static inline void blkdev_dequeue_request(struct request * req) +static inline void blkdev_dequeue_request(struct request *req) { - list_del(&req->queue); + if (req->bio) + bio_hash_remove(req->bio); + if (req->biotail) + bio_hash_remove(req->biotail); + + list_del(&req->queuelist); } -int end_that_request_first(struct request *req, int uptodate, char *name); -void end_that_request_last(struct request *req); +int end_that_request_first(struct request *, int uptodate, int nr_sectors); +void end_that_request_last(struct request *); #if defined(MAJOR_NR) || defined(IDE_DRIVER) @@ -338,12 +337,16 @@ static void floppy_off(unsigned int nr); #if !defined(IDE_DRIVER) #ifndef CURRENT -#define CURRENT blkdev_entry_next_request(&blk_dev[MAJOR_NR].request_queue.queue_head) +#define CURRENT elv_next_request(&blk_dev[MAJOR_NR].request_queue) +#endif +#ifndef QUEUE +#define QUEUE (&blk_dev[MAJOR_NR].request_queue) #endif #ifndef QUEUE_EMPTY -#define QUEUE_EMPTY list_empty(&blk_dev[MAJOR_NR].request_queue.queue_head) +#define QUEUE_EMPTY blk_queue_empty(QUEUE) #endif + #ifndef DEVICE_NAME #define DEVICE_NAME "unknown" #endif @@ -367,16 +370,14 @@ static void (DEVICE_REQUEST)(request_queue_t *); #endif #define INIT_REQUEST \ - if (QUEUE_EMPTY) {\ + if (QUEUE_EMPTY) { \ CLEAR_INTR; \ - return; \ + return; \ } \ if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \ panic(DEVICE_NAME ": request list destroyed"); \ - if (CURRENT->bh) { \ - if (!buffer_locked(CURRENT->bh)) \ - panic(DEVICE_NAME ": block not locked"); \ - } + if (!CURRENT->bio) \ + panic(DEVICE_NAME ": no bio"); \ #endif /* !defined(IDE_DRIVER) */ @@ -385,10 +386,11 @@ static void (DEVICE_REQUEST)(request_queue_t *); #if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR) -static inline void end_request(int uptodate) { +static inline void end_request(int uptodate) +{ struct request *req = CURRENT; - if (end_that_request_first(req, uptodate, DEVICE_NAME)) + if (end_that_request_first(req, uptodate, CURRENT->hard_cur_sectors)) return; #ifndef DEVICE_NO_RANDOM diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index cdb196ca50fb..f3e54a537508 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -6,60 +6,57 @@ #include <linux/genhd.h> #include <linux/tqueue.h> #include <linux/list.h> +#include <linux/mm.h> + +#include <asm/scatterlist.h> struct request_queue; typedef struct request_queue request_queue_t; struct elevator_s; typedef struct elevator_s elevator_t; -/* - * Ok, this is an expanded form so that we can use the same - * request for paging requests. - */ struct request { - struct list_head queue; + struct list_head queuelist; /* looking for ->queue? you must _not_ + * access it directly, use + * blkdev_dequeue_request! */ int elevator_sequence; - volatile int rq_status; /* should split this into a few status bits */ -#define RQ_INACTIVE (-1) -#define RQ_ACTIVE 1 -#define RQ_SCSI_BUSY 0xffff -#define RQ_SCSI_DONE 0xfffe -#define RQ_SCSI_DISCONNECTING 0xffe0 + int inactive; /* driver hasn't seen it yet */ + int rq_status; /* should split this into a few status bits */ kdev_t rq_dev; int cmd; /* READ or WRITE */ int errors; - unsigned long sector; + sector_t sector; unsigned long nr_sectors; unsigned long hard_sector, hard_nr_sectors; - unsigned int nr_segments; - unsigned int nr_hw_segments; - unsigned long current_nr_sectors; - void * special; - char * buffer; - struct completion * waiting; - struct buffer_head * bh; - struct buffer_head * bhtail; + unsigned short nr_segments; + unsigned short nr_hw_segments; + unsigned int current_nr_sectors; + unsigned int hard_cur_sectors; + void *special; + char *buffer; + struct completion *waiting; + struct bio *bio, *biotail; request_queue_t *q; }; #include <linux/elevator.h> -typedef int (merge_request_fn) (request_queue_t *q, - struct request *req, - struct buffer_head *bh, - int); -typedef int (merge_requests_fn) (request_queue_t *q, - struct request *req, - struct request *req2, - int); +typedef int (merge_request_fn) (request_queue_t *, struct request *, + struct bio *); +typedef int (merge_requests_fn) (request_queue_t *, struct request *, + struct request *); typedef void (request_fn_proc) (request_queue_t *q); typedef request_queue_t * (queue_proc) (kdev_t dev); -typedef int (make_request_fn) (request_queue_t *q, int rw, struct buffer_head *bh); -typedef void (plug_device_fn) (request_queue_t *q, kdev_t device); +typedef int (make_request_fn) (request_queue_t *q, struct bio *bio); typedef void (unplug_device_fn) (void *q); +enum blk_queue_state { + Queue_down, + Queue_up, +}; + /* * Default nr free requests per queue, ll_rw_blk will scale it down * according to available RAM at init time @@ -69,6 +66,7 @@ typedef void (unplug_device_fn) (void *q); struct request_list { unsigned int count; struct list_head free; + wait_queue_head_t wait; }; struct request_queue @@ -89,7 +87,7 @@ struct request_queue merge_request_fn * front_merge_fn; merge_requests_fn * merge_requests_fn; make_request_fn * make_request_fn; - plug_device_fn * plug_device_fn; + /* * The queue owner gets to use this for whatever they like. * ll_rw_blk doesn't touch it. @@ -97,33 +95,111 @@ struct request_queue void * queuedata; /* - * This is used to remove the plug when tq_disk runs. + * queue needs bounce pages for pages above this limit */ - struct tq_struct plug_tq; + unsigned long bounce_pfn; /* - * Boolean that indicates whether this queue is plugged or not. + * for memory zoning (<= 4GB and > 4GB) */ - char plugged; + int bounce_gfp; /* - * Boolean that indicates whether current_request is active or - * not. + * This is used to remove the plug when tq_disk runs. */ - char head_active; + struct tq_struct plug_tq; /* - * Is meant to protect the queue in the future instead of - * io_request_lock + * various queue flags, see QUEUE_* below + */ + unsigned long queue_flags; + + /* + * protects queue structures from reentrancy */ spinlock_t queue_lock; /* - * Tasks wait here for free request + * queue settings */ - wait_queue_head_t wait_for_request; + unsigned short max_sectors; + unsigned short max_segments; + unsigned short hardsect_size; + unsigned int max_segment_size; + + wait_queue_head_t queue_wait; + + unsigned int hash_valid_counter; }; +#define RQ_INACTIVE (-1) +#define RQ_ACTIVE 1 +#define RQ_SCSI_BUSY 0xffff +#define RQ_SCSI_DONE 0xfffe +#define RQ_SCSI_DISCONNECTING 0xffe0 + +#define QUEUE_FLAG_PLUGGED 0 /* queue is plugged */ +#define QUEUE_FLAG_NOSPLIT 1 /* can process bio over several goes */ + +#define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags) + +#define blk_mark_plugged(q) set_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags) + +#define blk_queue_empty(q) elv_queue_empty(q) + +#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) + +/* + * noop, requests are automagically marked as active/inactive by I/O + * scheduler -- see elv_next_request + */ +#define blk_queue_headactive(q, head_active) + +extern unsigned long blk_max_low_pfn, blk_max_pfn; + +#define __elv_next_request(q) (q)->elevator.elevator_next_req_fn((q)) + +extern inline struct request *elv_next_request(request_queue_t *q) +{ + struct request *rq = __elv_next_request(q); + + if (rq) { + rq->inactive = 0; + wmb(); + + if (rq->bio) + bio_hash_remove(rq->bio); + if (rq->biotail) + bio_hash_remove(rq->biotail); + } + + return rq; +} + +#define BLK_BOUNCE_HIGH (blk_max_low_pfn << PAGE_SHIFT) +#define BLK_BOUNCE_ANY (blk_max_pfn << PAGE_SHIFT) + +#ifdef CONFIG_HIGHMEM + +extern void create_bounce(struct bio **bio_orig, int gfp_mask); + +extern inline void blk_queue_bounce(request_queue_t *q, struct bio **bio) +{ + struct page *page = bio_page(*bio); + + if (page - page->zone->zone_mem_map > q->bounce_pfn) + create_bounce(bio, q->bounce_gfp); +} + +#else /* CONFIG_HIGHMEM */ + +#define blk_queue_bounce(q, bio) do { } while (0) + +#endif /* CONFIG_HIGHMEM */ + +#define rq_for_each_bio(bio, rq) \ + for (bio = (rq)->bio; bio; bio = bio->bi_next) + struct blk_dev_struct { /* * queue_proc has to be atomic @@ -148,68 +224,78 @@ struct sec_size { extern struct sec_size * blk_sec[MAX_BLKDEV]; extern struct blk_dev_struct blk_dev[MAX_BLKDEV]; -extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size); +extern void grok_partitions(kdev_t dev, long size); +extern int wipe_partitions(kdev_t dev); extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size); -extern void generic_make_request(int rw, struct buffer_head * bh); +extern void generic_make_request(struct bio *bio); extern inline request_queue_t *blk_get_queue(kdev_t dev); extern void blkdev_release_request(struct request *); +extern void blk_attempt_remerge(request_queue_t *, struct request *); /* * Access functions for manipulating queue properties */ -extern void blk_init_queue(request_queue_t *, request_fn_proc *); +extern int blk_init_queue(request_queue_t *, request_fn_proc *, char *); extern void blk_cleanup_queue(request_queue_t *); -extern void blk_queue_headactive(request_queue_t *, int); extern void blk_queue_make_request(request_queue_t *, make_request_fn *); +extern void blk_queue_bounce_limit(request_queue_t *, unsigned long long); +extern void blk_queue_max_sectors(request_queue_t *q, unsigned short); +extern void blk_queue_max_segments(request_queue_t *q, unsigned short); +extern void blk_queue_max_segment_size(request_queue_t *q, unsigned int); +extern void blk_queue_hardsect_size(request_queue_t *q, unsigned short); +extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *); extern void generic_unplug_device(void *); extern int * blk_size[MAX_BLKDEV]; extern int * blksize_size[MAX_BLKDEV]; -extern int * hardsect_size[MAX_BLKDEV]; - extern int * max_readahead[MAX_BLKDEV]; -extern int * max_sectors[MAX_BLKDEV]; - -extern int * max_segments[MAX_BLKDEV]; - #define MAX_SEGMENTS 128 #define MAX_SECTORS 255 -#define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK) +#define MAX_SEGMENT_SIZE 65536 /* read-ahead in pages.. */ #define MAX_READAHEAD 31 #define MIN_READAHEAD 3 -#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queue) +#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist) #define blkdev_entry_next_request(entry) blkdev_entry_to_request((entry)->next) #define blkdev_entry_prev_request(entry) blkdev_entry_to_request((entry)->prev) -#define blkdev_next_request(req) blkdev_entry_to_request((req)->queue.next) -#define blkdev_prev_request(req) blkdev_entry_to_request((req)->queue.prev) +#define blkdev_next_request(req) blkdev_entry_to_request((req)->queuelist.next) +#define blkdev_prev_request(req) blkdev_entry_to_request((req)->queuelist.prev) extern void drive_stat_acct (kdev_t dev, int rw, unsigned long nr_sectors, int new_io); -static inline int get_hardsect_size(kdev_t dev) +extern inline void blk_clear(int major) { + blk_size[major] = NULL; +#if 0 + blk_size_in_bytes[major] = NULL; +#endif + blksize_size[major] = NULL; + max_readahead[major] = NULL; + read_ahead[major] = 0; +} + +extern inline int get_hardsect_size(kdev_t dev) +{ + request_queue_t *q = blk_get_queue(dev); int retval = 512; - int major = MAJOR(dev); - if (hardsect_size[major]) { - int minor = MINOR(dev); - if (hardsect_size[major][minor]) - retval = hardsect_size[major][minor]; - } + if (q && q->hardsect_size) + retval = q->hardsect_size; + return retval; } #define blk_finished_io(nsects) do { } while (0) #define blk_started_io(nsects) do { } while (0) -static inline unsigned int blksize_bits(unsigned int size) +extern inline unsigned int blksize_bits(unsigned int size) { unsigned int bits = 8; do { @@ -219,7 +305,7 @@ static inline unsigned int blksize_bits(unsigned int size) return bits; } -static inline unsigned int block_size(kdev_t dev) +extern inline unsigned int block_size(kdev_t dev) { int retval = BLOCK_SIZE; int major = MAJOR(dev); diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 6560f2901519..3bd68c042514 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -18,6 +18,11 @@ extern unsigned long max_low_pfn; extern unsigned long min_low_pfn; /* + * highest page + */ +extern unsigned long max_pfn; + +/* * node_bootmem_map is a map pointer - the bits represent all physical * memory pages (including holes) on the node. */ diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index e6bc2bcbc217..7ca978981e2c 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -3,7 +3,7 @@ #include <linux/fs.h> #include <linux/config.h> -#include <linux/locks.h> +#include <linux/spinlock.h> #include <linux/kdev_t.h> #include <linux/types.h> diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 1a8bb5c39ae6..9d5d644c3b88 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -5,13 +5,20 @@ typedef void (elevator_fn) (struct request *, elevator_t *, struct list_head *, struct list_head *, int); -typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct list_head *, - struct buffer_head *, int, int); +typedef int (elevator_merge_fn) (request_queue_t *, struct request **, + struct list_head *, struct bio *); typedef void (elevator_merge_cleanup_fn) (request_queue_t *, struct request *, int); typedef void (elevator_merge_req_fn) (struct request *, struct request *); +typedef struct request *(elevator_next_req_fn) (request_queue_t *); + +typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *); + +typedef int (elevator_init_fn) (request_queue_t *, elevator_t *); +typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *); + struct elevator_s { int read_latency; @@ -21,31 +28,46 @@ struct elevator_s elevator_merge_cleanup_fn *elevator_merge_cleanup_fn; elevator_merge_req_fn *elevator_merge_req_fn; - unsigned int queue_ID; + elevator_next_req_fn *elevator_next_req_fn; + elevator_add_req_fn *elevator_add_req_fn; + + elevator_init_fn *elevator_init_fn; + elevator_exit_fn *elevator_exit_fn; + + /* + * per-elevator private data + */ + void *elevator_data; + + char queue_name[16]; }; -int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int); +int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct bio *); void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int); void elevator_noop_merge_req(struct request *, struct request *); -int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int); +int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct bio *); void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int); void elevator_linus_merge_req(struct request *, struct request *); +int elv_linus_init(request_queue_t *, elevator_t *); +void elv_linus_exit(request_queue_t *, elevator_t *); +struct request *elv_next_request_fn(request_queue_t *); +void elv_add_request_fn(request_queue_t *, struct request *,struct list_head *); +/* + * use the /proc/iosched interface, all the below is history -> + */ typedef struct blkelv_ioctl_arg_s { int queue_ID; int read_latency; int write_latency; int max_bomb_segments; } blkelv_ioctl_arg_t; - #define BLKELVGET _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t)) #define BLKELVSET _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t)) -extern int blkelvget_ioctl(elevator_t *, blkelv_ioctl_arg_t *); -extern int blkelvset_ioctl(elevator_t *, const blkelv_ioctl_arg_t *); - -extern void elevator_init(elevator_t *, elevator_t); +extern int elevator_init(request_queue_t *, elevator_t *, elevator_t, char *); +extern void elevator_exit(request_queue_t *, elevator_t *); /* * Return values from elevator merger @@ -81,6 +103,24 @@ static inline int elevator_request_latency(elevator_t * elevator, int rw) return latency; } +/* + * will change once we move to a more complex data structure than a simple + * list for pending requests + */ +#define elv_queue_empty(q) list_empty(&(q)->queue_head) + +/* + * elevator private data + */ +struct elv_linus_data { + unsigned long flags; +}; + +#define ELV_DAT(e) ((struct elv_linus_data *)(e)->elevator_data) + +#define ELV_LINUS_BACK_MERGE 1 +#define ELV_LINUS_FRONT_MERGE 2 + #define ELEVATOR_NOOP \ ((elevator_t) { \ 0, /* read_latency */ \ @@ -89,6 +129,10 @@ static inline int elevator_request_latency(elevator_t * elevator, int rw) elevator_noop_merge, /* elevator_merge_fn */ \ elevator_noop_merge_cleanup, /* elevator_merge_cleanup_fn */ \ elevator_noop_merge_req, /* elevator_merge_req_fn */ \ + elv_next_request_fn, \ + elv_add_request_fn, \ + elv_linus_init, \ + elv_linus_exit, \ }) #define ELEVATOR_LINUS \ @@ -99,6 +143,10 @@ static inline int elevator_request_latency(elevator_t * elevator, int rw) elevator_linus_merge, /* elevator_merge_fn */ \ elevator_linus_merge_cleanup, /* elevator_merge_cleanup_fn */ \ elevator_linus_merge_req, /* elevator_merge_req_fn */ \ + elv_next_request_fn, \ + elv_add_request_fn, \ + elv_linus_init, \ + elv_linus_exit, \ }) #endif diff --git a/include/linux/fs.h b/include/linux/fs.h index ae92cfec5208..95bfc30de8c9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -21,6 +21,7 @@ #include <linux/cache.h> #include <linux/stddef.h> #include <linux/string.h> +#include <linux/bio.h> #include <asm/atomic.h> #include <asm/bitops.h> @@ -74,6 +75,8 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #define FMODE_READ 1 #define FMODE_WRITE 2 +#define RW_MASK 1 +#define RWA_MASK 2 #define READ 0 #define WRITE 1 #define READA 2 /* read-ahead - don't block if no resources */ @@ -202,6 +205,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time; extern void update_atime (struct inode *); #define UPDATE_ATIME(inode) update_atime (inode) +extern void bio_hash_init(unsigned long); extern void buffer_init(unsigned long); extern void inode_init(unsigned long); extern void mnt_init(unsigned long); @@ -238,28 +242,24 @@ enum bh_state_bits { struct buffer_head { /* First cache line: */ struct buffer_head *b_next; /* Hash queue list */ - unsigned long b_blocknr; /* block number */ + sector_t b_blocknr; /* block number */ unsigned short b_size; /* block size */ unsigned short b_list; /* List that this buffer appears */ kdev_t b_dev; /* device (B_FREE = free) */ atomic_t b_count; /* users using this block */ - kdev_t b_rdev; /* Real device */ unsigned long b_state; /* buffer state bitmap (see above) */ unsigned long b_flushtime; /* Time when (dirty) buffer should be written */ struct buffer_head *b_next_free;/* lru/free list linkage */ struct buffer_head *b_prev_free;/* doubly linked list of buffers */ struct buffer_head *b_this_page;/* circular list of buffers in one page */ - struct buffer_head *b_reqnext; /* request queue */ - struct buffer_head **b_pprev; /* doubly linked list of hash-queue */ char * b_data; /* pointer to data block */ struct page *b_page; /* the page this bh is mapped to */ void (*b_end_io)(struct buffer_head *bh, int uptodate); /* I/O completion */ void *b_private; /* reserved for b_end_io */ - unsigned long b_rsector; /* Real buffer location on disk */ wait_queue_head_t b_wait; struct inode * b_inode; @@ -854,6 +854,8 @@ struct inode_operations { int (*getattr) (struct dentry *, struct iattr *); }; +struct seq_file; + /* * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called * without the big kernel lock held in all filesystems. @@ -905,6 +907,7 @@ struct super_operations { */ struct dentry * (*fh_to_dentry)(struct super_block *sb, __u32 *fh, int len, int fhtype, int parent); int (*dentry_to_fh)(struct dentry *, __u32 *fh, int *lenp, int need_parent); + int (*show_options)(struct seq_file *, struct vfsmount *); }; /* Inode state bits.. */ @@ -1170,12 +1173,25 @@ static inline void mark_buffer_async(struct buffer_head * bh, int on) static inline void buffer_IO_error(struct buffer_head * bh) { mark_buffer_clean(bh); + /* - * b_end_io has to clear the BH_Uptodate bitflag in the error case! + * b_end_io has to clear the BH_Uptodate bitflag in the read error + * case, however buffer contents are not necessarily bad if a + * write fails */ - bh->b_end_io(bh, 0); + bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); } +/* + * return READ, READA, or WRITE + */ +#define bio_rw(bio) ((bio)->bi_rw & (RW_MASK | RWA_MASK)) + +/* + * return data direction, READ or WRITE + */ +#define bio_data_dir(bio) ((bio)->bi_rw & 1) + extern void buffer_insert_inode_queue(struct buffer_head *, struct inode *); static inline void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode) { @@ -1343,10 +1359,11 @@ extern void insert_inode_hash(struct inode *); extern void remove_inode_hash(struct inode *); extern struct file * get_empty_filp(void); extern void file_move(struct file *f, struct list_head *list); -extern struct buffer_head * get_hash_table(kdev_t, int, int); -extern struct buffer_head * getblk(kdev_t, int, int); +extern struct buffer_head * get_hash_table(kdev_t, sector_t, int); +extern struct buffer_head * getblk(kdev_t, sector_t, int); extern void ll_rw_block(int, int, struct buffer_head * bh[]); -extern void submit_bh(int, struct buffer_head *); +extern int submit_bh(int, struct buffer_head *); +extern int submit_bio(int, struct bio *); extern int is_read_only(kdev_t); extern void __brelse(struct buffer_head *); static inline void brelse(struct buffer_head *buf) @@ -1366,9 +1383,9 @@ extern void wakeup_bdflush(void); extern void put_unused_buffer_head(struct buffer_head * bh); extern struct buffer_head * get_unused_buffer_head(int async); -extern int brw_page(int, struct page *, kdev_t, int [], int); +extern int brw_page(int, struct page *, kdev_t, sector_t [], int); -typedef int (get_block_t)(struct inode*,long,struct buffer_head*,int); +typedef int (get_block_t)(struct inode*,sector_t,struct buffer_head*,int); /* Generic buffer handling for block filesystems.. */ extern int try_to_release_page(struct page * page, int gfp_mask); @@ -1384,7 +1401,7 @@ extern int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*, extern int block_commit_write(struct page *page, unsigned from, unsigned to); extern int block_sync_page(struct page *); -int generic_block_bmap(struct address_space *, long, get_block_t *); +sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); int generic_commit_write(struct file *, struct page *, unsigned, unsigned); int block_truncate_page(struct address_space *, loff_t, get_block_t *); extern int generic_direct_IO(int, struct inode *, struct kiobuf *, unsigned long, int, get_block_t *); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 323a2a2f0974..18f8d66ebe91 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -86,11 +86,11 @@ struct gendisk { }; /* drivers/block/genhd.c */ -extern struct gendisk *gendisk_head; - extern void add_gendisk(struct gendisk *gp); extern void del_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(kdev_t dev); +extern unsigned long get_start_sect(kdev_t dev); +extern unsigned long get_nr_sects(kdev_t dev); #endif /* __KERNEL__ */ @@ -244,35 +244,10 @@ char *disk_name (struct gendisk *hd, int minor, char *buf); extern void devfs_register_partitions (struct gendisk *dev, int minor, int unregister); - - -/* - * FIXME: this should use genhd->minor_shift, but that is slow to look up. - */ static inline unsigned int disk_index (kdev_t dev) { - int major = MAJOR(dev); - int minor = MINOR(dev); - unsigned int index; - - switch (major) { - case DAC960_MAJOR+0: - index = (minor & 0x00f8) >> 3; - break; - case SCSI_DISK0_MAJOR: - index = (minor & 0x00f0) >> 4; - break; - case IDE0_MAJOR: /* same as HD_MAJOR */ - case XT_DISK_MAJOR: - index = (minor & 0x0040) >> 6; - break; - case IDE1_MAJOR: - index = ((minor & 0x0040) >> 6) + 2; - break; - default: - return 0; - } - return index; + struct gendisk *g = get_gendisk(dev); + return g ? (MINOR(dev) >> g->minor_shift) : 0; } #endif diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 1e2b8b1f4ae6..4c6cb50a8d46 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -13,8 +13,7 @@ extern struct page *highmem_start_page; /* declarations for linux/mm/highmem.c */ unsigned int nr_free_highpages(void); -extern struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig); - +extern void create_bounce(struct bio **bio_orig, int gfp_mask); static inline char *bh_kmap(struct buffer_head *bh) { @@ -26,6 +25,42 @@ static inline void bh_kunmap(struct buffer_head *bh) kunmap(bh->b_page); } +/* + * remember to add offset! and never ever reenable interrupts between a + * bio_kmap_irq and bio_kunmap_irq!! + */ +static inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags) +{ + unsigned long addr; + + __save_flags(*flags); + + /* + * could be low + */ + if (!PageHighMem(bio_page(bio))) + return bio_data(bio); + + /* + * it's a highmem page + */ + __cli(); + addr = (unsigned long) kmap_atomic(bio_page(bio), KM_BIO_IRQ); + + if (addr & ~PAGE_MASK) + BUG(); + + return (char *) addr + bio_offset(bio); +} + +static inline void bio_kunmap_irq(char *buffer, unsigned long *flags) +{ + unsigned long ptr = (unsigned long) buffer & PAGE_MASK; + + kunmap_atomic((void *) ptr, KM_BIO_IRQ); + __restore_flags(*flags); +} + #else /* CONFIG_HIGHMEM */ static inline unsigned int nr_free_highpages(void) { return 0; } @@ -40,6 +75,9 @@ static inline void *kmap(struct page *page) { return page_address(page); } #define bh_kmap(bh) ((bh)->b_data) #define bh_kunmap(bh) do { } while (0) +#define bio_kmap_irq(bio, flags) (bio_data(bio)) +#define bio_kunmap_irq(buf, flags) do { *(flags) = 0; } while (0) + #endif /* CONFIG_HIGHMEM */ /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 97e3831a455f..38a17222c225 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -149,6 +149,21 @@ typedef unsigned char byte; /* used everywhere */ #define DATA_READY (DRQ_STAT) /* + * Our Physical Region Descriptor (PRD) table should be large enough + * to handle the biggest I/O request we are likely to see. Since requests + * can have no more than 256 sectors, and since the typical blocksize is + * two or more sectors, we could get by with a limit of 128 entries here for + * the usual worst case. Most requests seem to include some contiguous blocks, + * further reducing the number of table entries required. + * + * As it turns out though, we must allocate a full 4KB page for this, + * so the two PRD tables (ide0 & ide1) will each get half of that, + * allowing each to have about 256 entries (8 bytes each) from this. + */ +#define PRD_BYTES 8 +#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) + +/* * Some more useful definitions */ #define IDE_MAJOR_NAME "hd" /* the same for all i/f; see also genhd.c */ @@ -223,6 +238,23 @@ typedef int (ide_ack_intr_t)(struct hwif_s *); #endif /* + * hwif_chipset_t is used to keep track of the specific hardware + * chipset used by each IDE interface, if known. + */ +typedef enum { ide_unknown, ide_generic, ide_pci, + ide_cmd640, ide_dtc2278, ide_ali14xx, + ide_qd65xx, ide_umc8672, ide_ht6560b, + ide_pdc4030, ide_rz1000, ide_trm290, + ide_cmd646, ide_cy82c693, ide_4drives, + ide_pmac, ide_etrax100 +} hwif_chipset_t; + +#define IDE_CHIPSET_PCI_MASK \ + ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx)) +#define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1) + + +/* * Structure to hold all information about the location of this port */ typedef struct hw_regs_s { @@ -231,6 +263,7 @@ typedef struct hw_regs_s { int dma; /* our dma entry */ ide_ack_intr_t *ack_intr; /* acknowledge interrupt */ void *priv; /* interface specific data */ + hwif_chipset_t chipset; } hw_regs_t; /* @@ -440,22 +473,6 @@ typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t); */ typedef int (ide_busproc_t) (struct hwif_s *, int); -/* - * hwif_chipset_t is used to keep track of the specific hardware - * chipset used by each IDE interface, if known. - */ -typedef enum { ide_unknown, ide_generic, ide_pci, - ide_cmd640, ide_dtc2278, ide_ali14xx, - ide_qd65xx, ide_umc8672, ide_ht6560b, - ide_pdc4030, ide_rz1000, ide_trm290, - ide_cmd646, ide_cy82c693, ide_4drives, - ide_pmac, ide_etrax100 -} hwif_chipset_t; - -#define IDE_CHIPSET_PCI_MASK \ - ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx)) -#define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1) - #ifdef CONFIG_BLK_DEV_IDEPCI typedef struct ide_pci_devid_s { unsigned short vid; @@ -488,7 +505,6 @@ typedef struct hwif_s { struct scatterlist *sg_table; /* Scatter-gather list used to build the above */ int sg_nents; /* Current number of entries in it */ int sg_dma_direction; /* dma transfer direction */ - int sg_dma_active; /* is it in use */ struct hwif_s *mate; /* other hwif from same PCI chip */ unsigned long dma_base; /* base addr for dma ports */ unsigned dma_extra; /* extra addr for dma ports */ @@ -507,6 +523,7 @@ typedef struct hwif_s { unsigned reset : 1; /* reset after probe */ unsigned autodma : 1; /* automatically try to enable DMA at boot */ unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */ + unsigned highmem : 1; /* can do full 32-bit dma */ byte channel; /* for dual-port chips: 0=primary, 1=secondary */ #ifdef CONFIG_BLK_DEV_IDEPCI struct pci_dev *pci_dev; /* for pci chipsets */ @@ -541,10 +558,12 @@ typedef ide_startstop_t (ide_handler_t)(ide_drive_t *); */ typedef int (ide_expiry_t)(ide_drive_t *); +#define IDE_BUSY 0 +#define IDE_SLEEP 1 + typedef struct hwgroup_s { ide_handler_t *handler;/* irq handler, if active */ - volatile int busy; /* BOOL: protects all fields below */ - int sleeping; /* BOOL: wake us up on timer expiry */ + unsigned long flags; /* BUSY, SLEEPING */ ide_drive_t *drive; /* current drive */ ide_hwif_t *hwif; /* ptr to current hwif in linked-list */ struct request *rq; /* current request */ @@ -711,7 +730,8 @@ extern int noautodma; #define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */ #include <linux/blk.h> -void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup); +inline int __ide_end_request(ide_hwgroup_t *, int, int); +int ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup); /* * This is used for (nearly) all data transfers from/to the IDE interface @@ -787,6 +807,11 @@ ide_drive_t *get_info_ptr (kdev_t i_rdev); unsigned long current_capacity (ide_drive_t *drive); /* + * Revalidate (read partition tables) + */ +void ide_revalidate_drive (ide_drive_t *drive); + +/* * Start a reset operation for an IDE interface. * The caller should return immediately after invoking this. */ @@ -814,6 +839,21 @@ typedef enum { } ide_action_t; /* + * temporarily mapping a (possible) highmem bio for PIO transfer + */ +#define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) + +extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags) +{ + return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); +} + +extern inline void ide_unmap_buffer(char *buffer, unsigned long *flags) +{ + bio_kunmap_irq(buffer, flags); +} + +/* * This function issues a special IDE device request * onto the request queue. * @@ -961,4 +1001,7 @@ unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char * void hwif_unregister (ide_hwif_t *hwif); +#define DRIVE_LOCK(drive) (&(drive)->queue.queue_lock) +extern spinlock_t ide_lock; + #endif /* _IDE_H */ diff --git a/include/linux/iobuf.h b/include/linux/iobuf.h index 619187efec8d..869b05dc6b80 100644 --- a/include/linux/iobuf.h +++ b/include/linux/iobuf.h @@ -28,7 +28,7 @@ #define KIO_STATIC_PAGES (KIO_MAX_ATOMIC_IO / (PAGE_SIZE >> 10) + 1) #define KIO_MAX_SECTORS (KIO_MAX_ATOMIC_IO * 2) -/* The main kiobuf struct used for all our IO! */ +/* The main kiobuf struct */ struct kiobuf { @@ -48,8 +48,7 @@ struct kiobuf /* Always embed enough struct pages for atomic IO */ struct page * map_array[KIO_STATIC_PAGES]; - struct buffer_head * bh[KIO_MAX_SECTORS]; - unsigned long blocks[KIO_MAX_SECTORS]; + sector_t blocks[KIO_MAX_SECTORS]; /* Dynamic state for IO completion: */ atomic_t io_count; /* IOs still in progress */ @@ -69,7 +68,7 @@ void mark_dirty_kiobuf(struct kiobuf *iobuf, int bytes); /* fs/iobuf.c */ -void end_kio_request(struct kiobuf *, int); +int end_kio_request(struct kiobuf *, int); void simple_wakeup_kiobuf(struct kiobuf *); int alloc_kiovec(int nr, struct kiobuf **); void free_kiovec(int nr, struct kiobuf **); @@ -81,6 +80,9 @@ extern void free_kiobuf_bhs(struct kiobuf *); /* fs/buffer.c */ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], - kdev_t dev, unsigned long b[], int size); + kdev_t dev, sector_t [], int size); + +/* fs/bio.c */ +void ll_rw_kio(int rw, struct kiobuf *kio, kdev_t dev, sector_t block); #endif /* __LINUX_IOBUF_H */ diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h index 55be4e5903fd..82dde80812ae 100644 --- a/include/linux/iso_fs.h +++ b/include/linux/iso_fs.h @@ -220,7 +220,7 @@ int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); extern struct dentry *isofs_lookup(struct inode *, struct dentry *); extern struct buffer_head *isofs_bread(struct inode *, unsigned int, unsigned int); -extern int isofs_get_blocks(struct inode *, long, struct buffer_head **, unsigned long); +extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); extern struct inode_operations isofs_dir_inode_operations; extern struct file_operations isofs_dir_operations; diff --git a/include/linux/loop.h b/include/linux/loop.h index 11622345f2f9..4e86b0dcefb4 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h @@ -49,8 +49,8 @@ struct loop_device { int old_gfp_mask; spinlock_t lo_lock; - struct buffer_head *lo_bh; - struct buffer_head *lo_bhtail; + struct bio *lo_bio; + struct bio *lo_biotail; int lo_state; struct semaphore lo_sem; struct semaphore lo_ctl_mutex; diff --git a/include/linux/lvm.h b/include/linux/lvm.h index b3e68a6db266..226e267fd07f 100644 --- a/include/linux/lvm.h +++ b/include/linux/lvm.h @@ -468,6 +468,12 @@ typedef struct lv_bmap { } lv_bmap_t; /* + * fixme... + */ +#define LVM_MAX_ATOMIC_IO 512 +#define LVM_MAX_SECTORS (LVM_MAX_ATOMIC_IO * 2) + +/* * Structure Logical Volume (LV) Version 3 */ @@ -505,6 +511,7 @@ typedef struct lv_v5 { uint lv_snapshot_minor; #ifdef __KERNEL__ struct kiobuf *lv_iobuf; + sector_t blocks[LVM_MAX_SECTORS]; struct kiobuf *lv_COW_table_iobuf; struct rw_semaphore lv_lock; struct list_head *lv_snapshot_hash_table; diff --git a/include/linux/nbd.h b/include/linux/nbd.h index b34d4d18d8f9..0dbf87851169 100644 --- a/include/linux/nbd.h +++ b/include/linux/nbd.h @@ -37,24 +37,25 @@ extern int requests_out; static void nbd_end_request(struct request *req) { - struct buffer_head *bh; + struct bio *bio; unsigned nsect; unsigned long flags; int uptodate = (req->errors == 0) ? 1 : 0; + request_queue_t *q = req->q; #ifdef PARANOIA requests_out++; #endif - spin_lock_irqsave(&io_request_lock, flags); - while((bh = req->bh) != NULL) { - nsect = bh->b_size >> 9; + spin_lock_irqsave(&q->queue_lock, flags); + while((bio = req->bio) != NULL) { + nsect = bio_sectors(bio); blk_finished_io(nsect); - req->bh = bh->b_reqnext; - bh->b_reqnext = NULL; - bh->b_end_io(bh, uptodate); + req->bio = bio->bi_next; + bio->bi_next = NULL; + bio_endio(bio, uptodate, nsect); } blkdev_release_request(req); - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&q->queue_lock, flags); } #define MAX_NBD 128 diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index b53549dda951..5382bc072c3d 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -220,7 +220,7 @@ struct mddev_s struct mdk_personality_s { char *name; - int (*make_request)(mddev_t *mddev, int rw, struct buffer_head * bh); + int (*make_request)(mddev_t *mddev, int rw, struct bio *bio); int (*run)(mddev_t *mddev); int (*stop)(mddev_t *mddev); int (*status)(char *page, mddev_t *mddev); diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 9a1be8145a7d..cc6b767a6640 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1856,7 +1856,7 @@ void make_le_item_head (struct item_head * ih, const struct cpu_key * key, loff_t offset, int type, int length, int entry_count); /*void store_key (struct key * key); void forget_key (struct key * key);*/ -int reiserfs_get_block (struct inode * inode, long block, +int reiserfs_get_block (struct inode * inode, sector_t block, struct buffer_head * bh_result, int create); struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key); diff --git a/include/linux/slab.h b/include/linux/slab.h index efa8638d612b..ed4ff483974c 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -38,6 +38,7 @@ typedef struct kmem_cache_s kmem_cache_t; #define SLAB_NO_REAP 0x00001000UL /* never reap from the cache */ #define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */ #define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */ +#define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */ /* flags passed to a constructor func */ #define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */ @@ -76,6 +77,7 @@ extern kmem_cache_t *dquot_cachep; extern kmem_cache_t *bh_cachep; extern kmem_cache_t *fs_cachep; extern kmem_cache_t *sigact_cachep; +extern kmem_cache_t *bio_cachep; #endif /* __KERNEL__ */ diff --git a/include/linux/types.h b/include/linux/types.h index df4808fcdf45..211461bc97c0 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -113,6 +113,17 @@ typedef __u64 u_int64_t; typedef __s64 int64_t; #endif +/* + * transition to 64-bit sector_t, possibly making it an option... + */ +#undef BLK_64BIT_SECTOR + +#ifdef BLK_64BIT_SECTOR +typedef u64 sector_t; +#else +typedef unsigned long sector_t; +#endif + #endif /* __KERNEL_STRICT_NAMES */ /* |
