#include "md.h"
#include "bitmap.h"
-#define DEBUG 0
-#define dprintk(x...) ((void)(DEBUG && printk(x)))
-
#ifndef MODULE
static void autostart_arrays(int part);
#endif
+/* pers_list is a list of registered personalities protected
+ * by pers_lock.
+ * pers_lock does extra service to protect accesses to
+ * mddev->thread when the mutex cannot be held.
+ */
static LIST_HEAD(pers_list);
static DEFINE_SPINLOCK(pers_lock);
static void md_end_flush(struct bio *bio, int err)
{
- mdk_rdev_t *rdev = bio->bi_private;
+ struct md_rdev *rdev = bio->bi_private;
mddev_t *mddev = rdev->mddev;
rdev_dec_pending(rdev, mddev);
static void submit_flushes(struct work_struct *ws)
{
mddev_t *mddev = container_of(ws, mddev_t, flush_work);
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
INIT_WORK(&mddev->flush_work, md_submit_flush_data);
atomic_set(&mddev->flush_pending, 1);
} else
mutex_unlock(&mddev->reconfig_mutex);
+ /* was we've dropped the mutex we need a spinlock to
+ * make sur the thread doesn't disappear
+ */
+ spin_lock(&pers_lock);
md_wakeup_thread(mddev->thread);
+ spin_unlock(&pers_lock);
}
-static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+static struct md_rdev * find_rdev_nr(mddev_t *mddev, int nr)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->desc_nr == nr)
return NULL;
}
-static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
+static struct md_rdev * find_rdev(mddev_t * mddev, dev_t dev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->bdev->bd_dev == dev)
}
/* return the offset of the super block in 512byte sectors */
-static inline sector_t calc_dev_sboffset(mdk_rdev_t *rdev)
+static inline sector_t calc_dev_sboffset(struct md_rdev *rdev)
{
sector_t num_sectors = i_size_read(rdev->bdev->bd_inode) / 512;
return MD_NEW_SIZE_SECTORS(num_sectors);
}
-static int alloc_disk_sb(mdk_rdev_t * rdev)
+static int alloc_disk_sb(struct md_rdev * rdev)
{
if (rdev->sb_page)
MD_BUG();
return 0;
}
-static void free_disk_sb(mdk_rdev_t * rdev)
+static void free_disk_sb(struct md_rdev * rdev)
{
if (rdev->sb_page) {
put_page(rdev->sb_page);
static void super_written(struct bio *bio, int error)
{
- mdk_rdev_t *rdev = bio->bi_private;
+ struct md_rdev *rdev = bio->bi_private;
mddev_t *mddev = rdev->mddev;
if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) {
bio_put(bio);
}
-void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+void md_super_write(mddev_t *mddev, struct md_rdev *rdev,
sector_t sector, int size, struct page *page)
{
/* write first size bytes of page to sector of rdev
bio->bi_end_io = super_written;
atomic_inc(&mddev->pending_writes);
- submit_bio(REQ_WRITE | REQ_SYNC | REQ_FLUSH | REQ_FUA, bio);
+ submit_bio(WRITE_FLUSH_FUA, bio);
}
void md_super_wait(mddev_t *mddev)
complete((struct completion*)bio->bi_private);
}
-int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
+int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
struct page *page, int rw, bool metadata_op)
{
struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
}
EXPORT_SYMBOL_GPL(sync_page_io);
-static int read_disk_sb(mdk_rdev_t * rdev, int size)
+static int read_disk_sb(struct md_rdev * rdev, int size)
{
char b[BDEVNAME_SIZE];
if (!rdev->sb_page) {
* We rely on user-space to write the initial superblock, and support
* reading and updating of superblocks.
* Interface methods are:
- * int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev, int minor_version)
+ * int load_super(struct md_rdev *dev, struct md_rdev *refdev, int minor_version)
* loads and validates a superblock on dev.
* if refdev != NULL, compare superblocks on both devices
* Return:
* -EINVAL superblock incompatible or invalid
* -othererror e.g. -EIO
*
- * int validate_super(mddev_t *mddev, mdk_rdev_t *dev)
+ * int validate_super(mddev_t *mddev, struct md_rdev *dev)
* Verify that dev is acceptable into mddev.
* The first time, mddev->raid_disks will be 0, and data from
* dev should be merged in. Subsequent calls check that dev
* is new enough. Return 0 or -EINVAL
*
- * void sync_super(mddev_t *mddev, mdk_rdev_t *dev)
+ * void sync_super(mddev_t *mddev, struct md_rdev *dev)
* Update the superblock for rdev with data in mddev
* This does not write to disc.
*
struct super_type {
char *name;
struct module *owner;
- int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev,
+ int (*load_super)(struct md_rdev *rdev, struct md_rdev *refdev,
int minor_version);
- int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
- void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
- unsigned long long (*rdev_size_change)(mdk_rdev_t *rdev,
+ int (*validate_super)(mddev_t *mddev, struct md_rdev *rdev);
+ void (*sync_super)(mddev_t *mddev, struct md_rdev *rdev);
+ unsigned long long (*rdev_size_change)(struct md_rdev *rdev,
sector_t num_sectors);
};
/*
* load_super for 0.90.0
*/
-static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
{
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
mdp_super_t *sb;
ret = 0;
}
rdev->sectors = rdev->sb_start;
+ /* Limit to 4TB as metadata cannot record more than that */
+ if (rdev->sectors >= (2ULL << 32))
+ rdev->sectors = (2ULL << 32) - 2;
- if (rdev->sectors < sb->size * 2 && sb->level > 1)
+ if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1)
/* "this cannot possibly happen" ... */
ret = -EINVAL;
/*
* validate_super for 0.90.0
*/
-static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_90_validate(mddev_t *mddev, struct md_rdev *rdev)
{
mdp_disk_t *desc;
mdp_super_t *sb = page_address(rdev->sb_page);
mddev->clevel[0] = 0;
mddev->layout = sb->layout;
mddev->raid_disks = sb->raid_disks;
- mddev->dev_sectors = sb->size * 2;
+ mddev->dev_sectors = ((sector_t)sb->size) * 2;
mddev->events = ev1;
mddev->bitmap_info.offset = 0;
mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9;
/*
* sync_super for 0.90.0
*/
-static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_90_sync(mddev_t *mddev, struct md_rdev *rdev)
{
mdp_super_t *sb;
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
int next_spare = mddev->raid_disks;
* rdev_size_change for 0.90.0
*/
static unsigned long long
-super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
{
if (num_sectors && num_sectors < rdev->mddev->dev_sectors)
return 0; /* component must fit device */
rdev->sb_start = calc_dev_sboffset(rdev);
if (!num_sectors || num_sectors > rdev->sb_start)
num_sectors = rdev->sb_start;
+ /* Limit to 4TB as metadata cannot record more than that.
+ * 4TB == 2^32 KB, or 2*2^32 sectors.
+ */
+ if (num_sectors >= (2ULL << 32))
+ num_sectors = (2ULL << 32) - 2;
md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
rdev->sb_page);
md_super_wait(rdev->mddev);
static int md_set_badblocks(struct badblocks *bb, sector_t s, int sectors,
int acknowledged);
-static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
+static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
{
struct mdp_superblock_1 *sb;
int ret;
return ret;
}
-static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
+static int super_1_validate(mddev_t *mddev, struct md_rdev *rdev)
{
struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
__u64 ev1 = le64_to_cpu(sb->events);
return 0;
}
-static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
+static void super_1_sync(mddev_t *mddev, struct md_rdev *rdev)
{
struct mdp_superblock_1 *sb;
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
int max_dev, i;
/* make rdev->sb match mddev and rdev data. */
sb->level = cpu_to_le32(mddev->level);
sb->layout = cpu_to_le32(mddev->layout);
+ if (test_bit(WriteMostly, &rdev->flags))
+ sb->devflags |= WriteMostly1;
+ else
+ sb->devflags &= ~WriteMostly1;
+
if (mddev->bitmap && mddev->bitmap_info.file == NULL) {
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_info.offset);
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
}
static unsigned long long
-super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
{
struct mdp_superblock_1 *sb;
sector_t max_sectors;
},
};
-static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev)
+static void sync_super(mddev_t *mddev, struct md_rdev *rdev)
{
if (mddev->sync_super) {
mddev->sync_super(mddev, rdev);
static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
{
- mdk_rdev_t *rdev, *rdev2;
+ struct md_rdev *rdev, *rdev2;
rcu_read_lock();
rdev_for_each_rcu(rdev, mddev1)
*/
int md_integrity_register(mddev_t *mddev)
{
- mdk_rdev_t *rdev, *reference = NULL;
+ struct md_rdev *rdev, *reference = NULL;
if (list_empty(&mddev->disks))
return 0; /* nothing to do */
EXPORT_SYMBOL(md_integrity_register);
/* Disable data integrity if non-capable/non-matching disk is being added */
-void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_integrity_add_rdev(struct md_rdev *rdev, mddev_t *mddev)
{
struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
}
EXPORT_SYMBOL(md_integrity_add_rdev);
-static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
+static int bind_rdev_to_array(struct md_rdev * rdev, mddev_t * mddev)
{
char b[BDEVNAME_SIZE];
struct kobject *ko;
static void md_delayed_delete(struct work_struct *ws)
{
- mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work);
+ struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work);
kobject_del(&rdev->kobj);
kobject_put(&rdev->kobj);
}
-static void unbind_rdev_from_array(mdk_rdev_t * rdev)
+static void unbind_rdev_from_array(struct md_rdev * rdev)
{
char b[BDEVNAME_SIZE];
if (!rdev->mddev) {
* otherwise reused by a RAID array (or any other kernel
* subsystem), by bd_claiming the device.
*/
-static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
+static int lock_rdev(struct md_rdev *rdev, dev_t dev, int shared)
{
int err = 0;
struct block_device *bdev;
char b[BDEVNAME_SIZE];
bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
- shared ? (mdk_rdev_t *)lock_rdev : rdev);
+ shared ? (struct md_rdev *)lock_rdev : rdev);
if (IS_ERR(bdev)) {
printk(KERN_ERR "md: could not open %s.\n",
__bdevname(dev, b));
return err;
}
-static void unlock_rdev(mdk_rdev_t *rdev)
+static void unlock_rdev(struct md_rdev *rdev)
{
struct block_device *bdev = rdev->bdev;
rdev->bdev = NULL;
void md_autodetect_dev(dev_t dev);
-static void export_rdev(mdk_rdev_t * rdev)
+static void export_rdev(struct md_rdev * rdev)
{
char b[BDEVNAME_SIZE];
printk(KERN_INFO "md: export_rdev(%s)\n",
kobject_put(&rdev->kobj);
}
-static void kick_rdev_from_array(mdk_rdev_t * rdev)
+static void kick_rdev_from_array(struct md_rdev * rdev)
{
unbind_rdev_from_array(rdev);
export_rdev(rdev);
static void export_array(mddev_t *mddev)
{
- mdk_rdev_t *rdev, *tmp;
+ struct md_rdev *rdev, *tmp;
rdev_for_each(rdev, tmp, mddev) {
if (!rdev->mddev) {
);
}
-static void print_rdev(mdk_rdev_t *rdev, int major_version)
+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",
static void md_print_devices(void)
{
struct list_head *tmp;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
mddev_t *mddev;
char b[BDEVNAME_SIZE];
* (which would mean they aren't being marked as dirty
* with the rest of the array)
*/
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->sb_events == mddev->events ||
(nospares &&
static void md_update_sb(mddev_t * mddev, int force_change)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int sync_req;
int nospares = 0;
int any_badblocks_changed = 0;
sync_sbs(mddev, nospares);
spin_unlock_irq(&mddev->write_lock);
- dprintk(KERN_INFO
- "md: updating %s RAID superblock on device (in sync %d)\n",
- mdname(mddev),mddev->in_sync);
+ pr_debug("md: updating %s RAID superblock on device (in sync %d)\n",
+ mdname(mddev), mddev->in_sync);
bitmap_update_sb(mddev->bitmap);
list_for_each_entry(rdev, &mddev->disks, same_set) {
char b[BDEVNAME_SIZE];
- dprintk(KERN_INFO "md: ");
+
if (rdev->sb_loaded != 1)
continue; /* no noise on spare devices */
- if (test_bit(Faulty, &rdev->flags))
- dprintk("(skipping faulty ");
- dprintk("%s ", bdevname(rdev->bdev,b));
if (!test_bit(Faulty, &rdev->flags)) {
md_super_write(mddev,rdev,
rdev->sb_start, rdev->sb_size,
rdev->sb_page);
- dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
- bdevname(rdev->bdev,b),
- (unsigned long long)rdev->sb_start);
+ pr_debug("md: (write) %s's sb offset: %llu\n",
+ bdevname(rdev->bdev, b),
+ (unsigned long long)rdev->sb_start);
rdev->sb_events = mddev->events;
if (rdev->badblocks.size) {
md_super_write(mddev, rdev,
}
} else
- dprintk(")\n");
+ pr_debug("md: %s (skipping faulty)\n",
+ bdevname(rdev->bdev, b));
if (mddev->level == LEVEL_MULTIPATH)
/* only need to write one superblock... */
break;
struct rdev_sysfs_entry {
struct attribute attr;
- ssize_t (*show)(mdk_rdev_t *, char *);
- ssize_t (*store)(mdk_rdev_t *, const char *, size_t);
+ ssize_t (*show)(struct md_rdev *, char *);
+ ssize_t (*store)(struct md_rdev *, const char *, size_t);
};
static ssize_t
-state_show(mdk_rdev_t *rdev, char *page)
+state_show(struct md_rdev *rdev, char *page)
{
char *sep = "";
size_t len = 0;
}
static ssize_t
-state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+state_store(struct md_rdev *rdev, const char *buf, size_t len)
{
/* can write
* faulty - simulates an error
int err = -EINVAL;
if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
md_error(rdev->mddev, rdev);
- err = 0;
+ if (test_bit(Faulty, &rdev->flags))
+ err = 0;
+ else
+ err = -EBUSY;
} else if (cmd_match(buf, "remove")) {
if (rdev->raid_disk >= 0)
err = -EBUSY;
err = 0;
} else if (cmd_match(buf, "-blocked")) {
if (!test_bit(Faulty, &rdev->flags) &&
- test_bit(BlockedBadBlocks, &rdev->flags)) {
+ rdev->badblocks.unacked_exist) {
/* metadata handler doesn't understand badblocks,
* so we need to fail the device
*/
__ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store);
static ssize_t
-errors_show(mdk_rdev_t *rdev, char *page)
+errors_show(struct md_rdev *rdev, char *page)
{
return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
}
static ssize_t
-errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+errors_store(struct md_rdev *rdev, const char *buf, size_t len)
{
char *e;
unsigned long n = simple_strtoul(buf, &e, 10);
__ATTR(errors, S_IRUGO|S_IWUSR, errors_show, errors_store);
static ssize_t
-slot_show(mdk_rdev_t *rdev, char *page)
+slot_show(struct md_rdev *rdev, char *page)
{
if (rdev->raid_disk < 0)
return sprintf(page, "none\n");
}
static ssize_t
-slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+slot_store(struct md_rdev *rdev, const char *buf, size_t len)
{
char *e;
int err;
set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
md_wakeup_thread(rdev->mddev->thread);
} else if (rdev->mddev->pers) {
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
/* Activating a spare .. or possibly reactivating
* if we ever get bitmaps working here.
*/
__ATTR(slot, S_IRUGO|S_IWUSR, slot_show, slot_store);
static ssize_t
-offset_show(mdk_rdev_t *rdev, char *page)
+offset_show(struct md_rdev *rdev, char *page)
{
return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset);
}
static ssize_t
-offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+offset_store(struct md_rdev *rdev, const char *buf, size_t len)
{
char *e;
unsigned long long offset = simple_strtoull(buf, &e, 10);
__ATTR(offset, S_IRUGO|S_IWUSR, offset_show, offset_store);
static ssize_t
-rdev_size_show(mdk_rdev_t *rdev, char *page)
+rdev_size_show(struct md_rdev *rdev, char *page)
{
return sprintf(page, "%llu\n", (unsigned long long)rdev->sectors / 2);
}
}
static ssize_t
-rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
{
mddev_t *my_mddev = rdev->mddev;
sector_t oldsectors = rdev->sectors;
mddev_unlock(my_mddev);
for_each_mddev(mddev, tmp) {
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
mddev_lock(mddev);
list_for_each_entry(rdev2, &mddev->disks, same_set)
__ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store);
-static ssize_t recovery_start_show(mdk_rdev_t *rdev, char *page)
+static ssize_t recovery_start_show(struct md_rdev *rdev, char *page)
{
unsigned long long recovery_start = rdev->recovery_offset;
return sprintf(page, "%llu\n", recovery_start);
}
-static ssize_t recovery_start_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+static ssize_t recovery_start_store(struct md_rdev *rdev, const char *buf, size_t len)
{
unsigned long long recovery_start;
static ssize_t
badblocks_store(struct badblocks *bb, const char *page, size_t len, int unack);
-static ssize_t bb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t bb_show(struct md_rdev *rdev, char *page)
{
return badblocks_show(&rdev->badblocks, page, 0);
}
-static ssize_t bb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t bb_store(struct md_rdev *rdev, const char *page, size_t len)
{
int rv = badblocks_store(&rdev->badblocks, page, len, 0);
/* Maybe that ack was all we needed */
__ATTR(bad_blocks, S_IRUGO|S_IWUSR, bb_show, bb_store);
-static ssize_t ubb_show(mdk_rdev_t *rdev, char *page)
+static ssize_t ubb_show(struct md_rdev *rdev, char *page)
{
return badblocks_show(&rdev->badblocks, page, 1);
}
-static ssize_t ubb_store(mdk_rdev_t *rdev, const char *page, size_t len)
+static ssize_t ubb_store(struct md_rdev *rdev, const char *page, size_t len)
{
return badblocks_store(&rdev->badblocks, page, len, 1);
}
rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
- mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
+ struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
mddev_t *mddev = rdev->mddev;
ssize_t rv;
const char *page, size_t length)
{
struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
- mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
+ struct md_rdev *rdev = container_of(kobj, struct md_rdev, kobj);
ssize_t rv;
mddev_t *mddev = rdev->mddev;
static void rdev_free(struct kobject *ko)
{
- mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj);
+ struct md_rdev *rdev = container_of(ko, struct md_rdev, kobj);
kfree(rdev);
}
static const struct sysfs_ops rdev_sysfs_ops = {
.default_attrs = rdev_default_attrs,
};
-int md_rdev_init(mdk_rdev_t *rdev)
+int md_rdev_init(struct md_rdev *rdev)
{
rdev->desc_nr = -1;
rdev->saved_raid_disk = -1;
*
* a faulty rdev _never_ has rdev->sb set.
*/
-static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor)
+static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
{
char b[BDEVNAME_SIZE];
int err;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
sector_t size;
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
static void analyze_sbs(mddev_t * mddev)
{
int i;
- mdk_rdev_t *rdev, *freshest, *tmp;
+ struct md_rdev *rdev, *freshest, *tmp;
char b[BDEVNAME_SIZE];
freshest = NULL;
struct mdk_personality *pers;
long level;
void *priv;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (mddev->pers == NULL) {
if (len == 0)
int major = simple_strtoul(buf, &e, 10);
int minor;
dev_t dev;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int err;
if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
rdev = md_import_device(dev, mddev->major_version,
mddev->minor_version);
if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
- mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
- mdk_rdev_t, same_set);
+ struct md_rdev *rdev0
+ = list_entry(mddev->disks.next,
+ struct md_rdev, same_set);
err = super_types[mddev->major_version]
.load_super(rdev, rdev0, mddev->minor_version);
if (err < 0)
int md_run(mddev_t *mddev)
{
int err;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct mdk_personality *pers;
if (list_empty(&mddev->disks))
* configuration.
*/
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
- mdk_rdev_t *rdev2;
+ struct md_rdev *rdev2;
int warned = 0;
list_for_each_entry(rdev, &mddev->disks, same_set)
static int do_md_stop(mddev_t * mddev, int mode, int is_open)
{
struct gendisk *disk = mddev->gendisk;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
mutex_lock(&mddev->open_mutex);
if (atomic_read(&mddev->openers) > is_open ||
#ifndef MODULE
static void autorun_array(mddev_t *mddev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int err;
if (list_empty(&mddev->disks))
*/
static void autorun_devices(int part)
{
- mdk_rdev_t *rdev0, *rdev, *tmp;
+ struct md_rdev *rdev0, *rdev, *tmp;
mddev_t *mddev;
char b[BDEVNAME_SIZE];
dev_t dev;
LIST_HEAD(candidates);
rdev0 = list_entry(pending_raid_disks.next,
- mdk_rdev_t, same_set);
+ struct md_rdev, same_set);
printk(KERN_INFO "md: considering %s ...\n",
bdevname(rdev0->bdev,b));
{
mdu_array_info_t info;
int nr,working,insync,failed,spare;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
nr=working=insync=failed=spare=0;
list_for_each_entry(rdev, &mddev->disks, same_set) {
static int get_disk_info(mddev_t * mddev, void __user * arg)
{
mdu_disk_info_t info;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
{
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
dev_t dev = MKDEV(info->major,info->minor);
if (info->major != MAJOR(dev) || info->minor != MINOR(dev))
return PTR_ERR(rdev);
}
if (!list_empty(&mddev->disks)) {
- mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
- mdk_rdev_t, same_set);
+ struct md_rdev *rdev0
+ = list_entry(mddev->disks.next,
+ struct md_rdev, same_set);
err = super_types[mddev->major_version]
.load_super(rdev, rdev0, mddev->minor_version);
if (err < 0) {
static int hot_remove_disk(mddev_t * mddev, dev_t dev)
{
char b[BDEVNAME_SIZE];
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
rdev = find_rdev(mddev, dev);
if (!rdev)
{
char b[BDEVNAME_SIZE];
int err;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (!mddev->pers)
return -ENODEV;
static int update_size(mddev_t *mddev, sector_t num_sectors)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int rv;
int fit = (num_sectors == 0);
static int set_disk_faulty(mddev_t *mddev, dev_t dev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
if (mddev->pers == NULL)
return -ENODEV;
return -ENODEV;
md_error(mddev, rdev);
+ if (!test_bit(Faulty, &rdev->flags))
+ return -EBUSY;
return 0;
}
void md_wakeup_thread(mdk_thread_t *thread)
{
if (thread) {
- dprintk("md: waking up MD thread %s.\n", thread->tsk->comm);
+ pr_debug("md: waking up MD thread %s.\n", thread->tsk->comm);
set_bit(THREAD_WAKEUP, &thread->flags);
wake_up(&thread->wqueue);
}
return thread;
}
-void md_unregister_thread(mdk_thread_t *thread)
+void md_unregister_thread(mdk_thread_t **threadp)
{
+ mdk_thread_t *thread = *threadp;
if (!thread)
return;
- dprintk("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
+ pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
+ /* Locking ensures that mddev_unlock does not wake_up a
+ * non-existent thread
+ */
+ spin_lock(&pers_lock);
+ *threadp = NULL;
+ spin_unlock(&pers_lock);
kthread_stop(thread->tsk);
kfree(thread);
}
-void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
+void md_error(mddev_t *mddev, struct md_rdev *rdev)
{
if (!mddev) {
MD_BUG();
static void status_unused(struct seq_file *seq)
{
int i = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
seq_printf(seq, "unused devices: ");
{
mddev_t *mddev = v;
sector_t sectors;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct bitmap *bitmap;
if (v == (void*)1) {
static int is_mddev_idle(mddev_t *mddev, int init)
{
- mdk_rdev_t * rdev;
+ struct md_rdev * rdev;
int idle;
int curr_events;
struct list_head *tmp;
sector_t last_check;
int skipped = 0;
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
char *desc;
/* just incase thread restarts... */
static int remove_and_add_spares(mddev_t *mddev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
int spares = 0;
mddev->curr_resync_completed = 0;
static void reap_sync_thread(mddev_t *mddev)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
/* resync has finished, collect result */
- md_unregister_thread(mddev->sync_thread);
- mddev->sync_thread = NULL;
+ md_unregister_thread(&mddev->sync_thread);
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* success...*/
/* Only thing we do on a ro array is remove
* failed devices.
*/
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
!test_bit(Blocked, &rdev->flags) &&
}
}
-void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+void md_wait_for_blocked_rdev(struct md_rdev *rdev, mddev_t *mddev)
{
sysfs_notify_dirent_safe(rdev->sysfs_state);
wait_event_timeout(rdev->blocked_wait,
return rv;
}
-int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors,
+int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
int acknowledged)
{
int rv = md_set_badblocks(&rdev->badblocks,
return rv;
}
-int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors)
+int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors)
{
return md_clear_badblocks(&rdev->badblocks,
s + rdev->data_offset,
{
struct list_head *tmp;
mddev_t *mddev;
+ int need_delay = 0;
if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) {
printk(KERN_INFO "md: stopping all md devices.\n");
- for_each_mddev(mddev, tmp)
+ for_each_mddev(mddev, tmp) {
if (mddev_trylock(mddev)) {
/* Force a switch to readonly even array
* appears to still be in use. Hence
md_set_readonly(mddev, 100);
mddev_unlock(mddev);
}
+ need_delay = 1;
+ }
/*
* certain more exotic SCSI devices are known to be
* volatile wrt too early system reboots. While the
* right place to handle this issue is the given
* driver, we do want to have a safe RAID driver ...
*/
- mdelay(1000*1);
+ if (need_delay)
+ mdelay(1000*1);
}
return NOTIFY_DONE;
}
static void md_geninit(void)
{
- dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
+ pr_debug("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
}
static void autostart_arrays(int part)
{
- mdk_rdev_t *rdev;
+ struct md_rdev *rdev;
struct detected_devices_node *node_detected_dev;
dev_t dev;
int i_scanned, i_passed;