diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
commit | 46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch) | |
tree | 3b9b51fc482e729f663d25333e77fbed9aaa939a /drivers/block | |
parent | 31dc59d503a02e84c4de98826452acaeb56dc15a (diff) |
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/Config.in | 36 | ||||
-rw-r--r-- | drivers/block/ll_rw_blk.c | 34 | ||||
-rw-r--r-- | drivers/block/lvm.c | 2 | ||||
-rw-r--r-- | drivers/block/md.c | 213 | ||||
-rw-r--r-- | drivers/block/nbd.c | 8 | ||||
-rw-r--r-- | drivers/block/paride/pcd.c | 2 | ||||
-rw-r--r-- | drivers/block/paride/pd.c | 76 | ||||
-rw-r--r-- | drivers/block/paride/pf.c | 76 | ||||
-rw-r--r-- | drivers/block/rd.c | 3 | ||||
-rw-r--r-- | drivers/block/xd.c | 43 |
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); |