]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/md/md.c
md: Make calc_dev_sboffset() return a sector count.
[mv-sheeva.git] / drivers / md / md.c
index a849e06f861cd20a6b6c2573536a54691f6cf11a..3276edde757644244248af7e6e2435c8cfd7e5db 100644 (file)
@@ -347,21 +347,20 @@ static struct mdk_personality *find_pers(int level, char *clevel)
        return NULL;
 }
 
+/* return the offset of the super block in 512byte sectors */
 static inline sector_t calc_dev_sboffset(struct block_device *bdev)
 {
-       sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
-       return MD_NEW_SIZE_BLOCKS(size);
+       sector_t num_sectors = bdev->bd_inode->i_size / 512;
+       return MD_NEW_SIZE_SECTORS(num_sectors);
 }
 
-static sector_t calc_dev_size(mdk_rdev_t *rdev, unsigned chunk_size)
+static sector_t calc_num_sectors(mdk_rdev_t *rdev, unsigned chunk_size)
 {
-       sector_t size;
-
-       size = rdev->sb_offset;
+       sector_t num_sectors = rdev->sb_offset * 2;
 
        if (chunk_size)
-               size &= ~((sector_t)chunk_size/1024 - 1);
-       return size;
+               num_sectors &= ~((sector_t)chunk_size/512 - 1);
+       return num_sectors;
 }
 
 static int alloc_disk_sb(mdk_rdev_t * rdev)
@@ -372,7 +371,7 @@ static int alloc_disk_sb(mdk_rdev_t * rdev)
        rdev->sb_page = alloc_page(GFP_KERNEL);
        if (!rdev->sb_page) {
                printk(KERN_ALERT "md: out of memory.\n");
-               return -EINVAL;
+               return -ENOMEM;
        }
 
        return 0;
@@ -543,17 +542,12 @@ fail:
 
 static int uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2)
 {
-       if (    (sb1->set_uuid0 == sb2->set_uuid0) &&
-               (sb1->set_uuid1 == sb2->set_uuid1) &&
-               (sb1->set_uuid2 == sb2->set_uuid2) &&
-               (sb1->set_uuid3 == sb2->set_uuid3))
-
-               return 1;
-
-       return 0;
+       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;
 }
 
-
 static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
 {
        int ret;
@@ -564,7 +558,7 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
 
        if (!tmp1 || !tmp2) {
                ret = 0;
-               printk(KERN_INFO "md.c: sb1 is not equal to sb2!\n");
+               printk(KERN_INFO "md.c sb_equal(): failed to allocate memory!\n");
                goto abort;
        }
 
@@ -577,11 +571,7 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
        tmp1->nr_disks = 0;
        tmp2->nr_disks = 0;
 
-       if (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4))
-               ret = 0;
-       else
-               ret = 1;
-
+       ret = (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4) == 0);
 abort:
        kfree(tmp1);
        kfree(tmp2);
@@ -684,7 +674,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
         *
         * It also happens to be a multiple of 4Kb.
         */
-       sb_offset = calc_dev_sboffset(rdev->bdev);
+       sb_offset = calc_dev_sboffset(rdev->bdev) / 2;
        rdev->sb_offset = sb_offset;
 
        ret = read_disk_sb(rdev, MD_SB_BYTES);
@@ -762,7 +752,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
                else 
                        ret = 0;
        }
-       rdev->size = calc_dev_size(rdev, sb->chunk_size);
+       rdev->size = calc_num_sectors(rdev, sb->chunk_size) / 2;
 
        if (rdev->size < sb->size && sb->level > 1)
                /* "this cannot possibly happen" ... */
@@ -1017,7 +1007,7 @@ super_90_rdev_size_change(mdk_rdev_t *rdev, unsigned long long size)
        size *= 2; /* convert to sectors */
        if (rdev->mddev->bitmap_offset)
                return 0; /* can't move bitmap */
-       rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+       rdev->sb_offset = calc_dev_sboffset(rdev->bdev) / 2;
        if (!size || size > rdev->sb_offset*2)
                size = rdev->sb_offset*2;
        md_super_write(rdev->mddev, rdev, rdev->sb_offset << 1, rdev->sb_size,
@@ -2697,7 +2687,7 @@ array_state_show(mddev_t *mddev, char *page)
        return sprintf(page, "%s\n", array_states[st]);
 }
 
-static int do_md_stop(mddev_t * mddev, int ro);
+static int do_md_stop(mddev_t * mddev, int ro, int is_open);
 static int do_md_run(mddev_t * mddev);
 static int restart_array(mddev_t *mddev);
 
@@ -2713,14 +2703,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                /* stopping an active array */
                if (atomic_read(&mddev->active) > 1)
                        return -EBUSY;
-               err = do_md_stop(mddev, 0);
+               err = do_md_stop(mddev, 0, 0);
                break;
        case inactive:
                /* stopping an active array */
                if (mddev->pers) {
                        if (atomic_read(&mddev->active) > 1)
                                return -EBUSY;
-                       err = do_md_stop(mddev, 2);
+                       err = do_md_stop(mddev, 2, 0);
                } else
                        err = 0; /* already inactive */
                break;
@@ -2728,7 +2718,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                break; /* not supported yet */
        case readonly:
                if (mddev->pers)
-                       err = do_md_stop(mddev, 1);
+                       err = do_md_stop(mddev, 1, 0);
                else {
                        mddev->ro = 1;
                        set_disk_ro(mddev->gendisk, 1);
@@ -2738,7 +2728,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
        case read_auto:
                if (mddev->pers) {
                        if (mddev->ro != 1)
-                               err = do_md_stop(mddev, 1);
+                               err = do_md_stop(mddev, 1, 0);
                        else
                                err = restart_array(mddev);
                        if (err == 0) {
@@ -2899,7 +2889,7 @@ size_show(mddev_t *mddev, char *page)
        return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
 }
 
-static int update_size(mddev_t *mddev, unsigned long size);
+static int update_size(mddev_t *mddev, sector_t num_sectors);
 
 static ssize_t
 size_store(mddev_t *mddev, const char *buf, size_t len)
@@ -2916,7 +2906,7 @@ size_store(mddev_t *mddev, const char *buf, size_t len)
                return -EINVAL;
 
        if (mddev->pers) {
-               err = update_size(mddev, size);
+               err = update_size(mddev, size * 2);
                md_update_sb(mddev, 1);
        } else {
                if (mddev->size == 0 ||
@@ -3775,40 +3765,25 @@ static int do_md_run(mddev_t * mddev)
 static int restart_array(mddev_t *mddev)
 {
        struct gendisk *disk = mddev->gendisk;
-       int err;
 
-       /*
-        * Complain if it has no devices
-        */
-       err = -ENXIO;
+       /* Complain if it has no devices */
        if (list_empty(&mddev->disks))
-               goto out;
-
-       if (mddev->pers) {
-               err = -EBUSY;
-               if (!mddev->ro)
-                       goto out;
-
-               mddev->safemode = 0;
-               mddev->ro = 0;
-               set_disk_ro(disk, 0);
-
-               printk(KERN_INFO "md: %s switched to read-write mode.\n",
-                       mdname(mddev));
-               /*
-                * Kick recovery or resync if necessary
-                */
-               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-               md_wakeup_thread(mddev->thread);
-               md_wakeup_thread(mddev->sync_thread);
-               err = 0;
-               sysfs_notify(&mddev->kobj, NULL, "array_state");
-
-       } else
-               err = -EINVAL;
-
-out:
-       return err;
+               return -ENXIO;
+       if (!mddev->pers)
+               return -EINVAL;
+       if (!mddev->ro)
+               return -EBUSY;
+       mddev->safemode = 0;
+       mddev->ro = 0;
+       set_disk_ro(disk, 0);
+       printk(KERN_INFO "md: %s switched to read-write mode.\n",
+               mdname(mddev));
+       /* Kick recovery or resync if necessary */
+       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+       md_wakeup_thread(mddev->thread);
+       md_wakeup_thread(mddev->sync_thread);
+       sysfs_notify(&mddev->kobj, NULL, "array_state");
+       return 0;
 }
 
 /* similar to deny_write_access, but accounts for our holding a reference
@@ -3842,16 +3817,17 @@ static void restore_bitmap_write_access(struct file *file)
  *   1 - switch to readonly
  *   2 - stop but do not disassemble array
  */
-static int do_md_stop(mddev_t * mddev, int mode)
+static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 {
        int err = 0;
        struct gendisk *disk = mddev->gendisk;
 
+       if (atomic_read(&mddev->active) > 1 + is_open) {
+               printk("md: %s still in use.\n",mdname(mddev));
+               return -EBUSY;
+       }
+
        if (mddev->pers) {
-               if (atomic_read(&mddev->active)>2) {
-                       printk("md: %s still in use.\n",mdname(mddev));
-                       return -EBUSY;
-               }
 
                if (mddev->sync_thread) {
                        set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -4000,7 +3976,7 @@ static void autorun_array(mddev_t *mddev)
        err = do_md_run (mddev);
        if (err) {
                printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
-               do_md_stop (mddev, 0);
+               do_md_stop (mddev, 0, 0);
        }
 }
 
@@ -4210,15 +4186,12 @@ out:
 static int get_disk_info(mddev_t * mddev, void __user * arg)
 {
        mdu_disk_info_t info;
-       unsigned int nr;
        mdk_rdev_t *rdev;
 
        if (copy_from_user(&info, arg, sizeof(info)))
                return -EFAULT;
 
-       nr = info.number;
-
-       rdev = find_rdev_nr(mddev, nr);
+       rdev = find_rdev_nr(mddev, info.number);
        if (rdev) {
                info.major = MAJOR(rdev->bdev->bd_dev);
                info.minor = MINOR(rdev->bdev->bd_dev);
@@ -4384,8 +4357,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                        printk(KERN_INFO "md: nonpersistent superblock ...\n");
                        rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
                } else 
-                       rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
-               rdev->size = calc_dev_size(rdev, mddev->chunk_size);
+                       rdev->sb_offset = calc_dev_sboffset(rdev->bdev) / 2;
+               rdev->size = calc_num_sectors(rdev, mddev->chunk_size) / 2;
 
                err = bind_rdev_to_array(rdev, mddev);
                if (err) {
@@ -4424,7 +4397,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
 {
        char b[BDEVNAME_SIZE];
        int err;
-       unsigned int size;
        mdk_rdev_t *rdev;
 
        if (!mddev->pers)
@@ -4452,13 +4424,12 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
        }
 
        if (mddev->persistent)
-               rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+               rdev->sb_offset = calc_dev_sboffset(rdev->bdev) / 2;
        else
                rdev->sb_offset =
                        rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
 
-       size = calc_dev_size(rdev, mddev->chunk_size);
-       rdev->size = size;
+       rdev->size = calc_num_sectors(rdev, mddev->chunk_size) / 2;
 
        if (test_bit(Faulty, &rdev->flags)) {
                printk(KERN_WARNING 
@@ -4643,24 +4614,24 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
        return 0;
 }
 
-static int update_size(mddev_t *mddev, unsigned long size)
+static int update_size(mddev_t *mddev, sector_t num_sectors)
 {
        mdk_rdev_t * rdev;
        int rv;
        struct list_head *tmp;
-       int fit = (size == 0);
+       int fit = (num_sectors == 0);
 
        if (mddev->pers->resize == NULL)
                return -EINVAL;
-       /* The "size" is the amount of each device that is used.
-        * This can only make sense for arrays with redundancy.
-        * linear and raid0 always use whatever space is available
-        * We can only consider changing the size if no resync
-        * or reconstruction is happening, and if the new size
-        * is acceptable. It must fit before the sb_offset or,
-        * if that is <data_offset, it must fit before the
-        * size of each device.
-        * If size is zero, we find the largest size that fits.
+       /* The "num_sectors" is the number of sectors of each device that
+        * is used.  This can only make sense for arrays with redundancy.
+        * linear and raid0 always use whatever space is available. We can only
+        * consider changing this number if no resync or reconstruction is
+        * happening, and if the new size is acceptable. It must fit before the
+        * sb_offset or, if that is <data_offset, it must fit before the size
+        * of each device.  If num_sectors is zero, we find the largest size
+        * that fits.
+
         */
        if (mddev->sync_thread)
                return -EBUSY;
@@ -4668,12 +4639,12 @@ static int update_size(mddev_t *mddev, unsigned long size)
                sector_t avail;
                avail = rdev->size * 2;
 
-               if (fit && (size == 0 || size > avail/2))
-                       size = avail/2;
-               if (avail < ((sector_t)size << 1))
+               if (fit && (num_sectors == 0 || num_sectors > avail))
+                       num_sectors = avail;
+               if (avail < num_sectors)
                        return -ENOSPC;
        }
-       rv = mddev->pers->resize(mddev, (sector_t)size *2);
+       rv = mddev->pers->resize(mddev, num_sectors);
        if (!rv) {
                struct block_device *bdev;
 
@@ -4755,7 +4726,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
                        return mddev->pers->reconfig(mddev, info->layout, -1);
        }
        if (info->size >= 0 && mddev->size != info->size)
-               rv = update_size(mddev, info->size);
+               rv = update_size(mddev, (sector_t)info->size * 2);
 
        if (mddev->raid_disks    != info->raid_disks)
                rv = update_raid_disks(mddev, info->raid_disks);
@@ -4958,11 +4929,11 @@ static int md_ioctl(struct inode *inode, struct file *file,
                        goto done_unlock;
 
                case STOP_ARRAY:
-                       err = do_md_stop (mddev, 0);
+                       err = do_md_stop (mddev, 0, 1);
                        goto done_unlock;
 
                case STOP_ARRAY_RO:
-                       err = do_md_stop (mddev, 1);
+                       err = do_md_stop (mddev, 1, 1);
                        goto done_unlock;
 
        }
@@ -6253,7 +6224,7 @@ static int md_notify_reboot(struct notifier_block *this,
 
                for_each_mddev(mddev, tmp)
                        if (mddev_trylock(mddev)) {
-                               do_md_stop (mddev, 1);
+                               do_md_stop (mddev, 1, 0);
                                mddev_unlock(mddev);
                        }
                /*