mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 17:51:43 +00:00
MD: hold mddev lock to change bitmap location
Changing the location changes a lot of things. Holding the lock to avoid race. This makes the .quiesce called with mddev lock hold too. Acked-by: NeilBrown <neilb@suse.com> Signed-off-by: Shaohua Li <shli@fb.com>
This commit is contained in:
parent
ff00d3b4e5
commit
d9dd26b20c
@ -2183,19 +2183,29 @@ location_show(struct mddev *mddev, char *page)
|
|||||||
static ssize_t
|
static ssize_t
|
||||||
location_store(struct mddev *mddev, const char *buf, size_t len)
|
location_store(struct mddev *mddev, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = mddev_lock(mddev);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
if (!mddev->pers->quiesce)
|
if (!mddev->pers->quiesce) {
|
||||||
return -EBUSY;
|
rv = -EBUSY;
|
||||||
if (mddev->recovery || mddev->sync_thread)
|
goto out;
|
||||||
return -EBUSY;
|
}
|
||||||
|
if (mddev->recovery || mddev->sync_thread) {
|
||||||
|
rv = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mddev->bitmap || mddev->bitmap_info.file ||
|
if (mddev->bitmap || mddev->bitmap_info.file ||
|
||||||
mddev->bitmap_info.offset) {
|
mddev->bitmap_info.offset) {
|
||||||
/* bitmap already configured. Only option is to clear it */
|
/* bitmap already configured. Only option is to clear it */
|
||||||
if (strncmp(buf, "none", 4) != 0)
|
if (strncmp(buf, "none", 4) != 0) {
|
||||||
return -EBUSY;
|
rv = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
mddev->pers->quiesce(mddev, 1);
|
mddev->pers->quiesce(mddev, 1);
|
||||||
bitmap_destroy(mddev);
|
bitmap_destroy(mddev);
|
||||||
@ -2214,21 +2224,25 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
/* nothing to be done */;
|
/* nothing to be done */;
|
||||||
else if (strncmp(buf, "file:", 5) == 0) {
|
else if (strncmp(buf, "file:", 5) == 0) {
|
||||||
/* Not supported yet */
|
/* Not supported yet */
|
||||||
return -EINVAL;
|
rv = -EINVAL;
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
int rv;
|
|
||||||
if (buf[0] == '+')
|
if (buf[0] == '+')
|
||||||
rv = kstrtoll(buf+1, 10, &offset);
|
rv = kstrtoll(buf+1, 10, &offset);
|
||||||
else
|
else
|
||||||
rv = kstrtoll(buf, 10, &offset);
|
rv = kstrtoll(buf, 10, &offset);
|
||||||
if (rv)
|
if (rv)
|
||||||
return rv;
|
goto out;
|
||||||
if (offset == 0)
|
if (offset == 0) {
|
||||||
return -EINVAL;
|
rv = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (mddev->bitmap_info.external == 0 &&
|
if (mddev->bitmap_info.external == 0 &&
|
||||||
mddev->major_version == 0 &&
|
mddev->major_version == 0 &&
|
||||||
offset != mddev->bitmap_info.default_offset)
|
offset != mddev->bitmap_info.default_offset) {
|
||||||
return -EINVAL;
|
rv = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
mddev->bitmap_info.offset = offset;
|
mddev->bitmap_info.offset = offset;
|
||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
struct bitmap *bitmap;
|
struct bitmap *bitmap;
|
||||||
@ -2245,7 +2259,7 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
mddev->pers->quiesce(mddev, 0);
|
mddev->pers->quiesce(mddev, 0);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
bitmap_destroy(mddev);
|
bitmap_destroy(mddev);
|
||||||
return rv;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2257,6 +2271,11 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
||||||
md_wakeup_thread(mddev->thread);
|
md_wakeup_thread(mddev->thread);
|
||||||
}
|
}
|
||||||
|
rv = 0;
|
||||||
|
out:
|
||||||
|
mddev_unlock(mddev);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user