]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/md/md.c
staging: board: disable as it breaks the build
[karo-tx-linux.git] / drivers / md / md.c
index 2382cfc9bb3f55a40489a01cb1d31668ff6725bd..32fc19c540d426a95f11ace984db7195e34a870c 100644 (file)
@@ -3448,6 +3448,8 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
                mddev->level = LEVEL_NONE;
                return rv;
        }
+       if (mddev->ro)
+               return  -EROFS;
 
        /* request to change the personality.  Need to ensure:
         *  - array is not engaged in resync/recovery/reshape
@@ -3634,6 +3636,8 @@ layout_store(struct mddev *mddev, const char *buf, size_t len)
                int err;
                if (mddev->pers->check_reshape == NULL)
                        return -EBUSY;
+               if (mddev->ro)
+                       return -EROFS;
                mddev->new_layout = n;
                err = mddev->pers->check_reshape(mddev);
                if (err) {
@@ -3723,6 +3727,8 @@ chunk_size_store(struct mddev *mddev, const char *buf, size_t len)
                int err;
                if (mddev->pers->check_reshape == NULL)
                        return -EBUSY;
+               if (mddev->ro)
+                       return -EROFS;
                mddev->new_chunk_sectors = n >> 9;
                err = mddev->pers->check_reshape(mddev);
                if (err) {
@@ -5593,7 +5599,7 @@ static int get_array_info(struct mddev * mddev, void __user * arg)
        if (mddev->in_sync)
                info.state = (1<<MD_SB_CLEAN);
        if (mddev->bitmap && mddev->bitmap_info.offset)
-               info.state = (1<<MD_SB_BITMAP_PRESENT);
+               info.state |= (1<<MD_SB_BITMAP_PRESENT);
        info.active_disks  = insync;
        info.working_disks = working;
        info.failed_disks  = failed;
@@ -6135,6 +6141,8 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
         */
        if (mddev->sync_thread)
                return -EBUSY;
+       if (mddev->ro)
+               return -EROFS;
 
        rdev_for_each(rdev, mddev) {
                sector_t avail = rdev->sectors;
@@ -6157,6 +6165,8 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks)
        /* change the number of raid disks */
        if (mddev->pers->check_reshape == NULL)
                return -EINVAL;
+       if (mddev->ro)
+               return -EROFS;
        if (raid_disks <= 0 ||
            (mddev->max_disks && raid_disks >= mddev->max_disks))
                return -EINVAL;
@@ -7491,6 +7501,19 @@ void md_do_sync(struct md_thread *thread)
                            rdev->recovery_offset < j)
                                j = rdev->recovery_offset;
                rcu_read_unlock();
+
+               /* If there is a bitmap, we need to make sure all
+                * writes that started before we added a spare
+                * complete before we start doing a recovery.
+                * Otherwise the write might complete and (via
+                * bitmap_endwrite) set a bit in the bitmap after the
+                * recovery has checked that bit and skipped that
+                * region.
+                */
+               if (mddev->bitmap) {
+                       mddev->pers->quiesce(mddev, 1);
+                       mddev->pers->quiesce(mddev, 0);
+               }
        }
 
        printk(KERN_INFO "md: %s of RAID array %s\n", desc, mdname(mddev));
@@ -8333,7 +8356,7 @@ static int md_clear_badblocks(struct badblocks *bb, sector_t s, int sectors)
                        if (a < s) {
                                /* we need to split this range */
                                if (bb->count >= MD_MAX_BADBLOCKS) {
-                                       rv = 0;
+                                       rv = -ENOSPC;
                                        goto out;
                                }
                                memmove(p+lo+1, p+lo, (bb->count - lo) * 8);