aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-02-24 01:26:41 -0500
committerNeilBrown <neilb@suse.de>2011-02-24 01:26:41 -0500
commitf0b4f7e2f29af678bd9af43422c537dcb6008603 (patch)
treedfc2aa18bbf8411a499ef8117a5e15490eb44728
parent93b270f76e7ef3b81001576860c2701931cdc78b (diff)
md: Fix - again - partition detection when array becomes active
Revert b821eaa572fd737faaf6928ba046e571526c36c6 and f3b99be19ded511a1bf05a148276239d9f13eefa When I wrote the first of these I had a wrong idea about the lifetime of 'struct block_device'. It can disappear at any time that the block device is not open if it falls out of the inode cache. So relying on the 'size' recorded with it to detect when the device size has changed and so we need to revalidate, is wrong. Rather, we really do need the 'changed' attribute stored directly in the mddev and set/tested as appropriate. Without this patch, a sequence of: mknod / open / close / unlink (which can cause a block_device to be created and then destroyed) will result in a rescan of the partition table and consequence removal and addition of partitions. Several of these in a row can get udev racing to create and unlink and other code can get confused. With the patch, the rescan is only performed when needed and so there are no races. This is suitable for any stable kernel from 2.6.35. Reported-by: "Wojcik, Krzysztof" <krzysztof.wojcik@intel.com> Signed-off-by: NeilBrown <neilb@suse.de> Cc: stable@kernel.org
-rw-r--r--drivers/md/md.c22
-rw-r--r--drivers/md/md.h2
2 files changed, 23 insertions, 1 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 330addfe9b7..818313e277e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4627,6 +4627,7 @@ static int do_md_run(mddev_t *mddev)
4627 } 4627 }
4628 set_capacity(mddev->gendisk, mddev->array_sectors); 4628 set_capacity(mddev->gendisk, mddev->array_sectors);
4629 revalidate_disk(mddev->gendisk); 4629 revalidate_disk(mddev->gendisk);
4630 mddev->changed = 1;
4630 kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); 4631 kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
4631out: 4632out:
4632 return err; 4633 return err;
@@ -4715,6 +4716,7 @@ static void md_clean(mddev_t *mddev)
4715 mddev->sync_speed_min = mddev->sync_speed_max = 0; 4716 mddev->sync_speed_min = mddev->sync_speed_max = 0;
4716 mddev->recovery = 0; 4717 mddev->recovery = 0;
4717 mddev->in_sync = 0; 4718 mddev->in_sync = 0;
4719 mddev->changed = 0;
4718 mddev->degraded = 0; 4720 mddev->degraded = 0;
4719 mddev->safemode = 0; 4721 mddev->safemode = 0;
4720 mddev->bitmap_info.offset = 0; 4722 mddev->bitmap_info.offset = 0;
@@ -4830,6 +4832,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
4830 4832
4831 set_capacity(disk, 0); 4833 set_capacity(disk, 0);
4832 mutex_unlock(&mddev->open_mutex); 4834 mutex_unlock(&mddev->open_mutex);
4835 mddev->changed = 1;
4833 revalidate_disk(disk); 4836 revalidate_disk(disk);
4834 4837
4835 if (mddev->ro) 4838 if (mddev->ro)
@@ -6014,7 +6017,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
6014 atomic_inc(&mddev->openers); 6017 atomic_inc(&mddev->openers);
6015 mutex_unlock(&mddev->open_mutex); 6018 mutex_unlock(&mddev->open_mutex);
6016 6019
6017 check_disk_size_change(mddev->gendisk, bdev); 6020 check_disk_change(bdev);
6018 out: 6021 out:
6019 return err; 6022 return err;
6020} 6023}
@@ -6029,6 +6032,21 @@ static int md_release(struct gendisk *disk, fmode_t mode)
6029 6032
6030 return 0; 6033 return 0;
6031} 6034}
6035
6036static int md_media_changed(struct gendisk *disk)
6037{
6038 mddev_t *mddev = disk->private_data;
6039
6040 return mddev->changed;
6041}
6042
6043static int md_revalidate(struct gendisk *disk)
6044{
6045 mddev_t *mddev = disk->private_data;
6046
6047 mddev->changed = 0;
6048 return 0;
6049}
6032static const struct block_device_operations md_fops = 6050static const struct block_device_operations md_fops =
6033{ 6051{
6034 .owner = THIS_MODULE, 6052 .owner = THIS_MODULE,
@@ -6039,6 +6057,8 @@ static const struct block_device_operations md_fops =
6039 .compat_ioctl = md_compat_ioctl, 6057 .compat_ioctl = md_compat_ioctl,
6040#endif 6058#endif
6041 .getgeo = md_getgeo, 6059 .getgeo = md_getgeo,
6060 .media_changed = md_media_changed,
6061 .revalidate_disk= md_revalidate,
6042}; 6062};
6043 6063
6044static int md_thread(void * arg) 6064static int md_thread(void * arg)
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 7e90b8593b2..12215d437fc 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -274,6 +274,8 @@ struct mddev_s
274 atomic_t active; /* general refcount */ 274 atomic_t active; /* general refcount */
275 atomic_t openers; /* number of active opens */ 275 atomic_t openers; /* number of active opens */
276 276
277 int changed; /* True if we might need to
278 * reread partition info */
277 int degraded; /* whether md should consider 279 int degraded; /* whether md should consider
278 * adding a spare 280 * adding a spare
279 */ 281 */