summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 23:58:06 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 23:58:06 -0800
commite1e2cfc3fb42dbe54dd94fe97ba17a62cd7a265b (patch)
tree2cd3cb5d9f2c43fb7939bd95bdef808d113bc042 /include/linux
parent3735375e3fd2f2286c1dc2f0131f39d438ae9a5c (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.h230
-rw-r--r--include/linux/blk.h44
-rw-r--r--include/linux/blkdev.h216
-rw-r--r--include/linux/bootmem.h5
-rw-r--r--include/linux/devfs_fs_kernel.h2
-rw-r--r--include/linux/elevator.h68
-rw-r--r--include/linux/fs.h43
-rw-r--r--include/linux/genhd.h33
-rw-r--r--include/linux/highmem.h42
-rw-r--r--include/linux/ide.h83
-rw-r--r--include/linux/iobuf.h12
-rw-r--r--include/linux/iso_fs.h2
-rw-r--r--include/linux/loop.h4
-rw-r--r--include/linux/lvm.h7
-rw-r--r--include/linux/nbd.h17
-rw-r--r--include/linux/raid/md_k.h2
-rw-r--r--include/linux/reiserfs_fs.h2
-rw-r--r--include/linux/slab.h2
-rw-r--r--include/linux/types.h11
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 */
/*