diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 601 |
1 files changed, 195 insertions, 406 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 1294238610d..4dfa15da9cb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1,6 +1,6 @@ /* md.c : Multiple Devices driver for Linux - Copyright (C) 1998, 1999, 2000 Ingo Molnar + Copyright (C) 1998, 1999, 2000 Ingo Molnar completely rewritten, based on the MD driver code from Marc Zyngier @@ -66,8 +66,6 @@ static void autostart_arrays(int part); static LIST_HEAD(pers_list); static DEFINE_SPINLOCK(pers_lock); -static void md_print_devices(void); - static DECLARE_WAIT_QUEUE_HEAD(resync_wait); static struct workqueue_struct *md_wq; static struct workqueue_struct *md_misc_wq; @@ -75,8 +73,6 @@ static struct workqueue_struct *md_misc_wq; static int remove_and_add_spares(struct mddev *mddev, struct md_rdev *this); -#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } - /* * Default number of read corrections we'll attempt on an rdev * before ejecting it from the array. We divide the read error @@ -218,7 +214,6 @@ static void md_new_event_inintr(struct mddev *mddev) static LIST_HEAD(all_mddevs); static DEFINE_SPINLOCK(all_mddevs_lock); - /* * iterates through all used mddevs in the system. * We take care to grab the all_mddevs_lock whenever navigating @@ -228,7 +223,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); */ #define for_each_mddev(_mddev,_tmp) \ \ - for (({ spin_lock(&all_mddevs_lock); \ + for (({ spin_lock(&all_mddevs_lock); \ _tmp = all_mddevs.next; \ _mddev = NULL;}); \ ({ if (_tmp != &all_mddevs) \ @@ -241,7 +236,6 @@ static DEFINE_SPINLOCK(all_mddevs_lock); _tmp = _tmp->next;}) \ ) - /* Rather than calling directly into the personality make_request function, * IO requests come here first so that we can check if the device is * being suspended pending a reconfiguration. @@ -488,7 +482,7 @@ void mddev_init(struct mddev *mddev) } EXPORT_SYMBOL_GPL(mddev_init); -static struct mddev * mddev_find(dev_t unit) +static struct mddev *mddev_find(dev_t unit) { struct mddev *mddev, *new = NULL; @@ -530,7 +524,7 @@ static struct mddev * mddev_find(dev_t unit) kfree(new); return NULL; } - + is_free = 1; list_for_each_entry(mddev, &all_mddevs, all_mddevs) if (mddev->unit == dev) { @@ -562,7 +556,7 @@ static struct mddev * mddev_find(dev_t unit) goto retry; } -static inline int __must_check mddev_lock(struct mddev * mddev) +static inline int __must_check mddev_lock(struct mddev *mddev) { return mutex_lock_interruptible(&mddev->reconfig_mutex); } @@ -570,7 +564,7 @@ static inline int __must_check mddev_lock(struct mddev * mddev) /* Sometimes we need to take the lock in a situation where * failure due to interrupts is not acceptable. */ -static inline void mddev_lock_nointr(struct mddev * mddev) +static inline void mddev_lock_nointr(struct mddev *mddev) { mutex_lock(&mddev->reconfig_mutex); } @@ -580,14 +574,14 @@ static inline int mddev_is_locked(struct mddev *mddev) return mutex_is_locked(&mddev->reconfig_mutex); } -static inline int mddev_trylock(struct mddev * mddev) +static inline int mddev_trylock(struct mddev *mddev) { return mutex_trylock(&mddev->reconfig_mutex); } static struct attribute_group md_redundancy_group; -static void mddev_unlock(struct mddev * mddev) +static void mddev_unlock(struct mddev *mddev) { if (mddev->to_remove) { /* These cannot be removed under reconfig_mutex as @@ -630,17 +624,6 @@ static void mddev_unlock(struct mddev * mddev) spin_unlock(&pers_lock); } -static struct md_rdev * find_rdev_nr(struct mddev *mddev, int nr) -{ - struct md_rdev *rdev; - - rdev_for_each(rdev, mddev) - if (rdev->desc_nr == nr) - return rdev; - - return NULL; -} - static struct md_rdev *find_rdev_nr_rcu(struct mddev *mddev, int nr) { struct md_rdev *rdev; @@ -693,11 +676,8 @@ static inline sector_t calc_dev_sboffset(struct md_rdev *rdev) return MD_NEW_SIZE_SECTORS(num_sectors); } -static int alloc_disk_sb(struct md_rdev * rdev) +static int alloc_disk_sb(struct md_rdev *rdev) { - if (rdev->sb_page) - MD_BUG(); - rdev->sb_page = alloc_page(GFP_KERNEL); if (!rdev->sb_page) { printk(KERN_ALERT "md: out of memory.\n"); @@ -766,14 +746,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, void md_super_wait(struct mddev *mddev) { /* wait for all superblock writes that were scheduled to complete */ - DEFINE_WAIT(wq); - for(;;) { - prepare_to_wait(&mddev->sb_wait, &wq, TASK_UNINTERRUPTIBLE); - if (atomic_read(&mddev->pending_writes)==0) - break; - schedule(); - } - finish_wait(&mddev->sb_wait, &wq); + wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); } int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, @@ -801,17 +774,13 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, } EXPORT_SYMBOL_GPL(sync_page_io); -static int read_disk_sb(struct md_rdev * rdev, int size) +static int read_disk_sb(struct md_rdev *rdev, int size) { char b[BDEVNAME_SIZE]; - if (!rdev->sb_page) { - MD_BUG(); - return -EINVAL; - } + if (rdev->sb_loaded) return 0; - if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, true)) goto fail; rdev->sb_loaded = 1; @@ -825,7 +794,7 @@ fail: static int uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2) { - return sb1->set_uuid0 == sb2->set_uuid0 && + return sb1->set_uuid0 == sb2->set_uuid0 && sb1->set_uuid1 == sb2->set_uuid1 && sb1->set_uuid2 == sb2->set_uuid2 && sb1->set_uuid3 == sb2->set_uuid3; @@ -861,14 +830,13 @@ abort: return ret; } - static u32 md_csum_fold(u32 csum) { csum = (csum & 0xffff) + (csum >> 16); return (csum & 0xffff) + (csum >> 16); } -static unsigned int calc_sb_csum(mdp_super_t * sb) +static unsigned int calc_sb_csum(mdp_super_t *sb) { u64 newcsum = 0; u32 *sb32 = (u32*)sb; @@ -882,7 +850,6 @@ static unsigned int calc_sb_csum(mdp_super_t * sb) newcsum += sb32[i]; csum = (newcsum & 0xffffffff) + (newcsum>>32); - #ifdef CONFIG_ALPHA /* This used to use csum_partial, which was wrong for several * reasons including that different results are returned on @@ -899,7 +866,6 @@ static unsigned int calc_sb_csum(mdp_super_t * sb) return csum; } - /* * Handle superblock details. * We want to be able to handle multiple superblock formats @@ -965,7 +931,7 @@ int md_check_no_bitmap(struct mddev *mddev) EXPORT_SYMBOL(md_check_no_bitmap); /* - * load_super for 0.90.0 + * load_super for 0.90.0 */ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version) { @@ -1044,7 +1010,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor ev2 = md_event(refsb); if (ev1 > ev2) ret = 1; - else + else ret = 0; } rdev->sectors = rdev->sb_start; @@ -1118,7 +1084,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) if (sb->state & (1<<MD_SB_CLEAN)) mddev->recovery_cp = MaxSector; else { - if (sb->events_hi == sb->cp_events_hi && + if (sb->events_hi == sb->cp_events_hi && sb->events_lo == sb->cp_events_lo) { mddev->recovery_cp = sb->recovery_cp; } else @@ -1146,7 +1112,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) ++ev1; if (sb->disks[rdev->desc_nr].state & ( (1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE))) - if (ev1 < mddev->events) + if (ev1 < mddev->events) return -EINVAL; } else if (mddev->bitmap) { /* if adding to array with a bitmap, then we can accept an @@ -1197,7 +1163,6 @@ static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev) struct md_rdev *rdev2; int next_spare = mddev->raid_disks; - /* make rdev->sb match mddev data.. * * 1/ zero out disks @@ -1366,7 +1331,7 @@ super_90_allow_new_offset(struct md_rdev *rdev, unsigned long long new_offset) * version 1 superblock */ -static __le32 calc_sb_1_csum(struct mdp_superblock_1 * sb) +static __le32 calc_sb_1_csum(struct mdp_superblock_1 *sb) { __le32 disk_csum; u32 csum; @@ -1430,7 +1395,6 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ ret = read_disk_sb(rdev, 4096); if (ret) return ret; - sb = page_address(rdev->sb_page); if (sb->magic != cpu_to_le32(MD_SB_MAGIC) || @@ -1817,7 +1781,7 @@ retry: for (i=0; i<max_dev;i++) sb->dev_roles[i] = cpu_to_le16(0xfffe); - + rdev_for_each(rdev2, mddev) { i = rdev2->desc_nr; if (test_bit(Faulty, &rdev2->flags)) @@ -2033,18 +1997,13 @@ void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev) } EXPORT_SYMBOL(md_integrity_add_rdev); -static int bind_rdev_to_array(struct md_rdev * rdev, struct mddev * mddev) +static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) { char b[BDEVNAME_SIZE]; struct kobject *ko; char *s; int err; - if (rdev->mddev) { - MD_BUG(); - return -EINVAL; - } - /* prevent duplicates */ if (find_rdev(mddev, rdev->bdev->bd_dev)) return -EEXIST; @@ -2067,16 +2026,21 @@ static int bind_rdev_to_array(struct md_rdev * rdev, struct mddev * mddev) * If it is -1, assign a free number, else * check number is not in use */ + rcu_read_lock(); if (rdev->desc_nr < 0) { int choice = 0; - if (mddev->pers) choice = mddev->raid_disks; - while (find_rdev_nr(mddev, choice)) + if (mddev->pers) + choice = mddev->raid_disks; + while (find_rdev_nr_rcu(mddev, choice)) choice++; rdev->desc_nr = choice; } else { - if (find_rdev_nr(mddev, rdev->desc_nr)) + if (find_rdev_nr_rcu(mddev, rdev->desc_nr)) { + rcu_read_unlock(); return -EBUSY; + } } + rcu_read_unlock(); if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) { printk(KERN_WARNING "md: %s: array is limited to %d devices\n", mdname(mddev), mddev->max_disks); @@ -2118,13 +2082,10 @@ static void md_delayed_delete(struct work_struct *ws) kobject_put(&rdev->kobj); } -static void unbind_rdev_from_array(struct md_rdev * rdev) +static void unbind_rdev_from_array(struct md_rdev *rdev) { char b[BDEVNAME_SIZE]; - if (!rdev->mddev) { - MD_BUG(); - return; - } + bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk); list_del_rcu(&rdev->same_set); printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); @@ -2169,20 +2130,17 @@ static void unlock_rdev(struct md_rdev *rdev) { struct block_device *bdev = rdev->bdev; rdev->bdev = NULL; - if (!bdev) - MD_BUG(); blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); } void md_autodetect_dev(dev_t dev); -static void export_rdev(struct md_rdev * rdev) +static void export_rdev(struct md_rdev *rdev) { char b[BDEVNAME_SIZE]; + printk(KERN_INFO "md: export_rdev(%s)\n", bdevname(rdev->bdev,b)); - if (rdev->mddev) - MD_BUG(); md_rdev_clear(rdev); #ifndef MODULE if (test_bit(AutoDetected, &rdev->flags)) @@ -2192,7 +2150,7 @@ static void export_rdev(struct md_rdev * rdev) kobject_put(&rdev->kobj); } -static void kick_rdev_from_array(struct md_rdev * rdev) +static void kick_rdev_from_array(struct md_rdev *rdev) { unbind_rdev_from_array(rdev); export_rdev(rdev); @@ -2200,153 +2158,18 @@ static void kick_rdev_from_array(struct md_rdev * rdev) static void export_array(struct mddev *mddev) { - struct md_rdev *rdev, *tmp; + struct md_rdev *rdev; - rdev_for_each_safe(rdev, tmp, mddev) { - if (!rdev->mddev) { - MD_BUG(); - continue; - } + while (!list_empty(&mddev->disks)) { + rdev = list_first_entry(&mddev->disks, struct md_rdev, + same_set); kick_rdev_from_array(rdev); } - if (!list_empty(&mddev->disks)) - MD_BUG(); mddev->raid_disks = 0; mddev->major_version = 0; } -static void print_desc(mdp_disk_t *desc) -{ - printk(" DISK<N:%d,(%d,%d),R:%d,S:%d>\n", desc->number, - desc->major,desc->minor,desc->raid_disk,desc->state); -} - -static void print_sb_90(mdp_super_t *sb) -{ - int i; - - printk(KERN_INFO - "md: SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n", - sb->major_version, sb->minor_version, sb->patch_version, - sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3, - sb->ctime); - printk(KERN_INFO "md: L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", - sb->level, sb->size, sb->nr_disks, sb->raid_disks, - sb->md_minor, sb->layout, sb->chunk_size); - printk(KERN_INFO "md: UT:%08x ST:%d AD:%d WD:%d" - " FD:%d SD:%d CSUM:%08x E:%08lx\n", - sb->utime, sb->state, sb->active_disks, sb->working_disks, - sb->failed_disks, sb->spare_disks, - sb->sb_csum, (unsigned long)sb->events_lo); - - printk(KERN_INFO); - for (i = 0; i < MD_SB_DISKS; i++) { - mdp_disk_t *desc; - - desc = sb->disks + i; - if (desc->number || desc->major || desc->minor || - desc->raid_disk || (desc->state && (desc->state != 4))) { - printk(" D %2d: ", i); - print_desc(desc); - } - } - printk(KERN_INFO "md: THIS: "); - print_desc(&sb->this_disk); -} - -static void print_sb_1(struct mdp_superblock_1 *sb) -{ - __u8 *uuid; - - uuid = sb->set_uuid; - printk(KERN_INFO - "md: SB: (V:%u) (F:0x%08x) Array-ID:<%pU>\n" - "md: Name: \"%s\" CT:%llu\n", - le32_to_cpu(sb->major_version), - le32_to_cpu(sb->feature_map), - uuid, - sb->set_name, - (unsigned long long)le64_to_cpu(sb->ctime) - & MD_SUPERBLOCK_1_TIME_SEC_MASK); - - uuid = sb->device_uuid; - printk(KERN_INFO - "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" - " RO:%llu\n" - "md: Dev:%08x UUID: %pU\n" - "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" - "md: (MaxDev:%u) \n", - le32_to_cpu(sb->level), - (unsigned long long)le64_to_cpu(sb->size), - le32_to_cpu(sb->raid_disks), - le32_to_cpu(sb->layout), - le32_to_cpu(sb->chunksize), - (unsigned long long)le64_to_cpu(sb->data_offset), - (unsigned long long)le64_to_cpu(sb->data_size), - (unsigned long long)le64_to_cpu(sb->super_offset), - (unsigned long long)le64_to_cpu(sb->recovery_offset), - le32_to_cpu(sb->dev_number), - uuid, - sb->devflags, - (unsigned long long)le64_to_cpu(sb->utime) & MD_SUPERBLOCK_1_TIME_SEC_MASK, - (unsigned long long)le64_to_cpu(sb->events), - (unsigned long long)le64_to_cpu(sb->resync_offset), - le32_to_cpu(sb->sb_csum), - le32_to_cpu(sb->max_dev) - ); -} - -static void print_rdev(struct md_rdev *rdev, int major_version) -{ - char b[BDEVNAME_SIZE]; - printk(KERN_INFO "md: rdev %s, Sect:%08llu F:%d S:%d DN:%u\n", - bdevname(rdev->bdev, b), (unsigned long long)rdev->sectors, - test_bit(Faulty, &rdev->flags), test_bit(In_sync, &rdev->flags), - rdev->desc_nr); - if (rdev->sb_loaded) { - printk(KERN_INFO "md: rdev superblock (MJ:%d):\n", major_version); - switch (major_version) { - case 0: - print_sb_90(page_address(rdev->sb_page)); - break; - case 1: - print_sb_1(page_address(rdev->sb_page)); - break; - } - } else - printk(KERN_INFO "md: no rdev superblock!\n"); -} - -static void md_print_devices(void) -{ - struct list_head *tmp; - struct md_rdev *rdev; - struct mddev *mddev; - char b[BDEVNAME_SIZE]; - - printk("\n"); - printk("md: **********************************\n"); - printk("md: * <COMPLETE RAID STATE PRINTOUT> *\n"); - printk("md: **********************************\n"); - for_each_mddev(mddev, tmp) { - - if (mddev->bitmap) - bitmap_print_sb(mddev->bitmap); - else - printk("%s: ", mdname(mddev)); - rdev_for_each(rdev, mddev) - printk("<%s>", bdevname(rdev->bdev,b)); - printk("\n"); - - rdev_for_each(rdev, mddev) - print_rdev(rdev, mddev->major_version); - } - printk("md: **********************************\n"); - printk("\n"); -} - - -static void sync_sbs(struct mddev * mddev, int nospares) +static void sync_sbs(struct mddev *mddev, int nospares) { /* Update each superblock (in-memory image), but * if we are allowed to, skip spares which already @@ -2369,7 +2192,7 @@ static void sync_sbs(struct mddev * mddev, int nospares) } } -static void md_update_sb(struct mddev * mddev, int force_change) +static void md_update_sb(struct mddev *mddev, int force_change) { struct md_rdev *rdev; int sync_req; @@ -2390,7 +2213,7 @@ repeat: mddev->curr_resync_completed > rdev->recovery_offset) rdev->recovery_offset = mddev->curr_resync_completed; - } + } if (!mddev->persistent) { clear_bit(MD_CHANGE_CLEAN, &mddev->flags); clear_bit(MD_CHANGE_DEVS, &mddev->flags); @@ -2453,15 +2276,12 @@ repeat: mddev->can_decrease_events = nospares; } - if (!mddev->events) { - /* - * oops, this 64-bit counter should never wrap. - * Either we are in around ~1 trillion A.C., assuming - * 1 reboot per second, or we have a bug: - */ - MD_BUG(); - mddev->events --; - } + /* + * This 64-bit counter should never wrap. + * Either we are in around ~1 trillion A.C., assuming + * 1 reboot per second, or we have a bug... + */ + WARN_ON(mddev->events == 0); rdev_for_each(rdev, mddev) { if (rdev->badblocks.changed) @@ -2668,10 +2488,12 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) set_bit(In_sync, &rdev->flags); err = 0; } else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0) { - clear_bit(In_sync, &rdev->flags); - rdev->saved_raid_disk = rdev->raid_disk; - rdev->raid_disk = -1; - err = 0; + if (rdev->mddev->pers == NULL) { + clear_bit(In_sync, &rdev->flags); + rdev->saved_raid_disk = rdev->raid_disk; + rdev->raid_disk = -1; + err = 0; + } } else if (cmd_match(buf, "write_error")) { set_bit(WriteErrorSeen, &rdev->flags); err = 0; @@ -2829,7 +2651,6 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len) return len; } - static struct rdev_sysfs_entry rdev_slot = __ATTR(slot, S_IRUGO|S_IWUSR, slot_show, slot_store); @@ -2980,20 +2801,20 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len) rdev->sectors = sectors; if (sectors > oldsectors && my_mddev->external) { - /* need to check that all other rdevs with the same ->bdev - * do not overlap. We need to unlock the mddev to avoid - * a deadlock. We have already changed rdev->sectors, and if - * we have to change it back, we will have the lock again. + /* Need to check that all other rdevs with the same + * ->bdev do not overlap. 'rcu' is sufficient to walk + * the rdev lists safely. + * This check does not provide a hard guarantee, it + * just helps avoid dangerous mistakes. */ struct mddev *mddev; int overlap = 0; struct list_head *tmp; - mddev_unlock(my_mddev); + rcu_read_lock(); for_each_mddev(mddev, tmp) { struct md_rdev *rdev2; - mddev_lock_nointr(mddev); rdev_for_each(rdev2, mddev) if (rdev->bdev == rdev2->bdev && rdev != rdev2 && @@ -3003,13 +2824,12 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len) overlap = 1; break; } - mddev_unlock(mddev); if (overlap) { mddev_put(mddev); break; } } - mddev_lock_nointr(my_mddev); + rcu_read_unlock(); if (overlap) { /* Someone else could have slipped in a size * change here, but doing so is just silly. @@ -3027,7 +2847,6 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len) static struct rdev_sysfs_entry rdev_size = __ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store); - static ssize_t recovery_start_show(struct md_rdev *rdev, char *page) { unsigned long long recovery_start = rdev->recovery_offset; @@ -3063,7 +2882,6 @@ static ssize_t recovery_start_store(struct md_rdev *rdev, const char *buf, size_ static struct rdev_sysfs_entry rdev_recovery_start = __ATTR(recovery_start, S_IRUGO|S_IWUSR, recovery_start_show, recovery_start_store); - static ssize_t badblocks_show(struct badblocks *bb, char *page, int unack); static ssize_t @@ -3084,7 +2902,6 @@ static ssize_t bb_store(struct md_rdev *rdev, const char *page, size_t len) static struct rdev_sysfs_entry rdev_bad_blocks = __ATTR(bad_blocks, S_IRUGO|S_IWUSR, bb_show, bb_store); - static ssize_t ubb_show(struct md_rdev *rdev, char *page) { return badblocks_show(&rdev->badblocks, page, 1); @@ -3241,7 +3058,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe size = i_size_read(rdev->bdev->bd_inode) >> BLOCK_SIZE_BITS; if (!size) { - printk(KERN_WARNING + printk(KERN_WARNING "md: %s has zero or unknown size, marking faulty!\n", bdevname(rdev->bdev,b)); err = -EINVAL; @@ -3260,7 +3077,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe goto abort_free; } if (err < 0) { - printk(KERN_WARNING + printk(KERN_WARNING "md: could not read %s's sb, not importing!\n", bdevname(rdev->bdev,b)); goto abort_free; @@ -3281,8 +3098,7 @@ abort_free: * Check a full RAID array for plausibility */ - -static void analyze_sbs(struct mddev * mddev) +static void analyze_sbs(struct mddev *mddev) { int i; struct md_rdev *rdev, *freshest, *tmp; @@ -3300,12 +3116,11 @@ static void analyze_sbs(struct mddev * mddev) default: printk( KERN_ERR \ "md: fatal superblock inconsistency in %s" - " -- removing from array\n", + " -- removing from array\n", bdevname(rdev->bdev,b)); kick_rdev_from_array(rdev); } - super_types[mddev->major_version]. validate_super(mddev, freshest); @@ -3344,7 +3159,7 @@ static void analyze_sbs(struct mddev * mddev) /* Read a fixed-point number. * Numbers in sysfs attributes should be in "standard" units where * possible, so time should be in seconds. - * However we internally use a a much smaller unit such as + * However we internally use a a much smaller unit such as * milliseconds or jiffies. * This function takes a decimal number with a possible fractional * component, and produces an integer which is the result of @@ -3381,7 +3196,6 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) return 0; } - static void md_safemode_timeout(unsigned long data); static ssize_t @@ -3524,7 +3338,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) /* Looks like we have a winner */ mddev_suspend(mddev); mddev->pers->stop(mddev); - + if (mddev->pers->sync_request == NULL && pers->sync_request != NULL) { /* need to add the md_redundancy_group */ @@ -3533,7 +3347,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) "md: cannot register extra attributes for %s\n", mdname(mddev)); mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action"); - } + } if (mddev->pers->sync_request != NULL && pers->sync_request == NULL) { /* need to remove the md_redundancy_group */ @@ -3611,7 +3425,6 @@ level_store(struct mddev *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_level = __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store); - static ssize_t layout_show(struct mddev *mddev, char *page) { @@ -3654,7 +3467,6 @@ layout_store(struct mddev *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_layout = __ATTR(layout, S_IRUGO|S_IWUSR, layout_show, layout_store); - static ssize_t raid_disks_show(struct mddev *mddev, char *page) { @@ -3859,9 +3671,9 @@ array_state_show(struct mddev *mddev, char *page) return sprintf(page, "%s\n", array_states[st]); } -static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev); -static int md_set_readonly(struct mddev * mddev, struct block_device *bdev); -static int do_md_run(struct mddev * mddev); +static int do_md_stop(struct mddev *mddev, int ro, struct block_device *bdev); +static int md_set_readonly(struct mddev *mddev, struct block_device *bdev); +static int do_md_run(struct mddev *mddev); static int restart_array(struct mddev *mddev); static ssize_t @@ -4012,7 +3824,6 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len) minor != MINOR(dev)) return -EOVERFLOW; - if (mddev->persistent) { rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); @@ -4108,7 +3919,6 @@ size_store(struct mddev *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_size = __ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store); - /* Metadata version. * This is one of * 'none' for arrays with no metadata (good luck...) @@ -4490,7 +4300,7 @@ suspend_lo_store(struct mddev *mddev, const char *buf, size_t len) unsigned long long new = simple_strtoull(buf, &e, 10); unsigned long long old = mddev->suspend_lo; - if (mddev->pers == NULL || + if (mddev->pers == NULL || mddev->pers->quiesce == NULL) return -EINVAL; if (buf == e || (*e && *e != '\n')) @@ -4510,7 +4320,6 @@ suspend_lo_store(struct mddev *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_suspend_lo = __ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store); - static ssize_t suspend_hi_show(struct mddev *mddev, char *page) { @@ -4698,7 +4507,6 @@ static struct attribute_group md_redundancy_group = { .attrs = md_redundancy_attrs, }; - static ssize_t md_attr_show(struct kobject *kobj, struct attribute *attr, char *page) { @@ -5111,7 +4919,7 @@ int md_run(struct mddev *mddev) } else if (mddev->ro == 2) /* auto-readonly not meaningful */ mddev->ro = 0; - atomic_set(&mddev->writes_pending,0); + atomic_set(&mddev->writes_pending,0); atomic_set(&mddev->max_corr_read_errors, MD_DEFAULT_MAX_CORRECTED_READ_ERRORS); mddev->safemode = 0; @@ -5125,9 +4933,9 @@ int md_run(struct mddev *mddev) if (rdev->raid_disk >= 0) if (sysfs_link_rdev(mddev, rdev)) /* failure here is OK */; - + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - + if (mddev->flags & MD_UPDATE_SB_FLAGS) md_update_sb(mddev, 0); @@ -5307,7 +5115,7 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) mddev_lock_nointr(mddev); mutex_lock(&mddev->open_mutex); - if (atomic_read(&mddev->openers) > !!bdev || + if ((mddev->pers && atomic_read(&mddev->openers) > !!bdev) || mddev->sync_thread || (bdev && !test_bit(MD_STILL_CLOSED, &mddev->flags))) { printk("md: %s still in use.\n",mdname(mddev)); @@ -5339,7 +5147,7 @@ out: * 0 - completely stop and dis-assemble array * 2 - stop but do not disassemble array */ -static int do_md_stop(struct mddev * mddev, int mode, +static int do_md_stop(struct mddev *mddev, int mode, struct block_device *bdev) { struct gendisk *disk = mddev->gendisk; @@ -5362,7 +5170,7 @@ static int do_md_stop(struct mddev * mddev, int mode, mddev_lock_nointr(mddev); mutex_lock(&mddev->open_mutex); - if (atomic_read(&mddev->openers) > !!bdev || + if ((mddev->pers && atomic_read(&mddev->openers) > !!bdev) || mddev->sysfs_active || mddev->sync_thread || (bdev && !test_bit(MD_STILL_CLOSED, &mddev->flags))) { @@ -5512,12 +5320,12 @@ static void autorun_devices(int part) "md: cannot allocate memory for md drive.\n"); break; } - if (mddev_lock(mddev)) + if (mddev_lock(mddev)) printk(KERN_WARNING "md: %s locked, cannot run\n", mdname(mddev)); else if (mddev->raid_disks || mddev->major_version || !list_empty(&mddev->disks)) { - printk(KERN_WARNING + printk(KERN_WARNING "md: %s already running, cannot run %s\n", mdname(mddev), bdevname(rdev0->bdev,b)); mddev_unlock(mddev); @@ -5545,7 +5353,7 @@ static void autorun_devices(int part) } #endif /* !MODULE */ -static int get_version(void __user * arg) +static int get_version(void __user *arg) { mdu_version_t ver; @@ -5559,7 +5367,7 @@ static int get_version(void __user * arg) return 0; } -static int get_array_info(struct mddev * mddev, void __user * arg) +static int get_array_info(struct mddev *mddev, void __user *arg) { mdu_array_info_t info; int nr,working,insync,failed,spare; @@ -5574,7 +5382,7 @@ static int get_array_info(struct mddev * mddev, void __user * arg) else { working++; if (test_bit(In_sync, &rdev->flags)) - insync++; + insync++; else spare++; } @@ -5614,7 +5422,7 @@ static int get_array_info(struct mddev * mddev, void __user * arg) return 0; } -static int get_bitmap_file(struct mddev * mddev, void __user * arg) +static int get_bitmap_file(struct mddev *mddev, void __user * arg) { mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */ char *ptr, *buf = NULL; @@ -5652,7 +5460,7 @@ out: return err; } -static int get_disk_info(struct mddev * mddev, void __user * arg) +static int get_disk_info(struct mddev *mddev, void __user * arg) { mdu_disk_info_t info; struct md_rdev *rdev; @@ -5688,7 +5496,7 @@ static int get_disk_info(struct mddev * mddev, void __user * arg) return 0; } -static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) +static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info) { char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; struct md_rdev *rdev; @@ -5702,7 +5510,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) /* expecting a device which has a superblock */ rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); if (IS_ERR(rdev)) { - printk(KERN_WARNING + printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); return PTR_ERR(rdev); @@ -5714,9 +5522,9 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) err = super_types[mddev->major_version] .load_super(rdev, rdev0, mddev->minor_version); if (err < 0) { - printk(KERN_WARNING + printk(KERN_WARNING "md: %s has different UUID to %s\n", - bdevname(rdev->bdev,b), + bdevname(rdev->bdev,b), bdevname(rdev0->bdev,b2)); export_rdev(rdev); return -EINVAL; @@ -5736,7 +5544,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) if (mddev->pers) { int err; if (!mddev->pers->hot_add_disk) { - printk(KERN_WARNING + printk(KERN_WARNING "%s: personality does not support diskops!\n", mdname(mddev)); return -EINVAL; @@ -5747,7 +5555,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) else rdev = md_import_device(dev, -1, -1); if (IS_ERR(rdev)) { - printk(KERN_WARNING + printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); return PTR_ERR(rdev); @@ -5821,7 +5629,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) int err; rdev = md_import_device(dev, -1, 0); if (IS_ERR(rdev)) { - printk(KERN_WARNING + printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev)); return PTR_ERR(rdev); @@ -5856,7 +5664,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) return 0; } -static int hot_remove_disk(struct mddev * mddev, dev_t dev) +static int hot_remove_disk(struct mddev *mddev, dev_t dev) { char b[BDEVNAME_SIZE]; struct md_rdev *rdev; @@ -5882,7 +5690,7 @@ busy: return -EBUSY; } -static int hot_add_disk(struct mddev * mddev, dev_t dev) +static int hot_add_disk(struct mddev *mddev, dev_t dev) { char b[BDEVNAME_SIZE]; int err; @@ -5898,7 +5706,7 @@ static int hot_add_disk(struct mddev * mddev, dev_t dev) return -EINVAL; } if (!mddev->pers->hot_add_disk) { - printk(KERN_WARNING + printk(KERN_WARNING "%s: personality does not support diskops!\n", mdname(mddev)); return -EINVAL; @@ -5906,7 +5714,7 @@ static int hot_add_disk(struct mddev * mddev, dev_t dev) rdev = md_import_device(dev, -1, 0); if (IS_ERR(rdev)) { - printk(KERN_WARNING + printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev)); return -EINVAL; @@ -5920,7 +5728,7 @@ static int hot_add_disk(struct mddev * mddev, dev_t dev) rdev->sectors = rdev->sb_start; if (test_bit(Faulty, &rdev->flags)) { - printk(KERN_WARNING + printk(KERN_WARNING "md: can not hot-add faulty %s disk to %s!\n", bdevname(rdev->bdev,b), mdname(mddev)); err = -EINVAL; @@ -5968,7 +5776,6 @@ static int set_bitmap_file(struct mddev *mddev, int fd) /* we should be able to change the bitmap.. */ } - if (fd >= 0) { struct inode *inode; if (mddev->bitmap) @@ -6039,7 +5846,7 @@ static int set_bitmap_file(struct mddev *mddev, int fd) * The minor and patch _version numbers are also kept incase the * super_block handler wishes to interpret them. */ -static int set_array_info(struct mddev * mddev, mdu_array_info_t *info) +static int set_array_info(struct mddev *mddev, mdu_array_info_t *info) { if (info->raid_disks == 0) { @@ -6048,7 +5855,7 @@ static int set_array_info(struct mddev * mddev, mdu_array_info_t *info) info->major_version >= ARRAY_SIZE(super_types) || super_types[info->major_version].name == NULL) { /* maybe try to auto-load a module? */ - printk(KERN_INFO + printk(KERN_INFO "md: superblock version %d not known\n", info->major_version); return -EINVAL; @@ -6196,7 +6003,6 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks) return rv; } - /* * update_array_info is used to change the configuration of an * on-line array. @@ -6347,7 +6153,6 @@ static inline bool md_ioctl_valid(unsigned int cmd) case GET_DISK_INFO: case HOT_ADD_DISK: case HOT_REMOVE_DISK: - case PRINT_RAID_DEBUG: case RAID_AUTORUN: case RAID_VERSION: case RESTART_ARRAY_RW: @@ -6391,18 +6196,13 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case RAID_VERSION: err = get_version(argp); - goto done; - - case PRINT_RAID_DEBUG: - err = 0; - md_print_devices(); - goto done; + goto out; #ifndef MODULE case RAID_AUTORUN: err = 0; autostart_arrays(arg); - goto done; + goto out; #endif default:; } @@ -6415,7 +6215,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, if (!mddev) { BUG(); - goto abort; + goto out; } /* Some actions do not requires the mutex */ @@ -6425,18 +6225,18 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, err = -ENODEV; else err = get_array_info(mddev, argp); - goto abort; + goto out; case GET_DISK_INFO: if (!mddev->raid_disks && !mddev->external) err = -ENODEV; else err = get_disk_info(mddev, argp); - goto abort; + goto out; case SET_DISK_FAULTY: err = set_disk_faulty(mddev, new_decode_dev(arg)); - goto abort; + goto out; } if (cmd == ADD_NEW_DISK) @@ -6454,10 +6254,10 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, * and writes */ mutex_lock(&mddev->open_mutex); - if (atomic_read(&mddev->openers) > 1) { + if (mddev->pers && atomic_read(&mddev->openers) > 1) { mutex_unlock(&mddev->open_mutex); err = -EBUSY; - goto abort; + goto out; } set_bit(MD_STILL_CLOSED, &mddev->flags); mutex_unlock(&mddev->open_mutex); @@ -6465,10 +6265,10 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, } err = mddev_lock(mddev); if (err) { - printk(KERN_INFO + printk(KERN_INFO "md: ioctl lock interrupted, reason %d, cmd %d\n", err, cmd); - goto abort; + goto out; } if (cmd == SET_ARRAY_INFO) { @@ -6477,38 +6277,38 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, memset(&info, 0, sizeof(info)); else if (copy_from_user(&info, argp, sizeof(info))) { err = -EFAULT; - goto abort_unlock; + goto unlock; } if (mddev->pers) { err = update_array_info(mddev, &info); if (err) { printk(KERN_WARNING "md: couldn't update" " array info. %d\n", err); - goto abort_unlock; + goto unlock; } - goto done_unlock; + goto unlock; } if (!list_empty(&mddev->disks)) { printk(KERN_WARNING "md: array %s already has disks!\n", mdname(mddev)); err = -EBUSY; - goto abort_unlock; + goto unlock; } if (mddev->raid_disks) { printk(KERN_WARNING "md: array %s already initialised!\n", mdname(mddev)); err = -EBUSY; - goto abort_unlock; + goto unlock; } err = set_array_info(mddev, &info); if (err) { printk(KERN_WARNING "md: couldn't set" " array info. %d\n", err); - goto abort_unlock; + goto unlock; } - goto done_unlock; + goto unlock; } /* @@ -6521,7 +6321,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE && cmd != GET_BITMAP_FILE) { err = -ENODEV; - goto abort_unlock; + goto unlock; } /* @@ -6530,23 +6330,23 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case GET_BITMAP_FILE: err = get_bitmap_file(mddev, argp); - goto done_unlock; + goto unlock; case RESTART_ARRAY_RW: err = restart_array(mddev); - goto done_unlock; + goto unlock; case STOP_ARRAY: err = do_md_stop(mddev, 0, bdev); - goto done_unlock; + goto unlock; case STOP_ARRAY_RO: err = md_set_readonly(mddev, bdev); - goto done_unlock; + goto unlock; case HOT_REMOVE_DISK: err = hot_remove_disk(mddev, new_decode_dev(arg)); - goto done_unlock; + goto unlock; case ADD_NEW_DISK: /* We can support ADD_NEW_DISK on read-only arrays @@ -6562,14 +6362,14 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, break; else err = add_new_disk(mddev, &info); - goto done_unlock; + goto unlock; } break; case BLKROSET: if (get_user(ro, (int __user *)(arg))) { err = -EFAULT; - goto done_unlock; + goto unlock; } err = -EINVAL; @@ -6577,11 +6377,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, * does not matter, no writes are coming */ if (ro) - goto done_unlock; + goto unlock; /* are we are already prepared for writes? */ if (mddev->ro != 1) - goto done_unlock; + goto unlock; /* transitioning to readauto need only happen for * arrays that call md_write_start @@ -6593,17 +6393,14 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, set_disk_ro(mddev->gendisk, 0); } } - goto done_unlock; + goto unlock; } /* * The remaining ioctls are changing the state of the * superblock, so we do not allow them on read-only arrays. - * However non-MD ioctls (e.g. get-size) will still come through - * here and hit the 'default' below, so only disallow - * 'md' ioctls, and switch to rw mode if started auto-readonly. */ - if (_IOC_TYPE(cmd) == MD_MAJOR && mddev->ro && mddev->pers) { + if (mddev->ro && mddev->pers) { if (mddev->ro == 2) { mddev->ro = 0; sysfs_notify_dirent_safe(mddev->sysfs_state); @@ -6621,7 +6418,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, } } else { err = -EROFS; - goto abort_unlock; + goto unlock; } } @@ -6633,38 +6430,32 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, err = -EFAULT; else err = add_new_disk(mddev, &info); - goto done_unlock; + goto unlock; } case HOT_ADD_DISK: err = hot_add_disk(mddev, new_decode_dev(arg)); - goto done_unlock; + goto unlock; case RUN_ARRAY: err = do_md_run(mddev); - goto done_unlock; + goto unlock; case SET_BITMAP_FILE: err = set_bitmap_file(mddev, (int)arg); - goto done_unlock; + goto unlock; default: err = -EINVAL; - goto abort_unlock; + goto unlock; } -done_unlock: -abort_unlock: +unlock: if (mddev->hold_active == UNTIL_IOCTL && err != -EINVAL) mddev->hold_active = 0; mddev_unlock(mddev); - - return err; -done: - if (err) - MD_BUG(); -abort: +out: return err; } #ifdef CONFIG_COMPAT @@ -6726,7 +6517,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) static void md_release(struct gendisk *disk, fmode_t mode) { - struct mddev *mddev = disk->private_data; + struct mddev *mddev = disk->private_data; BUG_ON(!mddev); atomic_dec(&mddev->openers); @@ -6761,7 +6552,7 @@ static const struct block_device_operations md_fops = .revalidate_disk= md_revalidate, }; -static int md_thread(void * arg) +static int md_thread(void *arg) { struct md_thread *thread = arg; @@ -6810,6 +6601,7 @@ void md_wakeup_thread(struct md_thread *thread) wake_up(&thread->wqueue); } } +EXPORT_SYMBOL(md_wakeup_thread); struct md_thread *md_register_thread(void (*run) (struct md_thread *), struct mddev *mddev, const char *name) @@ -6835,6 +6627,7 @@ struct md_thread *md_register_thread(void (*run) (struct md_thread *), } return thread; } +EXPORT_SYMBOL(md_register_thread); void md_unregister_thread(struct md_thread **threadp) { @@ -6852,14 +6645,10 @@ void md_unregister_thread(struct md_thread **threadp) kthread_stop(thread->tsk); kfree(thread); } +EXPORT_SYMBOL(md_unregister_thread); void md_error(struct mddev *mddev, struct md_rdev *rdev) { - if (!mddev) { - MD_BUG(); - return; - } - if (!rdev || test_bit(Faulty, &rdev->flags)) return; @@ -6876,6 +6665,7 @@ void md_error(struct mddev *mddev, struct md_rdev *rdev) queue_work(md_misc_wq, &mddev->event_work); md_new_event_inintr(mddev); } +EXPORT_SYMBOL(md_error); /* seq_file implementation /proc/mdstat */ @@ -6898,8 +6688,7 @@ static void status_unused(struct seq_file *seq) seq_printf(seq, "\n"); } - -static void status_resync(struct seq_file *seq, struct mddev * mddev) +static void status_resync(struct seq_file *seq, struct mddev *mddev) { sector_t max_sectors, resync, res; unsigned long dt, db; @@ -6919,13 +6708,7 @@ static void status_resync(struct seq_file *seq, struct mddev * mddev) else max_sectors = mddev->dev_sectors; - /* - * Should not happen. - */ - if (!max_sectors) { - MD_BUG(); - return; - } + WARN_ON(max_sectors == 0); /* Pick 'scale' such that (resync>>scale)*1000 will fit * in a sector_t, and (max_sectors>>scale) will fit in a * u32, as those are the requirements for sector_div. @@ -7021,7 +6804,7 @@ static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct list_head *tmp; struct mddev *next_mddev, *mddev = v; - + ++*pos; if (v == (void*)2) return NULL; @@ -7036,7 +6819,7 @@ static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos) else { next_mddev = (void*)2; *pos = 0x10000; - } + } spin_unlock(&all_mddevs_lock); if (v != (void*)1) @@ -7132,7 +6915,7 @@ static int md_seq_show(struct seq_file *seq, void *v) if (mddev->pers) { mddev->pers->status(seq, mddev); - seq_printf(seq, "\n "); + seq_printf(seq, "\n "); if (mddev->pers->sync_request) { if (mddev->curr_resync > 2) { status_resync(seq, mddev); @@ -7150,7 +6933,7 @@ static int md_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "\n"); } mddev_unlock(mddev); - + return 0; } @@ -7204,12 +6987,14 @@ static const struct file_operations md_seq_fops = { int register_md_personality(struct md_personality *p) { + printk(KERN_INFO "md: %s personality registered for level %d\n", + p->name, p->level); spin_lock(&pers_lock); list_add_tail(&p->list, &pers_list); - printk(KERN_INFO "md: %s personality registered for level %d\n", p->name, p->level); spin_unlock(&pers_lock); return 0; } +EXPORT_SYMBOL(register_md_personality); int unregister_md_personality(struct md_personality *p) { @@ -7219,10 +7004,11 @@ int unregister_md_personality(struct md_personality *p) spin_unlock(&pers_lock); return 0; } +EXPORT_SYMBOL(unregister_md_personality); static int is_mddev_idle(struct mddev *mddev, int init) { - struct md_rdev * rdev; + struct md_rdev *rdev; int idle; int curr_events; @@ -7276,7 +7062,7 @@ void md_done_sync(struct mddev *mddev, int blocks, int ok) // stop recovery, signal do_sync .... } } - +EXPORT_SYMBOL(md_done_sync); /* md_write_start(mddev, bi) * If we need to update some array metadata (e.g. 'active' flag @@ -7317,6 +7103,7 @@ void md_write_start(struct mddev *mddev, struct bio *bi) wait_event(mddev->sb_wait, !test_bit(MD_CHANGE_PENDING, &mddev->flags)); } +EXPORT_SYMBOL(md_write_start); void md_write_end(struct mddev *mddev) { @@ -7327,6 +7114,7 @@ void md_write_end(struct mddev *mddev) mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay); } } +EXPORT_SYMBOL(md_write_end); /* md_allow_write(mddev) * Calling this ensures that the array is marked 'active' so that writes @@ -7784,6 +7572,33 @@ no_add: return spares; } +static void md_start_sync(struct work_struct *ws) +{ + struct mddev *mddev = container_of(ws, struct mddev, del_work); + + mddev->sync_thread = md_register_thread(md_do_sync, + mddev, + "resync"); + if (!mddev->sync_thread) { + printk(KERN_ERR "%s: could not start resync" + " thread...\n", + mdname(mddev)); + /* leave the spares where they are, it shouldn't hurt */ + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); + clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); + if (test_and_clear_bit(MD_RECOVERY_RECOVER, + &mddev->recovery)) + if (mddev->sysfs_action) + sysfs_notify_dirent_safe(mddev->sysfs_action); + } else + md_wakeup_thread(mddev->sync_thread); + sysfs_notify_dirent_safe(mddev->sysfs_action); + md_new_event(mddev); +} + /* * This routine is regularly called by all per-raid-array threads to * deal with generic issues like resync and super-block update. @@ -7900,7 +7715,7 @@ void md_check_recovery(struct mddev *mddev) if (!test_and_clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || test_bit(MD_RECOVERY_FROZEN, &mddev->recovery)) - goto unlock; + goto not_running; /* no recovery is running. * remove any failed drives, then * add spares if possible. @@ -7912,7 +7727,7 @@ void md_check_recovery(struct mddev *mddev) if (mddev->pers->check_reshape == NULL || mddev->pers->check_reshape(mddev) != 0) /* Cannot proceed */ - goto unlock; + goto not_running; set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); } else if ((spares = remove_and_add_spares(mddev, NULL))) { @@ -7925,7 +7740,7 @@ void md_check_recovery(struct mddev *mddev) clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); } else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) /* nothing to be done ... */ - goto unlock; + goto not_running; if (mddev->pers->sync_request) { if (spares) { @@ -7935,27 +7750,11 @@ void md_check_recovery(struct mddev *mddev) */ bitmap_write_all(mddev->bitmap); } - mddev->sync_thread = md_register_thread(md_do_sync, - mddev, - "resync"); - if (!mddev->sync_thread) { - printk(KERN_ERR "%s: could not start resync" - " thread...\n", - mdname(mddev)); - /* leave the spares where they are, it shouldn't hurt */ - clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); - clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); - clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); - clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); - } else - md_wakeup_thread(mddev->sync_thread); - sysfs_notify_dirent_safe(mddev->sysfs_action); - md_new_event(mddev); + INIT_WORK(&mddev->del_work, md_start_sync); + queue_work(md_misc_wq, &mddev->del_work); + goto unlock; } - unlock: - wake_up(&mddev->sb_wait); - + not_running: if (!mddev->sync_thread) { clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); if (test_and_clear_bit(MD_RECOVERY_RECOVER, @@ -7963,9 +7762,12 @@ void md_check_recovery(struct mddev *mddev) if (mddev->sysfs_action) sysfs_notify_dirent_safe(mddev->sysfs_action); } + unlock: + wake_up(&mddev->sb_wait); mddev_unlock(mddev); } } +EXPORT_SYMBOL(md_check_recovery); void md_reap_sync_thread(struct mddev *mddev) { @@ -8008,6 +7810,7 @@ void md_reap_sync_thread(struct mddev *mddev) if (mddev->event_work.func) queue_work(md_misc_wq, &mddev->event_work); } +EXPORT_SYMBOL(md_reap_sync_thread); void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev) { @@ -8641,7 +8444,6 @@ void md_autodetect_dev(dev_t dev) } } - static void autostart_arrays(int part) { struct md_rdev *rdev; @@ -8665,10 +8467,9 @@ static void autostart_arrays(int part) if (IS_ERR(rdev)) continue; - if (test_bit(Faulty, &rdev->flags)) { - MD_BUG(); + if (test_bit(Faulty, &rdev->flags)) continue; - } + set_bit(AutoDetected, &rdev->flags); list_add(&rdev->same_set, &pending_raid_disks); i_passed++; @@ -8736,20 +8537,8 @@ static int set_ro(const char *val, struct kernel_param *kp) module_param_call(start_ro, set_ro, get_ro, NULL, S_IRUSR|S_IWUSR); module_param(start_dirty_degraded, int, S_IRUGO|S_IWUSR); - module_param_call(new_array, add_named_array, NULL, NULL, S_IWUSR); -EXPORT_SYMBOL(register_md_personality); -EXPORT_SYMBOL(unregister_md_personality); -EXPORT_SYMBOL(md_error); -EXPORT_SYMBOL(md_done_sync); -EXPORT_SYMBOL(md_write_start); -EXPORT_SYMBOL(md_write_end); -EXPORT_SYMBOL(md_register_thread); -EXPORT_SYMBOL(md_unregister_thread); -EXPORT_SYMBOL(md_wakeup_thread); -EXPORT_SYMBOL(md_check_recovery); -EXPORT_SYMBOL(md_reap_sync_thread); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MD RAID framework"); MODULE_ALIAS("md"); |