mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-04 05:46:49 +00:00
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
This commit is contained in:
commit
638691a7a4
@ -1355,7 +1355,7 @@ int invalidate_partition(struct gendisk *disk, int partno)
|
||||
struct block_device *bdev = bdget_disk(disk, partno);
|
||||
if (bdev) {
|
||||
fsync_bdev(bdev);
|
||||
res = __invalidate_device(bdev);
|
||||
res = __invalidate_device(bdev, true);
|
||||
bdput(bdev);
|
||||
}
|
||||
return res;
|
||||
|
@ -3281,7 +3281,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
|
||||
struct block_device *bdev = opened_bdev[cnt];
|
||||
if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
|
||||
continue;
|
||||
__invalidate_device(bdev);
|
||||
__invalidate_device(bdev, true);
|
||||
}
|
||||
mutex_unlock(&open_lock);
|
||||
} else {
|
||||
|
@ -216,7 +216,6 @@ static int linear_run (mddev_t *mddev)
|
||||
|
||||
if (md_check_no_bitmap(mddev))
|
||||
return -EINVAL;
|
||||
mddev->queue->queue_lock = &mddev->queue->__queue_lock;
|
||||
conf = linear_conf(mddev, mddev->raid_disks);
|
||||
|
||||
if (!conf)
|
||||
|
@ -553,6 +553,9 @@ static mddev_t * mddev_find(dev_t unit)
|
||||
{
|
||||
mddev_t *mddev, *new = NULL;
|
||||
|
||||
if (unit && MAJOR(unit) != MD_MAJOR)
|
||||
unit &= ~((1<<MdpMinorShift)-1);
|
||||
|
||||
retry:
|
||||
spin_lock(&all_mddevs_lock);
|
||||
|
||||
@ -4138,10 +4141,10 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len)
|
||||
}
|
||||
|
||||
mddev->array_sectors = sectors;
|
||||
set_capacity(mddev->gendisk, mddev->array_sectors);
|
||||
if (mddev->pers)
|
||||
if (mddev->pers) {
|
||||
set_capacity(mddev->gendisk, mddev->array_sectors);
|
||||
revalidate_disk(mddev->gendisk);
|
||||
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -4624,6 +4627,7 @@ static int do_md_run(mddev_t *mddev)
|
||||
}
|
||||
set_capacity(mddev->gendisk, mddev->array_sectors);
|
||||
revalidate_disk(mddev->gendisk);
|
||||
mddev->changed = 1;
|
||||
kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
|
||||
out:
|
||||
return err;
|
||||
@ -4712,6 +4716,7 @@ static void md_clean(mddev_t *mddev)
|
||||
mddev->sync_speed_min = mddev->sync_speed_max = 0;
|
||||
mddev->recovery = 0;
|
||||
mddev->in_sync = 0;
|
||||
mddev->changed = 0;
|
||||
mddev->degraded = 0;
|
||||
mddev->safemode = 0;
|
||||
mddev->bitmap_info.offset = 0;
|
||||
@ -4827,6 +4832,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
|
||||
|
||||
set_capacity(disk, 0);
|
||||
mutex_unlock(&mddev->open_mutex);
|
||||
mddev->changed = 1;
|
||||
revalidate_disk(disk);
|
||||
|
||||
if (mddev->ro)
|
||||
@ -6011,7 +6017,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
|
||||
atomic_inc(&mddev->openers);
|
||||
mutex_unlock(&mddev->open_mutex);
|
||||
|
||||
check_disk_size_change(mddev->gendisk, bdev);
|
||||
check_disk_change(bdev);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@ -6026,6 +6032,21 @@ static int md_release(struct gendisk *disk, fmode_t mode)
|
||||
|
||||
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 =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
@ -6036,6 +6057,8 @@ static const struct block_device_operations md_fops =
|
||||
.compat_ioctl = md_compat_ioctl,
|
||||
#endif
|
||||
.getgeo = md_getgeo,
|
||||
.media_changed = md_media_changed,
|
||||
.revalidate_disk= md_revalidate,
|
||||
};
|
||||
|
||||
static int md_thread(void * arg)
|
||||
|
@ -274,6 +274,8 @@ struct mddev_s
|
||||
atomic_t active; /* general refcount */
|
||||
atomic_t openers; /* number of active opens */
|
||||
|
||||
int changed; /* True if we might need to
|
||||
* reread partition info */
|
||||
int degraded; /* whether md should consider
|
||||
* adding a spare
|
||||
*/
|
||||
|
@ -435,7 +435,6 @@ static int multipath_run (mddev_t *mddev)
|
||||
* bookkeeping area. [whatever we allocate in multipath_run(),
|
||||
* should be freed in multipath_stop()]
|
||||
*/
|
||||
mddev->queue->queue_lock = &mddev->queue->__queue_lock;
|
||||
|
||||
conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
|
||||
mddev->private = conf;
|
||||
|
@ -361,7 +361,6 @@ static int raid0_run(mddev_t *mddev)
|
||||
if (md_check_no_bitmap(mddev))
|
||||
return -EINVAL;
|
||||
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 (mddev->private == NULL) {
|
||||
@ -670,6 +669,7 @@ static void *raid0_takeover_raid1(mddev_t *mddev)
|
||||
mddev->new_layout = 0;
|
||||
mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */
|
||||
mddev->delta_disks = 1 - mddev->raid_disks;
|
||||
mddev->raid_disks = 1;
|
||||
/* make sure it will be not marked as dirty */
|
||||
mddev->recovery_cp = MaxSector;
|
||||
|
||||
|
@ -593,7 +593,10 @@ static int flush_pending_writes(conf_t *conf)
|
||||
if (conf->pending_bio_list.head) {
|
||||
struct bio *bio;
|
||||
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);
|
||||
spin_unlock(conf->mddev->queue->queue_lock);
|
||||
spin_unlock_irq(&conf->device_lock);
|
||||
/* flush any pending bitmap writes to
|
||||
* disk before proceeding w/ I/O */
|
||||
@ -959,7 +962,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
|
||||
atomic_inc(&r1_bio->remaining);
|
||||
spin_lock_irqsave(&conf->device_lock, flags);
|
||||
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);
|
||||
}
|
||||
r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL);
|
||||
@ -2021,7 +2024,6 @@ static int run(mddev_t *mddev)
|
||||
if (IS_ERR(conf))
|
||||
return PTR_ERR(conf);
|
||||
|
||||
mddev->queue->queue_lock = &conf->device_lock;
|
||||
list_for_each_entry(rdev, &mddev->disks, same_set) {
|
||||
disk_stack_limits(mddev->gendisk, rdev->bdev,
|
||||
rdev->data_offset << 9);
|
||||
|
@ -662,7 +662,10 @@ static int flush_pending_writes(conf_t *conf)
|
||||
if (conf->pending_bio_list.head) {
|
||||
struct bio *bio;
|
||||
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);
|
||||
spin_unlock(conf->mddev->queue->queue_lock);
|
||||
spin_unlock_irq(&conf->device_lock);
|
||||
/* flush any pending bitmap writes to disk
|
||||
* before proceeding w/ I/O */
|
||||
@ -971,7 +974,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
|
||||
atomic_inc(&r10_bio->remaining);
|
||||
spin_lock_irqsave(&conf->device_lock, flags);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2304,8 +2307,6 @@ static int run(mddev_t *mddev)
|
||||
if (!conf)
|
||||
goto out;
|
||||
|
||||
mddev->queue->queue_lock = &conf->device_lock;
|
||||
|
||||
mddev->thread = conf->thread;
|
||||
conf->thread = NULL;
|
||||
|
||||
|
@ -5204,7 +5204,6 @@ static int run(mddev_t *mddev)
|
||||
|
||||
mddev->queue->backing_dev_info.congested_data = mddev;
|
||||
mddev->queue->backing_dev_info.congested_fn = raid5_congested;
|
||||
mddev->queue->queue_lock = &conf->device_lock;
|
||||
mddev->queue->unplug_fn = raid5_unplug_queue;
|
||||
|
||||
chunk_size = mddev->chunk_sectors << 9;
|
||||
|
@ -933,9 +933,9 @@ EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
|
||||
* when a disk has been changed -- either by a media change or online
|
||||
* 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] = "";
|
||||
|
||||
if (bdev->bd_disk)
|
||||
@ -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",
|
||||
name, bdev_size, disk_size);
|
||||
i_size_write(bdev->bd_inode, disk_size);
|
||||
flush_disk(bdev);
|
||||
flush_disk(bdev, false);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(check_disk_size_change);
|
||||
@ -1025,7 +1025,7 @@ int check_disk_change(struct block_device *bdev)
|
||||
if (!(events & DISK_EVENT_MEDIA_CHANGE))
|
||||
return 0;
|
||||
|
||||
flush_disk(bdev);
|
||||
flush_disk(bdev, true);
|
||||
if (bdops->revalidate_disk)
|
||||
bdops->revalidate_disk(bdev->bd_disk);
|
||||
return 1;
|
||||
@ -1606,7 +1606,7 @@ fail:
|
||||
}
|
||||
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);
|
||||
int res = 0;
|
||||
@ -1619,7 +1619,7 @@ int __invalidate_device(struct block_device *bdev)
|
||||
* hold).
|
||||
*/
|
||||
shrink_dcache_sb(sb);
|
||||
res = invalidate_inodes(sb);
|
||||
res = invalidate_inodes(sb, kill_dirty);
|
||||
drop_super(sb);
|
||||
}
|
||||
invalidate_bdev(bdev);
|
||||
|
@ -548,11 +548,14 @@ void evict_inodes(struct super_block *sb)
|
||||
/**
|
||||
* invalidate_inodes - attempt to free all inodes on a superblock
|
||||
* @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
|
||||
* 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;
|
||||
struct inode *inode, *next;
|
||||
@ -564,6 +567,10 @@ int invalidate_inodes(struct super_block *sb)
|
||||
list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
|
||||
if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))
|
||||
continue;
|
||||
if (inode->i_state & I_DIRTY && !kill_dirty) {
|
||||
busy = 1;
|
||||
continue;
|
||||
}
|
||||
if (atomic_read(&inode->i_count)) {
|
||||
busy = 1;
|
||||
continue;
|
||||
|
@ -112,4 +112,4 @@ extern void release_open_intent(struct nameidata *);
|
||||
*/
|
||||
extern int get_nr_dirty_inodes(void);
|
||||
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,
|
||||
struct block_device *bdev);
|
||||
extern int revalidate_disk(struct gendisk *);
|
||||
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);
|
||||
#endif
|
||||
unsigned long invalidate_mapping_pages(struct address_space *mapping,
|
||||
|
Loading…
Reference in New Issue
Block a user