Skip to content

Commit 23da422

Browse files
committed
md: use mddev->lock to protect updates to resync_{min,max}.
There are interdependencies between these two sysfs attributes and whether a resync is currently running. Rather than depending on reconfig_mutex to ensure no races when testing these interdependencies are met, use the spinlock. This will allow the mutex to be remove from protecting this code in a subsequent patch. Signed-off-by: NeilBrown <[email protected]>
1 parent 1b30e66 commit 23da422

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

drivers/md/md.c

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4269,22 +4269,36 @@ static ssize_t
42694269
min_sync_store(struct mddev *mddev, const char *buf, size_t len)
42704270
{
42714271
unsigned long long min;
4272+
int err;
4273+
int chunk;
4274+
42724275
if (kstrtoull(buf, 10, &min))
42734276
return -EINVAL;
4277+
4278+
spin_lock(&mddev->lock);
4279+
err = -EINVAL;
42744280
if (min > mddev->resync_max)
4275-
return -EINVAL;
4281+
goto out_unlock;
4282+
4283+
err = -EBUSY;
42764284
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
4277-
return -EBUSY;
4285+
goto out_unlock;
42784286

42794287
/* Must be a multiple of chunk_size */
4280-
if (mddev->chunk_sectors) {
4288+
chunk = mddev->chunk_sectors;
4289+
if (chunk) {
42814290
sector_t temp = min;
4282-
if (sector_div(temp, mddev->chunk_sectors))
4283-
return -EINVAL;
4291+
4292+
err = -EINVAL;
4293+
if (sector_div(temp, chunk))
4294+
goto out_unlock;
42844295
}
42854296
mddev->resync_min = min;
4297+
err = 0;
42864298

4287-
return len;
4299+
out_unlock:
4300+
spin_unlock(&mddev->lock);
4301+
return err ?: len;
42884302
}
42894303

42904304
static struct md_sysfs_entry md_min_sync =
@@ -4302,29 +4316,42 @@ max_sync_show(struct mddev *mddev, char *page)
43024316
static ssize_t
43034317
max_sync_store(struct mddev *mddev, const char *buf, size_t len)
43044318
{
4319+
int err;
4320+
spin_lock(&mddev->lock);
43054321
if (strncmp(buf, "max", 3) == 0)
43064322
mddev->resync_max = MaxSector;
43074323
else {
43084324
unsigned long long max;
4325+
int chunk;
4326+
4327+
err = -EINVAL;
43094328
if (kstrtoull(buf, 10, &max))
4310-
return -EINVAL;
4329+
goto out_unlock;
43114330
if (max < mddev->resync_min)
4312-
return -EINVAL;
4331+
goto out_unlock;
4332+
4333+
err = -EBUSY;
43134334
if (max < mddev->resync_max &&
43144335
mddev->ro == 0 &&
43154336
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
4316-
return -EBUSY;
4337+
goto out_unlock;
43174338

43184339
/* Must be a multiple of chunk_size */
4319-
if (mddev->chunk_sectors) {
4340+
chunk = mddev->chunk_sectors;
4341+
if (chunk) {
43204342
sector_t temp = max;
4321-
if (sector_div(temp, mddev->chunk_sectors))
4322-
return -EINVAL;
4343+
4344+
err = -EINVAL;
4345+
if (sector_div(temp, chunk))
4346+
goto out_unlock;
43234347
}
43244348
mddev->resync_max = max;
43254349
}
43264350
wake_up(&mddev->recovery_wait);
4327-
return len;
4351+
err = 0;
4352+
out_unlock:
4353+
spin_unlock(&mddev->lock);
4354+
return err ?: len;
43284355
}
43294356

43304357
static struct md_sysfs_entry md_max_sync =
@@ -7585,6 +7612,7 @@ void md_do_sync(struct md_thread *thread)
75857612
skip:
75867613
set_bit(MD_CHANGE_DEVS, &mddev->flags);
75877614

7615+
spin_lock(&mddev->lock);
75887616
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
75897617
/* We completed so min/max setting can be forgotten if used. */
75907618
if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
@@ -7593,6 +7621,8 @@ void md_do_sync(struct md_thread *thread)
75937621
} else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
75947622
mddev->resync_min = mddev->curr_resync_completed;
75957623
mddev->curr_resync = 0;
7624+
spin_unlock(&mddev->lock);
7625+
75967626
wake_up(&resync_wait);
75977627
set_bit(MD_RECOVERY_DONE, &mddev->recovery);
75987628
md_wakeup_thread(mddev->thread);
@@ -7793,7 +7823,9 @@ void md_check_recovery(struct mddev *mddev)
77937823
* any transients in the value of "sync_action".
77947824
*/
77957825
mddev->curr_resync_completed = 0;
7826+
spin_lock(&mddev->lock);
77967827
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
7828+
spin_unlock(&mddev->lock);
77977829
/* Clear some bits that don't mean anything, but
77987830
* might be left set
77997831
*/

drivers/md/md.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ struct mddev {
394394
* pers (also protected by reconfig_mutex and pending IO).
395395
* clearing ->bitmap
396396
* clearing ->bitmap_info.file
397+
* changing ->resync_{min,max}
398+
* setting MD_RECOVERY_RUNNING (which interacts with resync_{min,max})
397399
*/
398400
spinlock_t lock;
399401
wait_queue_head_t sb_wait; /* for waiting on superblock updates */

0 commit comments

Comments
 (0)