Commit 638691a7 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://neil.brown.name/md

* 'for-linus' of git://neil.brown.name/md:
  md: Fix - again - partition detection when array becomes active
  Fix over-zealous flush_disk when changing device size.
  md: avoid spinlock problem in blk_throtl_exit
  md: correctly handle probe of an 'mdp' device.
  md: don't set_capacity before array is active.
  md: Fix raid1->raid0 takeover
parents 0a93ea2e f0b4f7e2
...@@ -1355,7 +1355,7 @@ int invalidate_partition(struct gendisk *disk, int partno) ...@@ -1355,7 +1355,7 @@ int invalidate_partition(struct gendisk *disk, int partno)
struct block_device *bdev = bdget_disk(disk, partno); struct block_device *bdev = bdget_disk(disk, partno);
if (bdev) { if (bdev) {
fsync_bdev(bdev); fsync_bdev(bdev);
res = __invalidate_device(bdev); res = __invalidate_device(bdev, true);
bdput(bdev); bdput(bdev);
} }
return res; return res;
......
...@@ -3281,7 +3281,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, ...@@ -3281,7 +3281,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
struct block_device *bdev = opened_bdev[cnt]; struct block_device *bdev = opened_bdev[cnt];
if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
continue; continue;
__invalidate_device(bdev); __invalidate_device(bdev, true);
} }
mutex_unlock(&open_lock); mutex_unlock(&open_lock);
} else { } else {
......
...@@ -216,7 +216,6 @@ static int linear_run (mddev_t *mddev) ...@@ -216,7 +216,6 @@ static int linear_run (mddev_t *mddev)
if (md_check_no_bitmap(mddev)) if (md_check_no_bitmap(mddev))
return -EINVAL; return -EINVAL;
mddev->queue->queue_lock = &mddev->queue->__queue_lock;
conf = linear_conf(mddev, mddev->raid_disks); conf = linear_conf(mddev, mddev->raid_disks);
if (!conf) if (!conf)
......
...@@ -553,6 +553,9 @@ static mddev_t * mddev_find(dev_t unit) ...@@ -553,6 +553,9 @@ static mddev_t * mddev_find(dev_t unit)
{ {
mddev_t *mddev, *new = NULL; mddev_t *mddev, *new = NULL;
if (unit && MAJOR(unit) != MD_MAJOR)
unit &= ~((1<<MdpMinorShift)-1);
retry: retry:
spin_lock(&all_mddevs_lock); spin_lock(&all_mddevs_lock);
...@@ -4138,10 +4141,10 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len) ...@@ -4138,10 +4141,10 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len)
} }
mddev->array_sectors = sectors; mddev->array_sectors = sectors;
if (mddev->pers) {
set_capacity(mddev->gendisk, mddev->array_sectors); set_capacity(mddev->gendisk, mddev->array_sectors);
if (mddev->pers)
revalidate_disk(mddev->gendisk); revalidate_disk(mddev->gendisk);
}
return len; return len;
} }
...@@ -4624,6 +4627,7 @@ static int do_md_run(mddev_t *mddev) ...@@ -4624,6 +4627,7 @@ static int do_md_run(mddev_t *mddev)
} }
set_capacity(mddev->gendisk, mddev->array_sectors); set_capacity(mddev->gendisk, mddev->array_sectors);
revalidate_disk(mddev->gendisk); revalidate_disk(mddev->gendisk);
mddev->changed = 1;
kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
out: out:
return err; return err;
...@@ -4712,6 +4716,7 @@ static void md_clean(mddev_t *mddev) ...@@ -4712,6 +4716,7 @@ static void md_clean(mddev_t *mddev)
mddev->sync_speed_min = mddev->sync_speed_max = 0; mddev->sync_speed_min = mddev->sync_speed_max = 0;
mddev->recovery = 0; mddev->recovery = 0;
mddev->in_sync = 0; mddev->in_sync = 0;
mddev->changed = 0;
mddev->degraded = 0; mddev->degraded = 0;
mddev->safemode = 0; mddev->safemode = 0;
mddev->bitmap_info.offset = 0; mddev->bitmap_info.offset = 0;
...@@ -4827,6 +4832,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) ...@@ -4827,6 +4832,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
set_capacity(disk, 0); set_capacity(disk, 0);
mutex_unlock(&mddev->open_mutex); mutex_unlock(&mddev->open_mutex);
mddev->changed = 1;
revalidate_disk(disk); revalidate_disk(disk);
if (mddev->ro) if (mddev->ro)
...@@ -6011,7 +6017,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) ...@@ -6011,7 +6017,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
atomic_inc(&mddev->openers); atomic_inc(&mddev->openers);
mutex_unlock(&mddev->open_mutex); mutex_unlock(&mddev->open_mutex);
check_disk_size_change(mddev->gendisk, bdev); check_disk_change(bdev);
out: out:
return err; return err;
} }
...@@ -6026,6 +6032,21 @@ static int md_release(struct gendisk *disk, fmode_t mode) ...@@ -6026,6 +6032,21 @@ static int md_release(struct gendisk *disk, fmode_t mode)
return 0; return 0;
} }
static int md_media_changed(struct gendisk *disk)
{
mddev_t *mddev = disk->private_data;
return mddev->changed;
}
static int md_revalidate(struct gendisk *disk)
{
mddev_t *mddev = disk->private_data;
mddev->changed = 0;
return 0;
}
static const struct block_device_operations md_fops = static const struct block_device_operations md_fops =
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -6036,6 +6057,8 @@ static const struct block_device_operations md_fops = ...@@ -6036,6 +6057,8 @@ static const struct block_device_operations md_fops =
.compat_ioctl = md_compat_ioctl, .compat_ioctl = md_compat_ioctl,
#endif #endif
.getgeo = md_getgeo, .getgeo = md_getgeo,
.media_changed = md_media_changed,
.revalidate_disk= md_revalidate,
}; };
static int md_thread(void * arg) static int md_thread(void * arg)
......
...@@ -274,6 +274,8 @@ struct mddev_s ...@@ -274,6 +274,8 @@ struct mddev_s
atomic_t active; /* general refcount */ atomic_t active; /* general refcount */
atomic_t openers; /* number of active opens */ atomic_t openers; /* number of active opens */
int changed; /* True if we might need to
* reread partition info */
int degraded; /* whether md should consider int degraded; /* whether md should consider
* adding a spare * adding a spare
*/ */
......
...@@ -435,7 +435,6 @@ static int multipath_run (mddev_t *mddev) ...@@ -435,7 +435,6 @@ static int multipath_run (mddev_t *mddev)
* bookkeeping area. [whatever we allocate in multipath_run(), * bookkeeping area. [whatever we allocate in multipath_run(),
* should be freed in multipath_stop()] * should be freed in multipath_stop()]
*/ */
mddev->queue->queue_lock = &mddev->queue->__queue_lock;
conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL); conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
mddev->private = conf; mddev->private = conf;
......
...@@ -361,7 +361,6 @@ static int raid0_run(mddev_t *mddev) ...@@ -361,7 +361,6 @@ static int raid0_run(mddev_t *mddev)
if (md_check_no_bitmap(mddev)) if (md_check_no_bitmap(mddev))
return -EINVAL; return -EINVAL;
blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
mddev->queue->queue_lock = &mddev->queue->__queue_lock;
/* if private is not null, we are here after takeover */ /* if private is not null, we are here after takeover */
if (mddev->private == NULL) { if (mddev->private == NULL) {
...@@ -670,6 +669,7 @@ static void *raid0_takeover_raid1(mddev_t *mddev) ...@@ -670,6 +669,7 @@ static void *raid0_takeover_raid1(mddev_t *mddev)
mddev->new_layout = 0; mddev->new_layout = 0;
mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */ mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */
mddev->delta_disks = 1 - mddev->raid_disks; mddev->delta_disks = 1 - mddev->raid_disks;
mddev->raid_disks = 1;
/* make sure it will be not marked as dirty */ /* make sure it will be not marked as dirty */
mddev->recovery_cp = MaxSector; mddev->recovery_cp = MaxSector;
......
...@@ -593,7 +593,10 @@ static int flush_pending_writes(conf_t *conf) ...@@ -593,7 +593,10 @@ static int flush_pending_writes(conf_t *conf)
if (conf->pending_bio_list.head) { if (conf->pending_bio_list.head) {
struct bio *bio; struct bio *bio;
bio = bio_list_get(&conf->pending_bio_list); bio = bio_list_get(&conf->pending_bio_list);
/* Only take the spinlock to quiet a warning */
spin_lock(conf->mddev->queue->queue_lock);
blk_remove_plug(conf->mddev->queue); blk_remove_plug(conf->mddev->queue);
spin_unlock(conf->mddev->queue->queue_lock);
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
/* flush any pending bitmap writes to /* flush any pending bitmap writes to
* disk before proceeding w/ I/O */ * disk before proceeding w/ I/O */
...@@ -959,7 +962,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) ...@@ -959,7 +962,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
atomic_inc(&r1_bio->remaining); atomic_inc(&r1_bio->remaining);
spin_lock_irqsave(&conf->device_lock, flags); spin_lock_irqsave(&conf->device_lock, flags);
bio_list_add(&conf->pending_bio_list, mbio); bio_list_add(&conf->pending_bio_list, mbio);
blk_plug_device(mddev->queue); blk_plug_device_unlocked(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags); spin_unlock_irqrestore(&conf->device_lock, flags);
} }
r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL); r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL);
...@@ -2021,7 +2024,6 @@ static int run(mddev_t *mddev) ...@@ -2021,7 +2024,6 @@ static int run(mddev_t *mddev)
if (IS_ERR(conf)) if (IS_ERR(conf))
return PTR_ERR(conf); return PTR_ERR(conf);
mddev->queue->queue_lock = &conf->device_lock;
list_for_each_entry(rdev, &mddev->disks, same_set) { list_for_each_entry(rdev, &mddev->disks, same_set) {
disk_stack_limits(mddev->gendisk, rdev->bdev, disk_stack_limits(mddev->gendisk, rdev->bdev,
rdev->data_offset << 9); rdev->data_offset << 9);
......
...@@ -662,7 +662,10 @@ static int flush_pending_writes(conf_t *conf) ...@@ -662,7 +662,10 @@ static int flush_pending_writes(conf_t *conf)
if (conf->pending_bio_list.head) { if (conf->pending_bio_list.head) {
struct bio *bio; struct bio *bio;
bio = bio_list_get(&conf->pending_bio_list); bio = bio_list_get(&conf->pending_bio_list);
/* Spinlock only taken to quiet a warning */
spin_lock(conf->mddev->queue->queue_lock);
blk_remove_plug(conf->mddev->queue); blk_remove_plug(conf->mddev->queue);
spin_unlock(conf->mddev->queue->queue_lock);
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
/* flush any pending bitmap writes to disk /* flush any pending bitmap writes to disk
* before proceeding w/ I/O */ * before proceeding w/ I/O */
...@@ -971,7 +974,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) ...@@ -971,7 +974,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
atomic_inc(&r10_bio->remaining); atomic_inc(&r10_bio->remaining);
spin_lock_irqsave(&conf->device_lock, flags); spin_lock_irqsave(&conf->device_lock, flags);
bio_list_add(&conf->pending_bio_list, mbio); bio_list_add(&conf->pending_bio_list, mbio);
blk_plug_device(mddev->queue); blk_plug_device_unlocked(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags); spin_unlock_irqrestore(&conf->device_lock, flags);
} }
...@@ -2304,8 +2307,6 @@ static int run(mddev_t *mddev) ...@@ -2304,8 +2307,6 @@ static int run(mddev_t *mddev)
if (!conf) if (!conf)
goto out; goto out;
mddev->queue->queue_lock = &conf->device_lock;
mddev->thread = conf->thread; mddev->thread = conf->thread;
conf->thread = NULL; conf->thread = NULL;
......
...@@ -5204,7 +5204,6 @@ static int run(mddev_t *mddev) ...@@ -5204,7 +5204,6 @@ static int run(mddev_t *mddev)
mddev->queue->backing_dev_info.congested_data = mddev; mddev->queue->backing_dev_info.congested_data = mddev;
mddev->queue->backing_dev_info.congested_fn = raid5_congested; mddev->queue->backing_dev_info.congested_fn = raid5_congested;
mddev->queue->queue_lock = &conf->device_lock;
mddev->queue->unplug_fn = raid5_unplug_queue; mddev->queue->unplug_fn = raid5_unplug_queue;
chunk_size = mddev->chunk_sectors << 9; chunk_size = mddev->chunk_sectors << 9;
......
...@@ -933,9 +933,9 @@ EXPORT_SYMBOL_GPL(bd_unlink_disk_holder); ...@@ -933,9 +933,9 @@ EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
* when a disk has been changed -- either by a media change or online * when a disk has been changed -- either by a media change or online
* resize. * resize.
*/ */
static void flush_disk(struct block_device *bdev) static void flush_disk(struct block_device *bdev, bool kill_dirty)
{ {
if (__invalidate_device(bdev)) { if (__invalidate_device(bdev, kill_dirty)) {
char name[BDEVNAME_SIZE] = ""; char name[BDEVNAME_SIZE] = "";
if (bdev->bd_disk) if (bdev->bd_disk)
...@@ -972,7 +972,7 @@ void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) ...@@ -972,7 +972,7 @@ void check_disk_size_change(struct gendisk *disk, struct block_device *bdev)
"%s: detected capacity change from %lld to %lld\n", "%s: detected capacity change from %lld to %lld\n",
name, bdev_size, disk_size); name, bdev_size, disk_size);
i_size_write(bdev->bd_inode, disk_size); i_size_write(bdev->bd_inode, disk_size);
flush_disk(bdev); flush_disk(bdev, false);
} }
} }
EXPORT_SYMBOL(check_disk_size_change); EXPORT_SYMBOL(check_disk_size_change);
...@@ -1025,7 +1025,7 @@ int check_disk_change(struct block_device *bdev) ...@@ -1025,7 +1025,7 @@ int check_disk_change(struct block_device *bdev)
if (!(events & DISK_EVENT_MEDIA_CHANGE)) if (!(events & DISK_EVENT_MEDIA_CHANGE))
return 0; return 0;
flush_disk(bdev); flush_disk(bdev, true);
if (bdops->revalidate_disk) if (bdops->revalidate_disk)
bdops->revalidate_disk(bdev->bd_disk); bdops->revalidate_disk(bdev->bd_disk);
return 1; return 1;
...@@ -1606,7 +1606,7 @@ struct block_device *lookup_bdev(const char *pathname) ...@@ -1606,7 +1606,7 @@ struct block_device *lookup_bdev(const char *pathname)
} }
EXPORT_SYMBOL(lookup_bdev); EXPORT_SYMBOL(lookup_bdev);
int __invalidate_device(struct block_device *bdev) int __invalidate_device(struct block_device *bdev, bool kill_dirty)
{ {
struct super_block *sb = get_super(bdev); struct super_block *sb = get_super(bdev);
int res = 0; int res = 0;
...@@ -1619,7 +1619,7 @@ int __invalidate_device(struct block_device *bdev) ...@@ -1619,7 +1619,7 @@ int __invalidate_device(struct block_device *bdev)
* hold). * hold).
*/ */
shrink_dcache_sb(sb); shrink_dcache_sb(sb);
res = invalidate_inodes(sb); res = invalidate_inodes(sb, kill_dirty);
drop_super(sb); drop_super(sb);
} }
invalidate_bdev(bdev); invalidate_bdev(bdev);
......
...@@ -548,11 +548,14 @@ void evict_inodes(struct super_block *sb) ...@@ -548,11 +548,14 @@ void evict_inodes(struct super_block *sb)
/** /**
* invalidate_inodes - attempt to free all inodes on a superblock * invalidate_inodes - attempt to free all inodes on a superblock
* @sb: superblock to operate on * @sb: superblock to operate on
* @kill_dirty: flag to guide handling of dirty inodes
* *
* Attempts to free all inodes for a given superblock. If there were any * Attempts to free all inodes for a given superblock. If there were any
* busy inodes return a non-zero value, else zero. * busy inodes return a non-zero value, else zero.
* If @kill_dirty is set, discard dirty inodes too, otherwise treat
* them as busy.
*/ */
int invalidate_inodes(struct super_block *sb) int invalidate_inodes(struct super_block *sb, bool kill_dirty)
{ {
int busy = 0; int busy = 0;
struct inode *inode, *next; struct inode *inode, *next;
...@@ -564,6 +567,10 @@ int invalidate_inodes(struct super_block *sb) ...@@ -564,6 +567,10 @@ int invalidate_inodes(struct super_block *sb)
list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))
continue; continue;
if (inode->i_state & I_DIRTY && !kill_dirty) {
busy = 1;
continue;
}
if (atomic_read(&inode->i_count)) { if (atomic_read(&inode->i_count)) {
busy = 1; busy = 1;
continue; continue;
......
...@@ -112,4 +112,4 @@ extern void release_open_intent(struct nameidata *); ...@@ -112,4 +112,4 @@ extern void release_open_intent(struct nameidata *);
*/ */
extern int get_nr_dirty_inodes(void); extern int get_nr_dirty_inodes(void);
extern void evict_inodes(struct super_block *); extern void evict_inodes(struct super_block *);
extern int invalidate_inodes(struct super_block *); extern int invalidate_inodes(struct super_block *, bool);
...@@ -2140,7 +2140,7 @@ extern void check_disk_size_change(struct gendisk *disk, ...@@ -2140,7 +2140,7 @@ extern void check_disk_size_change(struct gendisk *disk,
struct block_device *bdev); struct block_device *bdev);
extern int revalidate_disk(struct gendisk *); extern int revalidate_disk(struct gendisk *);
extern int check_disk_change(struct block_device *); extern int check_disk_change(struct block_device *);
extern int __invalidate_device(struct block_device *); extern int __invalidate_device(struct block_device *, bool);
extern int invalidate_partition(struct gendisk *, int); extern int invalidate_partition(struct gendisk *, int);
#endif #endif
unsigned long invalidate_mapping_pages(struct address_space *mapping, unsigned long invalidate_mapping_pages(struct address_space *mapping,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment