]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/md.c
md: fix 'safemode' handling for external metadata.
[linux-2.6-omap-h63xx.git] / drivers / md / md.c
index 61ccbd2683fa215aeddb0363bd6ddcb621bc85ac..ff9fef389608a48622bb5f9d0923ebc6537afc98 100644 (file)
@@ -276,13 +276,15 @@ static mddev_t * mddev_find(dev_t unit)
        init_waitqueue_head(&new->sb_wait);
        new->reshape_position = MaxSector;
        new->resync_max = MaxSector;
+       new->level = LEVEL_NONE;
 
        new->queue = blk_alloc_queue(GFP_KERNEL);
        if (!new->queue) {
                kfree(new);
                return NULL;
        }
-       set_bit(QUEUE_FLAG_CLUSTER, &new->queue->queue_flags);
+       /* Can be unlocked because the queue is new: no concurrency */
+       queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, new->queue);
 
        blk_queue_make_request(new->queue, md_fail_request);
 
@@ -731,9 +733,9 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
        else
                rdev->desc_nr = sb->this_disk.number;
 
-       if (refdev == 0)
+       if (!refdev) {
                ret = 1;
-       else {
+       else {
                __u64 ev1, ev2;
                mdp_super_t *refsb = (mdp_super_t*)page_address(refdev->sb_page);
                if (!uuid_equal(refsb, sb)) {
@@ -1116,9 +1118,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
        else
                rdev->desc_nr = le32_to_cpu(sb->dev_number);
 
-       if (refdev == 0)
+       if (!refdev) {
                ret = 1;
-       else {
+       else {
                __u64 ev1, ev2;
                struct mdp_superblock_1 *refsb = 
                        (struct mdp_superblock_1*)page_address(refdev->sb_page);
@@ -1651,6 +1653,8 @@ static void md_update_sb(mddev_t * mddev, int force_change)
        int sync_req;
        int nospares = 0;
 
+       if (mddev->external)
+               return;
 repeat:
        spin_lock_irq(&mddev->write_lock);
 
@@ -2096,7 +2100,7 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
                        rv = -EBUSY;
                else
                        rv = entry->store(rdev, page, length);
-               mddev_unlock(rdev->mddev);
+               mddev_unlock(mddev);
        }
        return rv;
 }
@@ -2611,6 +2615,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                        if (atomic_read(&mddev->writes_pending) == 0) {
                                if (mddev->in_sync == 0) {
                                        mddev->in_sync = 1;
+                                       if (mddev->safemode == 1)
+                                               mddev->safemode = 0;
                                        if (mddev->persistent)
                                                set_bit(MD_CHANGE_CLEAN,
                                                        &mddev->flags);
@@ -3711,6 +3717,30 @@ static int do_md_stop(mddev_t * mddev, int mode)
                mddev->reshape_position = MaxSector;
                mddev->external = 0;
                mddev->persistent = 0;
+               mddev->level = LEVEL_NONE;
+               mddev->clevel[0] = 0;
+               mddev->flags = 0;
+               mddev->ro = 0;
+               mddev->metadata_type[0] = 0;
+               mddev->chunk_size = 0;
+               mddev->ctime = mddev->utime = 0;
+               mddev->layout = 0;
+               mddev->max_disks = 0;
+               mddev->events = 0;
+               mddev->delta_disks = 0;
+               mddev->new_level = LEVEL_NONE;
+               mddev->new_layout = 0;
+               mddev->new_chunk = 0;
+               mddev->curr_resync = 0;
+               mddev->resync_mismatches = 0;
+               mddev->suspend_lo = mddev->suspend_hi = 0;
+               mddev->sync_speed_min = mddev->sync_speed_max = 0;
+               mddev->recovery = 0;
+               mddev->in_sync = 0;
+               mddev->changed = 0;
+               mddev->degraded = 0;
+               mddev->barriers_work = 0;
+               mddev->safemode = 0;
 
        } else if (mddev->pers)
                printk(KERN_INFO "md: %s switched to read-only mode.\n",
@@ -4152,7 +4182,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
 
        return 0;
 busy:
-       printk(KERN_WARNING "md: cannot remove active disk %s from %s ... \n",
+       printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
                bdevname(rdev->bdev,b), mdname(mddev));
        return -EBUSY;
 }
@@ -5364,6 +5394,8 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
                md_wakeup_thread(mddev->sync_thread);
        }
        atomic_inc(&mddev->writes_pending);
+       if (mddev->safemode == 1)
+               mddev->safemode = 0;
        if (mddev->in_sync) {
                spin_lock_irq(&mddev->write_lock);
                if (mddev->in_sync) {
@@ -5788,7 +5820,7 @@ void md_check_recovery(mddev_t *mddev)
                return;
 
        if (signal_pending(current)) {
-               if (mddev->pers->sync_request) {
+               if (mddev->pers->sync_request && !mddev->external) {
                        printk(KERN_INFO "md: %s in immediate safe mode\n",
                               mdname(mddev));
                        mddev->safemode = 2;
@@ -5800,7 +5832,7 @@ void md_check_recovery(mddev_t *mddev)
                (mddev->flags && !mddev->external) ||
                test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
                test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
-               (mddev->safemode == 1) ||
+               (mddev->external == 0 && mddev->safemode == 1) ||
                (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
                 && !mddev->in_sync && mddev->recovery_cp == MaxSector)
                ))
@@ -5809,16 +5841,20 @@ void md_check_recovery(mddev_t *mddev)
        if (mddev_trylock(mddev)) {
                int spares = 0;
 
-               spin_lock_irq(&mddev->write_lock);
-               if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
-                   !mddev->in_sync && mddev->recovery_cp == MaxSector) {
-                       mddev->in_sync = 1;
-                       if (mddev->persistent)
-                               set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+               if (!mddev->external) {
+                       spin_lock_irq(&mddev->write_lock);
+                       if (mddev->safemode &&
+                           !atomic_read(&mddev->writes_pending) &&
+                           !mddev->in_sync &&
+                           mddev->recovery_cp == MaxSector) {
+                               mddev->in_sync = 1;
+                               if (mddev->persistent)
+                                       set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+                       }
+                       if (mddev->safemode == 1)
+                               mddev->safemode = 0;
+                       spin_unlock_irq(&mddev->write_lock);
                }
-               if (mddev->safemode == 1)
-                       mddev->safemode = 0;
-               spin_unlock_irq(&mddev->write_lock);
 
                if (mddev->flags)
                        md_update_sb(mddev, 0);
@@ -5947,13 +5983,9 @@ static struct notifier_block md_notifier = {
 
 static void md_geninit(void)
 {
-       struct proc_dir_entry *p;
-
        dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
-       p = create_proc_entry("mdstat", S_IRUGO, NULL);
-       if (p)
-               p->proc_fops = &md_seq_fops;
+       proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
 }
 
 static int __init md_init(void)