summaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-10 05:27:25 +0000
commitc9c06167e7933d93a6e396174c68abf242294abb (patch)
treed9a8bb30663e9a3405a1ef37ffb62bc14b9f019f /drivers/md
parentf79e8cc3c34e4192a3e5ef4cc9c6542fdef703c0 (diff)
Merge with Linux 2.4.0-test12.
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/Makefile18
-rw-r--r--drivers/md/linear.c36
-rw-r--r--drivers/md/lvm.c7
-rw-r--r--drivers/md/md.c106
-rw-r--r--drivers/md/raid0.c29
-rw-r--r--drivers/md/raid1.c173
-rw-r--r--drivers/md/raid5.c19
-rw-r--r--drivers/md/xor.c1
8 files changed, 182 insertions, 207 deletions
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 69d65c2bd..c37ce84db 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -16,18 +16,26 @@ obj-m :=
obj-n :=
obj- :=
-obj-$(CONFIG_BLK_DEV_MD) += md.o
+# Note: link order is important. All raid personalities
+# and xor.o must come before md.o, as they each initialise
+# themselves, and md.o may use the personalities when it
+# auto-initialised.
+# The use of MIX_OBJS allows link order to be maintained even
+# though some are export-objs and some aren't.
+
obj-$(CONFIG_MD_LINEAR) += linear.o
obj-$(CONFIG_MD_RAID0) += raid0.o
obj-$(CONFIG_MD_RAID1) += raid1.o
obj-$(CONFIG_MD_RAID5) += raid5.o xor.o
+obj-$(CONFIG_BLK_DEV_MD) += md.o
obj-$(CONFIG_BLK_DEV_LVM) += lvm-mod.o
# Translate to Rules.make lists.
-O_OBJS := $(filter-out $(export-objs), $(obj-y))
-OX_OBJS := $(filter $(export-objs), $(obj-y))
-M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
+active-objs := $(sort $(obj-y) $(obj-m))
+
+O_OBJS := $(obj-y)
+M_OBJS := $(obj-m)
+MIX_OBJS := $(filter $(export-objs), $(active-objs))
include $(TOPDIR)/Rules.make
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 855bc44dd..e6b50b84d 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -84,21 +84,19 @@ static int linear_run (mddev_t *mddev)
dev_info_t *disk = conf->disks + j;
if (size < 0) {
- table->dev1 = disk;
- table++;
+ table[-1].dev1 = disk;
}
size += disk->size;
- while (size) {
+ while (size>0) {
table->dev0 = disk;
- size -= conf->smallest->size;
- if (size < 0)
- break;
table->dev1 = NULL;
+ size -= conf->smallest->size;
table++;
}
}
- table->dev1 = NULL;
+ if (table-conf->hash_table != nb_zone)
+ BUG();
return 0;
@@ -136,7 +134,8 @@ static int linear_make_request (mddev_t *mddev,
if (!hash->dev1) {
printk ("linear_make_request : hash->dev1==NULL for block %ld\n",
block);
- return -1;
+ buffer_IO_error(bh);
+ return 0;
}
tmp_dev = hash->dev1;
} else
@@ -145,7 +144,8 @@ static int linear_make_request (mddev_t *mddev,
if (block >= (tmp_dev->size + tmp_dev->offset)
|| block < tmp_dev->offset) {
printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
- return -1;
+ buffer_IO_error(bh);
+ return 0;
}
bh->b_rdev = tmp_dev->dev;
bh->b_rsector = bh->b_rsector - (tmp_dev->offset << 1);
@@ -190,24 +190,16 @@ static mdk_personality_t linear_personality=
status: linear_status,
};
-#ifndef MODULE
-
-void md__init linear_init (void)
+static int md__init linear_init (void)
{
- register_md_personality (LINEAR, &linear_personality);
+ return register_md_personality (LINEAR, &linear_personality);
}
-#else
-
-int init_module (void)
-{
- return (register_md_personality (LINEAR, &linear_personality));
-}
-
-void cleanup_module (void)
+static void linear_exit (void)
{
unregister_md_personality (LINEAR);
}
-#endif
+module_init(linear_init);
+module_exit(linear_exit);
diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c
index 5aa88df9e..f9433232e 100644
--- a/drivers/md/lvm.c
+++ b/drivers/md/lvm.c
@@ -123,6 +123,7 @@
* - avoided inline strings functions lvm_strlen etc.
* 14/02/2000 - support for 2.3.43
* - integrated Andrea Arcangeli's snapshot code
+ * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown
*
*/
@@ -1488,8 +1489,10 @@ static void lvm_dummy_device_request(request_queue_t * t)
*/
static int lvm_make_request_fn(request_queue_t *q, int rw, struct buffer_head *bh)
{
- lvm_map(bh, rw);
- return 1;
+ if (lvm_map(bh, rw)<0)
+ return 0; /* failure, buffer_IO_error has been called, don't recurse */
+ else
+ return 1; /* all ok, mapping done, call lower level driver */
}
/*
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 091551597..8542bc2b0 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -179,7 +179,7 @@ static int md_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
return mddev->pers->make_request(mddev, rw, bh);
else {
buffer_IO_error(bh);
- return -1;
+ return 0;
}
}
@@ -203,6 +203,7 @@ static mddev_t * alloc_mddev (kdev_t dev)
init_MUTEX(&mddev->resync_sem);
MD_INIT_LIST_HEAD(&mddev->disks);
MD_INIT_LIST_HEAD(&mddev->all_mddevs);
+ atomic_set(&mddev->active, 0);
/*
* The 'base' mddev is the one with data NULL.
@@ -656,32 +657,25 @@ static void unbind_rdev_from_array (mdk_rdev_t * rdev)
static int lock_rdev (mdk_rdev_t *rdev)
{
int err = 0;
+ struct block_device *bdev;
- /*
- * First insert a dummy inode.
- */
- if (rdev->inode)
- MD_BUG();
- rdev->inode = get_empty_inode();
- if (!rdev->inode)
+ bdev = bdget(rdev->dev);
+ if (bdev == NULL)
return -ENOMEM;
- /*
- * we dont care about any other fields
- */
- rdev->inode->i_dev = rdev->inode->i_rdev = rdev->dev;
- insert_inode_hash(rdev->inode);
-
- memset(&rdev->filp, 0, sizeof(rdev->filp));
- rdev->filp.f_mode = 3; /* read write */
+ err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE);
+ if (!err) {
+ rdev->bdev = bdev;
+ }
return err;
}
static void unlock_rdev (mdk_rdev_t *rdev)
{
- if (!rdev->inode)
+ if (!rdev->bdev)
MD_BUG();
- iput(rdev->inode);
- rdev->inode = NULL;
+ blkdev_put(rdev->bdev, BDEV_FILE);
+ bdput(rdev->bdev);
+ rdev->bdev = NULL;
}
static void export_rdev (mdk_rdev_t * rdev)
@@ -1149,7 +1143,7 @@ static int md_import_device (kdev_t newdev, int on_disk)
abort_free:
if (rdev->sb) {
- if (rdev->inode)
+ if (rdev->bdev)
unlock_rdev(rdev);
free_disk_sb(rdev);
}
@@ -1718,12 +1712,20 @@ out:
#define STILL_MOUNTED KERN_WARNING \
"md: md%d still mounted.\n"
+#define STILL_IN_USE \
+"md: md%d still in use.\n"
static int do_md_stop (mddev_t * mddev, int ro)
{
int err = 0, resync_interrupted = 0;
kdev_t dev = mddev_to_kdev(mddev);
+ if (atomic_read(&mddev->active)>1) {
+ printk(STILL_IN_USE, mdidx(mddev));
+ OUT(-EBUSY);
+ }
+
+ /* this shouldn't be needed as above would have fired */
if (!ro && get_super(dev)) {
printk (STILL_MOUNTED, mdidx(mddev));
OUT(-EBUSY);
@@ -1859,8 +1861,10 @@ static void autorun_array (mddev_t *mddev)
* the 'same_array' list. Then order this list based on superblock
* update time (freshest comes first), kick out 'old' disks and
* compare superblocks. If everything's fine then run it.
+ *
+ * If "unit" is allocated, then bump its reference count
*/
-static void autorun_devices (void)
+static void autorun_devices (kdev_t countdev)
{
struct md_list_head candidates;
struct md_list_head *tmp;
@@ -1902,6 +1906,12 @@ static void autorun_devices (void)
continue;
}
mddev = alloc_mddev(md_kdev);
+ if (mddev == NULL) {
+ printk("md: cannot allocate memory for md drive.\n");
+ break;
+ }
+ if (md_kdev == countdev)
+ atomic_inc(&mddev->active);
printk("created md%d\n", mdidx(mddev));
ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {
bind_rdev_to_array(rdev, mddev);
@@ -1945,7 +1955,7 @@ static void autorun_devices (void)
#define AUTORUNNING KERN_INFO \
"md: auto-running md%d.\n"
-static int autostart_array (kdev_t startdev)
+static int autostart_array (kdev_t startdev, kdev_t countdev)
{
int err = -EINVAL, i;
mdp_super_t *sb = NULL;
@@ -2002,7 +2012,7 @@ static int autostart_array (kdev_t startdev)
/*
* possibly return codes
*/
- autorun_devices();
+ autorun_devices(countdev);
return 0;
abort:
@@ -2077,7 +2087,7 @@ int md__init md_run_setup(void)
md_list_add(&rdev->pending, &pending_raid_disks);
}
- autorun_devices();
+ autorun_devices(-1);
}
dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */
@@ -2607,6 +2617,8 @@ static int md_ioctl (struct inode *inode, struct file *file,
err = -ENOMEM;
goto abort;
}
+ atomic_inc(&mddev->active);
+
/*
* alloc_mddev() should possibly self-lock.
*/
@@ -2640,7 +2652,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
/*
* possibly make it lock the array ...
*/
- err = autostart_array((kdev_t)arg);
+ err = autostart_array((kdev_t)arg, dev);
if (err) {
printk("autostart %s failed!\n",
partition_name((kdev_t)arg));
@@ -2820,14 +2832,26 @@ abort:
static int md_open (struct inode *inode, struct file *file)
{
/*
- * Always succeed
+ * Always succeed, but increment the usage count
*/
+ mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
+ if (mddev)
+ atomic_inc(&mddev->active);
return (0);
}
+static int md_release (struct inode *inode, struct file * file)
+{
+ mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
+ if (mddev)
+ atomic_dec(&mddev->active);
+ return 0;
+}
+
static struct block_device_operations md_fops=
{
open: md_open,
+ release: md_release,
ioctl: md_ioctl,
};
@@ -3279,7 +3303,7 @@ recheck:
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) {
- printk(KERN_INFO "md: serializing resync, md%d has overlapping physical units with md%d!\n", mdidx(mddev), mdidx(mddev2));
+ printk(KERN_INFO "md: serializing resync, md%d shares one or more physical units with md%d!\n", mdidx(mddev), mdidx(mddev2));
serialize = 1;
break;
}
@@ -3576,20 +3600,14 @@ static void md_geninit (void)
create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
#endif
}
-void hsm_init (void);
-void translucent_init (void);
-void linear_init (void);
-void raid0_init (void);
-void raid1_init (void);
-void raid5_init (void);
int md__init md_init (void)
{
static char * name = "mdrecoveryd";
- printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n",
+ printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
MD_MAJOR_VERSION, MD_MINOR_VERSION,
- MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL);
+ MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops))
{
@@ -3617,18 +3635,6 @@ int md__init md_init (void)
md_register_reboot_notifier(&md_notifier);
raid_table_header = register_sysctl_table(raid_root_table, 1);
-#ifdef CONFIG_MD_LINEAR
- linear_init ();
-#endif
-#ifdef CONFIG_MD_RAID0
- raid0_init ();
-#endif
-#ifdef CONFIG_MD_RAID1
- raid1_init ();
-#endif
-#ifdef CONFIG_MD_RAID5
- raid5_init ();
-#endif
md_geninit();
return (0);
}
@@ -3639,7 +3645,7 @@ struct {
unsigned long set;
int pers[MAX_MD_BOOT_DEVS];
int chunk[MAX_MD_BOOT_DEVS];
- kdev_t devices[MAX_MD_BOOT_DEVS][MAX_REAL];
+ kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS];
} md_setup_args md__initdata = { 0, };
/*
@@ -3713,7 +3719,7 @@ static int md__init md_setup(char *str)
pername="super-block";
}
devnames = str;
- for (; i<MAX_REAL && str; i++) {
+ for (; i<MD_SB_DISKS && str; i++) {
if ((device = name_to_kdev_t(str))) {
md_setup_args.devices[minor][i] = device;
} else {
@@ -3853,7 +3859,7 @@ void cleanup_module (void)
#endif
__initcall(md_init);
-#ifdef CONFIG_AUTODETECT_RAID
+#if defined(CONFIG_AUTODETECT_RAID) || defined(CONFIG_MD_BOOT)
__initcall(md_run_setup);
#endif
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 09f3f8547..576dd3b43 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -275,16 +275,18 @@ static int raid0_make_request (mddev_t *mddev,
bad_map:
printk ("raid0_make_request bug: can't convert block across chunks or bigger than %dk %ld %d\n", chunk_size, bh->b_rsector, bh->b_size >> 10);
- return -1;
+ goto outerr;
bad_hash:
printk("raid0_make_request bug: hash==NULL for block %ld\n", block);
- return -1;
+ goto outerr;
bad_zone0:
printk ("raid0_make_request bug: hash->zone0==NULL for block %ld\n", block);
- return -1;
+ goto outerr;
bad_zone1:
printk ("raid0_make_request bug: hash->zone1==NULL for block %ld\n", block);
- return -1;
+ outerr:
+ buffer_IO_error(bh);
+ return 0;
}
static int raid0_status (char *page, mddev_t *mddev)
@@ -333,24 +335,17 @@ static mdk_personality_t raid0_personality=
status: raid0_status,
};
-#ifndef MODULE
-
-void raid0_init (void)
-{
- register_md_personality (RAID0, &raid0_personality);
-}
-
-#else
-
-int init_module (void)
+static int md__init raid0_init (void)
{
- return (register_md_personality (RAID0, &raid0_personality));
+ return register_md_personality (RAID0, &raid0_personality);
}
-void cleanup_module (void)
+static void raid0_exit (void)
{
unregister_md_personality (RAID0);
}
-#endif
+module_init(raid0_init);
+module_exit(raid0_exit);
+
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 85073b564..3a381b6a2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -463,16 +463,12 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
if (conf->resync_mirrors)
goto rb_out;
- if (conf->working_disks < 2) {
- int i = 0;
-
- while( !conf->mirrors[new_disk].operational &&
- (i < MD_SB_DISKS) ) {
- new_disk = conf->mirrors[new_disk].next;
- i++;
- }
-
- if (i >= MD_SB_DISKS) {
+
+ /* make sure that disk is operational */
+ while( !conf->mirrors[new_disk].operational) {
+ if (new_disk <= 0) new_disk = conf->raid_disks;
+ new_disk--;
+ if (new_disk == disk) {
/*
* This means no working disk was found
* Nothing much to do, lets not change anything
@@ -480,11 +476,13 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
*/
new_disk = conf->last_used;
+
+ goto rb_out;
}
-
- goto rb_out;
}
-
+ disk = new_disk;
+ /* now disk == new_disk == starting point for search */
+
/*
* Don't touch anything for sequential reads.
*/
@@ -501,16 +499,16 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
if (conf->sect_count >= conf->mirrors[new_disk].sect_limit) {
conf->sect_count = 0;
-
- while( new_disk != conf->mirrors[new_disk].next ) {
- if ((conf->mirrors[new_disk].write_only) ||
- (!conf->mirrors[new_disk].operational) )
- continue;
-
- new_disk = conf->mirrors[new_disk].next;
- break;
- }
-
+
+ do {
+ if (new_disk<=0)
+ new_disk = conf->raid_disks;
+ new_disk--;
+ if (new_disk == disk)
+ break;
+ } while ((conf->mirrors[new_disk].write_only) ||
+ (!conf->mirrors[new_disk].operational));
+
goto rb_out;
}
@@ -519,8 +517,10 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
/* Find the disk which is closest */
- while( conf->mirrors[disk].next != conf->last_used ) {
- disk = conf->mirrors[disk].next;
+ do {
+ if (disk <= 0)
+ disk = conf->raid_disks;
+ disk--;
if ((conf->mirrors[disk].write_only) ||
(!conf->mirrors[disk].operational))
@@ -534,7 +534,7 @@ static int raid1_read_balance (raid1_conf_t *conf, struct buffer_head *bh)
current_distance = new_distance;
new_disk = disk;
}
- }
+ } while (disk != conf->last_used);
rb_out:
conf->mirrors[new_disk].head_position = this_sector + sectors;
@@ -702,16 +702,6 @@ static int raid1_status (char *page, mddev_t *mddev)
return sz;
}
-static void unlink_disk (raid1_conf_t *conf, int target)
-{
- int disks = MD_SB_DISKS;
- int i;
-
- for (i = 0; i < disks; i++)
- if (conf->mirrors[i].next == target)
- conf->mirrors[i].next = conf->mirrors[target].next;
-}
-
#define LAST_DISK KERN_ALERT \
"raid1: only one disk left and IO error.\n"
@@ -735,7 +725,6 @@ static void mark_disk_bad (mddev_t *mddev, int failed)
mdp_super_t *sb = mddev->sb;
mirror->operational = 0;
- unlink_disk(conf, failed);
mark_disk_faulty(sb->disks+mirror->number);
mark_disk_nonsync(sb->disks+mirror->number);
mark_disk_inactive(sb->disks+mirror->number);
@@ -786,25 +775,6 @@ static int raid1_error (mddev_t *mddev, kdev_t dev)
#undef DISK_FAILED
#undef START_SYNCING
-/*
- * Insert the spare disk into the drive-ring
- */
-static void link_disk(raid1_conf_t *conf, struct mirror_info *mirror)
-{
- int j, next;
- int disks = MD_SB_DISKS;
- struct mirror_info *p = conf->mirrors;
-
- for (j = 0; j < disks; j++, p++)
- if (p->operational && !p->write_only) {
- next = p->next;
- p->next = mirror->raid_disk;
- mirror->next = next;
- return;
- }
-
- printk("raid1: bug: no read-operational devices\n");
-}
static void print_raid1_conf (raid1_conf_t *conf)
{
@@ -828,6 +798,32 @@ static void print_raid1_conf (raid1_conf_t *conf)
}
}
+static void close_sync(raid1_conf_t *conf)
+{
+ mddev_t *mddev = conf->mddev;
+ /* If reconstruction was interrupted, we need to close the "active" and "pending"
+ * holes.
+ * we know that there are no active rebuild requests, os cnt_active == cnt_ready ==0
+ */
+ /* this is really needed when recovery stops too... */
+ spin_lock_irq(&conf->segment_lock);
+ conf->start_active = conf->start_pending;
+ conf->start_ready = conf->start_pending;
+ wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
+ conf->start_active =conf->start_ready = conf->start_pending = conf->start_future;
+ conf->start_future = mddev->sb->size+1;
+ conf->cnt_pending = conf->cnt_future;
+ conf->cnt_future = 0;
+ conf->phase = conf->phase ^1;
+ wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
+ conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0;
+ conf->phase = 0;
+ conf->cnt_future = conf->cnt_done;;
+ conf->cnt_done = 0;
+ spin_unlock_irq(&conf->segment_lock);
+ wake_up(&conf->wait_done);
+}
+
static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
{
int err = 0;
@@ -940,6 +936,7 @@ static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
* Deactivate a spare disk:
*/
case DISKOP_SPARE_INACTIVE:
+ close_sync(conf);
sdisk = conf->mirrors + spare_disk;
sdisk->operational = 0;
sdisk->write_only = 0;
@@ -952,7 +949,7 @@ static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
* property)
*/
case DISKOP_SPARE_ACTIVE:
-
+ close_sync(conf);
sdisk = conf->mirrors + spare_disk;
fdisk = conf->mirrors + failed_disk;
@@ -1017,7 +1014,6 @@ static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
*/
fdisk->spare = 0;
fdisk->write_only = 0;
- link_disk(conf, fdisk);
/*
* if we activate a spare, we definitely replace a
@@ -1244,27 +1240,7 @@ static void raid1syncd (void *data)
conf->resync_mirrors = 0;
}
- /* If reconstruction was interrupted, we need to close the "active" and "pending"
- * holes.
- * we know that there are no active rebuild requests, os cnt_active == cnt_ready ==0
- */
- /* this is really needed when recovery stops too... */
- spin_lock_irq(&conf->segment_lock);
- conf->start_active = conf->start_pending;
- conf->start_ready = conf->start_pending;
- wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
- conf->start_active =conf->start_ready = conf->start_pending = conf->start_future;
- conf->start_future = mddev->sb->size+1;
- conf->cnt_pending = conf->cnt_future;
- conf->cnt_future = 0;
- conf->phase = conf->phase ^1;
- wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
- conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0;
- conf->phase = 0;
- conf->cnt_future = conf->cnt_done;;
- conf->cnt_done = 0;
- spin_unlock_irq(&conf->segment_lock);
- wake_up(&conf->wait_done);
+ close_sync(conf);
up(&mddev->recovery_sem);
raid1_shrink_buffers(conf);
@@ -1325,6 +1301,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
struct raid1_bh *r1_bh;
struct buffer_head *bh;
int bsize;
+ int disk;
spin_lock_irq(&conf->segment_lock);
if (!block_nr) {
@@ -1377,6 +1354,16 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
* could dedicate one to rebuild and others to
* service read requests ..
*/
+ disk = conf->last_used;
+ /* make sure disk is operational */
+ while (!conf->mirrors[disk].operational) {
+ if (disk <= 0) disk = conf->raid_disks;
+ disk--;
+ if (disk == conf->last_used)
+ break;
+ }
+ conf->last_used = disk;
+
mirror = conf->mirrors+conf->last_used;
r1_bh = raid1_alloc_buf (conf);
@@ -1396,7 +1383,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
bh->b_list = BUF_LOCKED;
bh->b_dev = mirror->dev;
bh->b_rdev = mirror->dev;
- bh->b_state = (1<<BH_Req) | (1<<BH_Mapped);
+ bh->b_state = (1<<BH_Req) | (1<<BH_Mapped) | (1<<BH_Lock);
if (!bh->b_page)
BUG();
if (!bh->b_data)
@@ -1717,19 +1704,10 @@ static int raid1_run (mddev_t *mddev)
* find the first working one and use it as a starting point
* to read balancing.
*/
- for (j = 0; !conf->mirrors[j].operational; j++)
+ for (j = 0; !conf->mirrors[j].operational && j < MD_SB_DISKS; j++)
/* nothing */;
conf->last_used = j;
- /*
- * initialize the 'working disks' list.
- */
- for (i = conf->raid_disks - 1; i >= 0; i--) {
- if (conf->mirrors[i].operational) {
- conf->mirrors[i].next = j;
- j = i;
- }
- }
if (conf->working_disks != sb->raid_disks) {
printk(KERN_ALERT "raid1: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev));
@@ -1882,19 +1860,16 @@ static mdk_personality_t raid1_personality=
sync_request: raid1_sync_request
};
-int raid1_init (void)
+static int md__init raid1_init (void)
{
return register_md_personality (RAID1, &raid1_personality);
}
-#ifdef MODULE
-int init_module (void)
-{
- return raid1_init();
-}
-
-void cleanup_module (void)
+static void raid1_exit (void)
{
unregister_md_personality (RAID1);
}
-#endif
+
+module_init(raid1_init);
+module_exit(raid1_exit);
+
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 4103b0ea5..55c50c5e7 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1516,8 +1516,8 @@ static int raid5_sync_request (mddev_t *mddev, unsigned long block_nr)
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
struct stripe_head *sh;
int sectors_per_chunk = conf->chunk_size >> 9;
- unsigned long stripe = (block_nr<<2)/sectors_per_chunk;
- int chunk_offset = (block_nr<<2) % sectors_per_chunk;
+ unsigned long stripe = (block_nr<<1)/sectors_per_chunk;
+ int chunk_offset = (block_nr<<1) % sectors_per_chunk;
int dd_idx, pd_idx;
unsigned long first_sector;
int raid_disks = conf->raid_disks;
@@ -2352,19 +2352,16 @@ static mdk_personality_t raid5_personality=
sync_request: raid5_sync_request
};
-int raid5_init (void)
+static int md__init raid5_init (void)
{
return register_md_personality (RAID5, &raid5_personality);
}
-#ifdef MODULE
-int init_module (void)
-{
- return raid5_init();
-}
-
-void cleanup_module (void)
+static void raid5_exit (void)
{
unregister_md_personality (RAID5);
}
-#endif
+
+module_init(raid5_init);
+module_exit(raid5_exit);
+
diff --git a/drivers/md/xor.c b/drivers/md/xor.c
index f58463ebc..b9b1cefe9 100644
--- a/drivers/md/xor.c
+++ b/drivers/md/xor.c
@@ -16,7 +16,6 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#define BH_TRACE 0
#include <linux/module.h>
#include <linux/raid/md.h>