summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
commit46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch)
tree3b9b51fc482e729f663d25333e77fbed9aaa939a /drivers/block
parent31dc59d503a02e84c4de98826452acaeb56dc15a (diff)
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in36
-rw-r--r--drivers/block/ll_rw_blk.c34
-rw-r--r--drivers/block/lvm.c2
-rw-r--r--drivers/block/md.c213
-rw-r--r--drivers/block/nbd.c8
-rw-r--r--drivers/block/paride/pcd.c2
-rw-r--r--drivers/block/paride/pd.c76
-rw-r--r--drivers/block/paride/pf.c76
-rw-r--r--drivers/block/rd.c3
-rw-r--r--drivers/block/xd.c43
10 files changed, 390 insertions, 103 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index cadc7eca7..146cbce88 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -12,9 +12,7 @@ if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY
fi
if [ "$CONFIG_MAC" = "y" ]; then
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP
- fi
+ dep_bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP $CONFIG_EXPERIMENTAL
fi
if [ "$CONFIG_MCA" = "y" ]; then
tristate 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2
@@ -30,36 +28,28 @@ if [ "$CONFIG_ATARI" = "y" ]; then
tristate ' Atari SLM laser printer support' CONFIG_ATARI_SLM
fi
fi
-tristate 'XT hard disk support' CONFIG_BLK_DEV_XD
+dep_tristate 'XT hard disk support' CONFIG_BLK_DEV_XD $CONFIG_ISA
dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARPORT
if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
source drivers/block/paride/Config.in
fi
-
-if [ "$CONFIG_PCI" = "y" ]; then
- tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA
- tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960
-fi
+dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI
+dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
comment 'Additional Block Devices'
tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-if [ "$CONFIG_NET" = "y" ]; then
- tristate 'Network block device support' CONFIG_BLK_DEV_NBD
-fi
+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
+
bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
-if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
- tristate ' Linear (append) mode' CONFIG_MD_LINEAR
- tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED
-# tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
-# tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
+dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD
+dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED $CONFIG_BLK_DEV_MD
+#dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING $CONFIG_BLK_DEV_MD
+#dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD
+if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then
+ bool ' Boot support (linear, striped)' CONFIG_MD_BOOT
fi
-#if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then
-# bool ' Boot support (linear, striped)' CONFIG_MD_BOOT
-#fi
tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
-if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
- bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
-fi
+dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
endmenu
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 431860f44..4adbbb313 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -481,7 +481,7 @@ static void attempt_merge(request_queue_t * q,
elevator_merge_requests(&q->elevator, req, next);
req->bhtail->b_reqnext = next->bh;
req->bhtail = next->bhtail;
- req->nr_sectors += next->nr_sectors;
+ req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
next->rq_status = RQ_INACTIVE;
list_del(&next->queue);
wake_up (&wait_for_request);
@@ -685,7 +685,7 @@ static inline void __make_request(request_queue_t * q, int rw,
break;
req->bhtail->b_reqnext = bh;
req->bhtail = bh;
- req->nr_sectors += count;
+ req->nr_sectors = req->hard_nr_sectors += count;
drive_stat_acct(req, count, 0);
elevator_merge_after(elevator, req, latency);
@@ -714,8 +714,8 @@ static inline void __make_request(request_queue_t * q, int rw,
req->bh = bh;
req->buffer = bh->b_data;
req->current_nr_sectors = count;
- req->sector = sector;
- req->nr_sectors += count;
+ req->sector = req->hard_sector = sector;
+ req->nr_sectors = req->hard_nr_sectors += count;
drive_stat_acct(req, count, 0);
elevator_merge_before(elevator, req, latency);
@@ -754,8 +754,8 @@ get_rq:
/* fill up the request-info, and add it to the queue */
req->cmd = rw;
req->errors = 0;
- req->sector = sector;
- req->nr_sectors = count;
+ req->hard_sector = req->sector = sector;
+ req->hard_nr_sectors = req->nr_sectors = count;
req->current_nr_sectors = count;
req->nr_segments = 1; /* Always 1 for a new request. */
req->nr_hw_segments = 1; /* Always 1 for a new request. */
@@ -920,23 +920,21 @@ int end_that_request_first (struct request *req, int uptodate, char *name)
int nsect;
req->errors = 0;
- if (!uptodate) {
+ if (!uptodate)
printk("end_request: I/O error, dev %s (%s), sector %lu\n",
kdevname(req->rq_dev), name, req->sector);
- if ((bh = req->bh) != NULL) {
- nsect = bh->b_size >> 9;
- req->nr_sectors--;
- req->nr_sectors &= ~(nsect - 1);
- req->sector += nsect;
- req->sector &= ~(nsect - 1);
- }
- }
if ((bh = req->bh) != NULL) {
+ nsect = bh->b_size >> 9;
req->bh = bh->b_reqnext;
bh->b_reqnext = NULL;
bh->b_end_io(bh, uptodate);
if ((bh = req->bh) != NULL) {
+ req->hard_sector += nsect;
+ req->hard_nr_sectors -= nsect;
+ req->sector = req->hard_sector;
+ req->nr_sectors = req->hard_nr_sectors;
+
req->current_nr_sectors = bh->b_size >> 9;
if (req->nr_sectors < req->current_nr_sectors) {
req->nr_sectors = req->current_nr_sectors;
@@ -1073,6 +1071,12 @@ int __init blk_dev_init(void)
#ifdef CONFIG_BLK_DEV_NBD
nbd_init();
#endif
+#ifdef CONFIG_MDISK
+ mdisk_init();
+#endif
+#ifdef CONFIG_DASD
+ dasd_init();
+#endif
return 0;
};
diff --git a/drivers/block/lvm.c b/drivers/block/lvm.c
index 0986ff7df..0c590db73 100644
--- a/drivers/block/lvm.c
+++ b/drivers/block/lvm.c
@@ -931,7 +931,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
printk(KERN_DEBUG
"%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name);
#endif
- if (put_user(lv->lv_read_ahead, (long *)arg))
+ if (put_user(lv_ptr->lv_read_ahead, (long *)arg))
return -EFAULT;
break;
diff --git a/drivers/block/md.c b/drivers/block/md.c
index dd8a83764..48796b402 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -1805,6 +1805,136 @@ out:
#undef OUT
+/* support old ioctls/init - cold add only */
+int do_md_add(mddev_t *mddev, kdev_t dev)
+{
+ int err;
+ mdk_rdev_t *rdev;
+
+ if (mddev->sb || mddev->pers)
+ return -EBUSY;
+ err = md_import_device(dev, 0);
+ if (err) return err;
+ rdev = find_rdev_all(dev);
+ if (!rdev) {
+ MD_BUG();
+ return -EINVAL;
+ }
+ rdev->old_dev = dev;
+ rdev->desc_nr = mddev->nb_dev;
+ bind_rdev_to_array(rdev, mddev);
+ return 0;
+}
+
+#define SET_SB(x,v) mddev->sb->x = v
+#define SET_RSB(x,y) mddev->sb->disks[nr].x = y
+static void autorun_array (mddev_t *mddev);
+int do_md_start(mddev_t *mddev, int info)
+{
+ int pers = (info & 0xFF0000UL)>>16;
+// int fault= (info & 0x00FF00UL)>>8;
+ int factor=(info & 0x0000FFUL);
+
+ struct md_list_head *tmp;
+ mdk_rdev_t *rdev, *rdev0=NULL;
+ int err = 0;
+
+ if (mddev->sb) {
+ printk("array md%d already has superbloc!!\n",
+ mdidx(mddev));
+ return -EBUSY;
+ }
+ if (pers==1 || pers==2) {
+ /* non-persistant super block */
+ int devs = mddev->nb_dev;
+ if (alloc_array_sb(mddev))
+ return -ENOMEM;
+ mddev->sb->major_version = MD_MAJOR_VERSION;
+ mddev->sb->minor_version = MD_MINOR_VERSION;
+ mddev->sb->patch_version = MD_PATCHLEVEL_VERSION;
+ mddev->sb->ctime = CURRENT_TIME;
+
+ SET_SB(level,pers_to_level(pers));
+ SET_SB(size,0);
+ SET_SB(nr_disks, devs);
+ SET_SB(raid_disks, devs);
+ SET_SB(md_minor,mdidx(mddev));
+ SET_SB(not_persistent, 1);
+
+
+ SET_SB(state, 1<<MD_SB_CLEAN);
+ SET_SB(active_disks, devs);
+ SET_SB(working_disks, devs);
+ SET_SB(failed_disks, 0);
+ SET_SB(spare_disks, 0);
+
+ SET_SB(layout,0);
+ SET_SB(chunk_size, 1<<(factor+PAGE_SHIFT));
+
+ mddev->sb->md_magic = MD_SB_MAGIC;
+
+ /*
+ * Generate a 128 bit UUID
+ */
+ get_random_bytes(&mddev->sb->set_uuid0, 4);
+ get_random_bytes(&mddev->sb->set_uuid1, 4);
+ get_random_bytes(&mddev->sb->set_uuid2, 4);
+ get_random_bytes(&mddev->sb->set_uuid3, 4);
+
+ /* add each disc */
+ ITERATE_RDEV(mddev,rdev,tmp) {
+ int nr, size;
+ nr = rdev->desc_nr;
+ SET_RSB(number,nr);
+ SET_RSB(major,MAJOR(rdev->dev));
+ SET_RSB(minor,MINOR(rdev->dev));
+ SET_RSB(raid_disk,nr);
+ SET_RSB(state,6); /* ACTIVE|SYNC */
+ size = calc_dev_size(rdev->dev, mddev, 0);
+ rdev->sb_offset = calc_dev_sboffset(rdev->dev, mddev, 0);
+
+ if (!mddev->sb->size || (mddev->sb->size > size))
+ mddev->sb->size = size;
+ }
+ sync_sbs(mddev);
+ err = do_md_run(mddev);
+ if (err)
+ do_md_stop(mddev, 0);
+ } else {
+ /* persistant super block - ignore the info and read the superblocks */
+ ITERATE_RDEV(mddev,rdev,tmp) {
+ if ((err = read_disk_sb(rdev))) {
+ printk("md: could not read %s's sb, not importing!\n",
+ partition_name(rdev->dev));
+ break;
+ }
+ if ((err = check_disk_sb(rdev))) {
+ printk("md: %s has invalid sb, not importing!\n",
+ partition_name(rdev->dev));
+ break;
+ }
+ rdev->desc_nr = rdev->sb->this_disk.number;
+ if (!rdev0) rdev0=rdev;
+ if (!uuid_equal(rdev0, rdev)) {
+ printk("%s has different UUID to %s .. dropping\n",
+ partition_name(rdev->dev),
+ partition_name(rdev0->dev));
+ err = -EINVAL;
+ break;
+ }
+ if (!sb_equal(rdev0->sb, rdev->sb)) {
+ printk("%s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+ err = -EINVAL;
+ break;
+ }
+ }
+ if (!err)
+ autorun_array(mddev);
+ }
+ return err;
+}
+#undef SET_SB
+#undef SET_RSB
/*
* We have to safely support old arrays too.
*/
@@ -2573,6 +2703,58 @@ static int md_ioctl (struct inode *inode, struct file *file,
}
default:
}
+ /* handle "old style" ioctls */
+ switch (cmd)
+ {
+ case START_MD:
+ if (!mddev)
+ return -ENODEV;
+ err = lock_mddev(mddev);
+ if (err) {
+ printk("ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);
+ goto abort;
+ }
+ err = do_md_start(mddev, (int) arg);
+ if (err) {
+ printk("couldn't mdstart\n");
+ goto abort_unlock;
+ }
+ goto done_unlock;
+ case STOP_MD:
+ if (!mddev)
+ return -ENODEV;
+ err = lock_mddev(mddev);
+ if (err) {
+ printk("ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);
+ goto abort_unlock;
+ }
+ err = do_md_stop(mddev, 0);
+ if (err) {
+ printk("couldn't mdstop\n");
+ goto abort_unlock;
+ }
+ goto done_unlock;
+ case REGISTER_DEV:
+ /* add this device to an unstarted array,
+ * create the array if needed */
+ if (!mddev)
+ mddev = alloc_mddev(dev);
+ if (!mddev) {
+ err = -ENOMEM;
+ goto abort;
+ }
+ err = lock_mddev(mddev);
+ if (err) {
+ printk("ioctl, reason %d, cmd %d\n", err, cmd);
+ goto abort;
+ }
+ err = do_md_add(mddev, to_kdev_t((dev_t) arg));
+ if (err) {
+ printk("do_md_add failed %d\n", err);
+ goto abort_unlock;
+ }
+ goto done_unlock;
+ }
switch (cmd)
{
@@ -2593,7 +2775,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
err = set_array_info(mddev, (void *)arg);
if (err) {
printk("couldnt set array info. %d\n", err);
- goto abort;
+ goto abort_unlock;
}
goto done_unlock;
@@ -3188,10 +3370,11 @@ void md__init raid_setup(char *str, int *ints)
}
#ifdef CONFIG_MD_BOOT
+#define MAX_MD_BOOT_DEVS 16
struct {
unsigned long set;
- int pers[MAX_MD_DEVS];
- kdev_t devices[MAX_MD_DEVS][MAX_REAL];
+ int pers[MAX_MD_BOOT_DEVS];
+ kdev_t devices[MAX_MD_BOOT_DEVS][MAX_REAL];
} md_setup_args md__initdata = {
0,{0},{{0}}
};
@@ -3219,7 +3402,7 @@ static int __init md_setup(char *str)
get_option(&str, &fault) != 2) {
printk("md: Too few arguments supplied to md=.\n");
return 0;
- } else if (minor >= MAX_MD_DEVS) {
+ } else if (minor >= MAX_MD_BOOT_DEVS) {
printk ("md: Minor device number too high.\n");
return 0;
} else if (md_setup_args.set & (1 << minor)) {
@@ -3229,13 +3412,13 @@ static int __init md_setup(char *str)
switch(level) {
#ifdef CONFIG_MD_LINEAR
case -1:
- level = LINEAR;
+ level = LINEAR<<16;
pername = "linear";
break;
#endif
#ifdef CONFIG_MD_STRIPED
case 0:
- level = STRIPED;
+ level = STRIPED<<16;
pername = "striped";
break;
#endif
@@ -3263,9 +3446,9 @@ static int __init md_setup(char *str)
printk ("md: Will configure md%d (%s) from %s, below.\n",
minor, pername, devnames);
md_setup_args.devices[minor][i] = (kdev_t) 0;
- md_setup_args.pers[minor] = level | factor | (fault << FAULT_SHIFT);
+ md_setup_args.pers[minor] = level | factor | (fault << 8);
md_setup_args.set |= (1 << minor);
- return 0;
+ return 1;
}
#endif
@@ -3273,7 +3456,7 @@ static void md_geninit (void)
{
int i;
- for(i = 0; i < MAX_MD_DEVS; i++) {
+ for(i = 0; i < MAX_MD_BOOT_DEVS; i++) {
md_blocksizes[i] = 1024;
md_size[i] = 0;
md_maxreadahead[i] = MD_READAHEAD;
@@ -3344,20 +3527,20 @@ int md__init md_init (void)
}
#ifdef CONFIG_MD_BOOT
-static void __init md_setup_drive(void)
+void __init md_setup_drive(void)
{
- if(md_setup_args.set)
- do_md_setup(md_setup_args.str, md_setup_args.ints);
int minor, i;
kdev_t dev;
+ mddev_t*mddev;
- for (minor = 0; minor < MAX_MD_DEVS; minor++) {
+ for (minor = 0; minor < MAX_MD_BOOT_DEVS; minor++) {
if ((md_setup_args.set & (1 << minor)) == 0)
continue;
printk("md: Loading md%d.\n", minor);
+ mddev = alloc_mddev(MKDEV(MD_MAJOR,minor));
for (i = 0; (dev = md_setup_args.devices[minor][i]); i++)
- do_md_add (minor, dev);
- do_md_run (minor, md_setup_args.pers[minor]);
+ do_md_add (mddev, dev);
+ do_md_start (mddev, md_setup_args.pers[minor]);
}
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0c3f5429f..b21be6bd2 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -350,6 +350,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
{
struct nbd_device *lo;
int dev, error, temp;
+ struct request sreq ;
/* Anyone capable of this syscall can do *real bad* things */
@@ -363,6 +364,13 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
lo = &nbd_dev[dev];
switch (cmd) {
+ case NBD_DISCONNECT:
+ printk("NBD_DISCONNECT\n") ;
+ sreq.cmd=2 ; /* shutdown command */
+ if (!lo->sock) return -EINVAL ;
+ nbd_send_req(lo->sock,&sreq) ;
+ return 0 ;
+
case NBD_CLEAR_SOCK:
down(&lo->queue_lock);
nbd_clear_que(lo);
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 878709944..38279282f 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -765,7 +765,7 @@ static void do_pcd_request (request_queue_t * q)
pcd_unit = unit;
}
pcd_sector = CURRENT->sector;
- pcd_count = CURRENT->nr_sectors;
+ pcd_count = CURRENT->current_nr_sectors;
pcd_buf = CURRENT->buffer;
pcd_busy = 1;
ps_set_intr(do_pcd_read,0,0,nice);
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index f40958ecd..4676250dd 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -385,9 +385,62 @@ void pd_init_units( void )
}
}
+static inline int pd_new_segment(request_queue_t *q, struct request *req, int max_segments)
+{
+ if (max_segments > cluster)
+ max_segments = cluster;
+
+ if (req->nr_segments < max_segments) {
+ req->nr_segments++;
+ q->elevator.nr_segments++;
+ return 1;
+ }
+ return 0;
+}
+
+static int pd_back_merge_fn(request_queue_t *q, struct request *req,
+ struct buffer_head *bh, int max_segments)
+{
+ if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data)
+ return 1;
+ return pd_new_segment(q, req, max_segments);
+}
+
+static int pd_front_merge_fn(request_queue_t *q, struct request *req,
+ struct buffer_head *bh, int max_segments)
+{
+ if (bh->b_data + bh->b_size == req->bh->b_data)
+ return 1;
+ return pd_new_segment(q, req, max_segments);
+}
+
+static int pd_merge_requests_fn(request_queue_t *q, struct request *req,
+ struct request *next, int max_segments)
+{
+ int total_segments = req->nr_segments + next->nr_segments;
+ int same_segment;
+
+ if (max_segments > cluster)
+ max_segments = cluster;
+
+ same_segment = 0;
+ if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) {
+ total_segments--;
+ same_segment = 1;
+ }
+
+ if (total_segments > max_segments)
+ return 0;
+
+ q->elevator.nr_segments -= same_segment;
+ req->nr_segments = total_segments;
+ return 1;
+}
+
int pd_init (void)
{ int i;
+ request_queue_t * q;
if (disable) return -1;
if (devfs_register_blkdev(MAJOR_NR,name,&pd_fops)) {
@@ -395,7 +448,11 @@ int pd_init (void)
name,major);
return -1;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ q = BLK_DEFAULT_QUEUE(MAJOR_NR);
+ blk_init_queue(q, DEVICE_REQUEST);
+ q->back_merge_fn = pd_back_merge_fn;
+ q->front_merge_fn = pd_front_merge_fn;
+ q->merge_requests_fn = pd_merge_requests_fn;
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
pd_gendisk.major = major;
@@ -865,7 +922,6 @@ static int pd_ready( void )
static void do_pd_request (request_queue_t * q)
{ struct buffer_head * bh;
- struct request * req;
int unit;
if (pd_busy) return;
@@ -876,12 +932,10 @@ repeat:
pd_dev = MINOR(CURRENT->rq_dev);
pd_unit = unit = DEVICE_NR(CURRENT->rq_dev);
pd_block = CURRENT->sector;
- pd_count = CURRENT->nr_sectors;
+ pd_run = CURRENT->nr_sectors;
+ pd_count = CURRENT->current_nr_sectors;
bh = CURRENT->bh;
- req = CURRENT;
- if (bh->b_reqnext)
- printk("%s: OUCH: b_reqnext != NULL\n",PD.name);
if ((pd_dev >= PD_DEVS) ||
((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) {
@@ -890,14 +944,6 @@ repeat:
}
pd_cmd = CURRENT->cmd;
- pd_run = pd_count;
- while ((pd_run <= cluster) &&
- (req = blkdev_next_request(req)) &&
- (pd_block+pd_run == req->sector) &&
- (pd_cmd == req->cmd) &&
- (pd_dev == MINOR(req->rq_dev)))
- pd_run += req->nr_sectors;
-
pd_poffs = pd_hd[pd_dev].start_sect;
pd_block += pd_poffs;
pd_buf = CURRENT->buffer;
@@ -932,7 +978,7 @@ static void pd_next_buf( int unit )
printk("%s: OUCH: request list changed unexpectedly\n",
PD.name);
- pd_count = CURRENT->nr_sectors;
+ pd_count = CURRENT->current_nr_sectors;
pd_buf = CURRENT->buffer;
spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 4e7a5aaf4..53f6ca3df 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -339,9 +339,62 @@ void pf_init_units( void )
}
}
+static inline int pf_new_segment(request_queue_t *q, struct request *req, int max_segments)
+{
+ if (max_segments > cluster)
+ max_segments = cluster;
+
+ if (req->nr_segments < max_segments) {
+ req->nr_segments++;
+ q->elevator.nr_segments++;
+ return 1;
+ }
+ return 0;
+}
+
+static int pf_back_merge_fn(request_queue_t *q, struct request *req,
+ struct buffer_head *bh, int max_segments)
+{
+ if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data)
+ return 1;
+ return pf_new_segment(q, req, max_segments);
+}
+
+static int pf_front_merge_fn(request_queue_t *q, struct request *req,
+ struct buffer_head *bh, int max_segments)
+{
+ if (bh->b_data + bh->b_size == req->bh->b_data)
+ return 1;
+ return pf_new_segment(q, req, max_segments);
+}
+
+static int pf_merge_requests_fn(request_queue_t *q, struct request *req,
+ struct request *next, int max_segments)
+{
+ int total_segments = req->nr_segments + next->nr_segments;
+ int same_segment;
+
+ if (max_segments > cluster)
+ max_segments = cluster;
+
+ same_segment = 0;
+ if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) {
+ total_segments--;
+ same_segment = 1;
+ }
+
+ if (total_segments > max_segments)
+ return 0;
+
+ q->elevator.nr_segments -= same_segment;
+ req->nr_segments = total_segments;
+ return 1;
+}
+
int pf_init (void) /* preliminary initialisation */
{ int i;
+ request_queue_t * q;
if (disable) return -1;
@@ -355,7 +408,11 @@ int pf_init (void) /* preliminary initialisation */
major);
return -1;
}
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ q = BLK_DEFAULT_QUEUE(MAJOR_NR);
+ blk_init_queue(q, DEVICE_REQUEST);
+ q->back_merge_fn = pf_back_merge_fn;
+ q->front_merge_fn = pf_front_merge_fn;
+ q->merge_requests_fn = pf_merge_requests_fn;
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
for (i=0;i<PF_UNITS;i++) pf_blocksizes[i] = 1024;
@@ -849,7 +906,6 @@ static int pf_ready( void )
static void do_pf_request (request_queue_t * q)
{ struct buffer_head * bh;
- struct request * req;
int unit;
if (pf_busy) return;
@@ -859,12 +915,10 @@ repeat:
pf_unit = unit = DEVICE_NR(CURRENT->rq_dev);
pf_block = CURRENT->sector;
- pf_count = CURRENT->nr_sectors;
+ pf_run = CURRENT->nr_sectors;
+ pf_count = CURRENT->current_nr_sectors;
bh = CURRENT->bh;
- req = CURRENT;
- if (bh->b_reqnext)
- printk("%s: OUCH: b_reqnext != NULL\n",PF.name);
if ((pf_unit >= PF_UNITS) || (pf_block+pf_count > PF.capacity)) {
end_request(0);
@@ -872,14 +926,6 @@ repeat:
}
pf_cmd = CURRENT->cmd;
- pf_run = pf_count;
- while ((pf_run <= cluster) &&
- (req = blkdev_next_request(req)) &&
- (pf_block+pf_run == req->sector) &&
- (pf_cmd == req->cmd) &&
- (pf_unit == DEVICE_NR(req->rq_dev)))
- pf_run += req->nr_sectors;
-
pf_buf = CURRENT->buffer;
pf_retries = 0;
@@ -912,7 +958,7 @@ static void pf_next_buf( int unit )
printk("%s: OUCH: request list changed unexpectedly\n",
PF.name);
- pf_count = CURRENT->nr_sectors;
+ pf_count = CURRENT->current_nr_sectors;
pf_buf = CURRENT->buffer;
spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index a51dcd36f..11a06ef61 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -333,7 +333,8 @@ static int rd_open(struct inode * inode, struct file * filp)
* Immunize device against invalidate_buffers() and prune_icache().
*/
if (rd_inode[DEVICE_NR(inode->i_rdev)] == NULL) {
- if((rd_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != NULL)
+ if (!inode->i_bdev) return -ENXIO;
+ if ((rd_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != NULL)
atomic_inc(&rd_inode[DEVICE_NR(inode->i_rdev)]->i_bdev->bd_openers);
}
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index fde487ecd..65d87930d 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -1059,7 +1059,7 @@ static void __init xd_override_init_drive (u_char drive)
}
/* xd_setup: initialise controler from command line parameters */
-void __init xd_setup (char *command,int *integers)
+void __init do_xd_setup (int *integers)
{
switch (integers[0]) {
case 4: if (integers[4] < 0)
@@ -1079,21 +1079,6 @@ void __init xd_setup (char *command,int *integers)
xd_maxsectors = 0x01;
}
-#ifndef MODULE
-/* xd_manual_geo_init: initialise drive geometry from command line parameters
- (used only for WD drives) */
-void __init xd_manual_geo_init (char *command,int *integers)
-{
- int i;
- if (integers[0]%3 != 0) {
- printk("xd: incorrect number of parameters for xd_geo\n");
- return;
- }
- for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++)
- xd_geo[i] = integers[i+1];
-}
-#endif /* MODULE */
-
/* xd_setparam: set the drive characteristics */
static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)
{
@@ -1149,7 +1134,7 @@ int init_module(void)
if(((xd[i] = xd[i-1]) >= 0) && !count)
count = i;
if((xd[0] = count))
- xd_setup(NULL, xd);
+ do_xd_setup(xd);
if (error = xd_init())
return error;
@@ -1191,6 +1176,30 @@ void cleanup_module(void)
}
#else
+static int __init xd_setup (char *str)
+{
+ int ints[5];
+ get_options (str, ARRAY_SIZE (ints), ints);
+ do_xd_setup (ints);
+ return 1;
+}
+
+/* xd_manual_geo_init: initialise drive geometry from command line parameters
+ (used only for WD drives) */
+static int __init xd_manual_geo_init (char *str)
+{
+ int i, integers[1 + 3*XD_MAXDRIVES];
+
+ get_options (str, ARRAY_SIZE (ints), ints);
+ if (integers[0]%3 != 0) {
+ printk("xd: incorrect number of parameters for xd_geo\n");
+ return 1;
+ }
+ for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++)
+ xd_geo[i] = integers[i+1];
+ return 1;
+}
+
__setup ("xd=", xd_setup);
__setup ("xd_geo=", xd_manual_geo_init);