md: 3 bugfixes for 3.5-rc
One of the bugs was introduced in 3.5-rc1. Others have been there for longer. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iQIVAwUAUAeiTznsnt1WYoG5AQLzcRAAqAIBtmGRzTpCTGzfJxF3ciDptQLfDKzx JDwcKsmD3+70bjkKUsHhu22EK/Fgdi2T7XirjlJTnMZFtwfQFbRBNFe+6AneefzI fJvTwEOsvgNBEJvEUtp9hboZBZBZBmujdXYuEf9NbSEoK+bOcxtTh6V+CwcCKAEI ulreMNCBX/e9RRP/ayUsj33TJGvDGEJWmFOoEj/3sZ9soKC3GYFkr5I50FcRhrgh J78mX64Qf1KCsIG2zwN5w/pE9Nnz5mJ4iBElhl3xQT6nDikhe4AZv2Z51s6UMQ9K oQSVgJg9IkAH+Vl/IFzvK/4mU1/xnCydA/Q+CEXxLXor0kFnl9XxpSwHhjQTQ/Ag l5cA+U5RR0wkCS7OGv0mxwY2rfw0wg7I+v9GQu9hg+XyeZTjWC4rU1EiANAWDHiE eCoUTi4MkwAA5vkL+G7B2I9fXD11eigTPFbiHvm5a3SNzqiKklMQgh7SoonnRZ9L iL3qfIBwhpQAbAChqTS92WofYvNKTfE6qTrQUfEomgr4EWtr2teiR36shDnfKRCw vdmL7d+ql9qHbD83NfV7tE08clK4h5MtKDmJtHoOdeeGK1UUI+VmMhQQSHEX3UAW TduJnL4bhaw5Z4QCrpS5IO5R/mTBX1VRrbzjcJl+Te4HrmRl/ccQKachvn1N597L ah3SlO5LBy0= =zpJG -----END PGP SIGNATURE----- Merge tag 'md-3.5-fixes' of git://neil.brown.name/md Pull three md bugfixes from NeilBrown: "One of the bugs was introduced in 3.5-rc1. Others have been there for longer." * tag 'md-3.5-fixes' of git://neil.brown.name/md: md/raid1: close some possible races on write errors during resync md: avoid crash when stopping md array races with closing other open fds. md: fix bug in handling of new_data_offset
This commit is contained in:
commit
3e4b9459fb
2 changed files with 32 additions and 15 deletions
|
@ -2931,6 +2931,7 @@ offset_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|||
* can be sane */
|
||||
return -EBUSY;
|
||||
rdev->data_offset = offset;
|
||||
rdev->new_data_offset = offset;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -3926,8 +3927,8 @@ array_state_show(struct mddev *mddev, char *page)
|
|||
return sprintf(page, "%s\n", array_states[st]);
|
||||
}
|
||||
|
||||
static int do_md_stop(struct mddev * mddev, int ro, int is_open);
|
||||
static int md_set_readonly(struct mddev * mddev, int is_open);
|
||||
static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev);
|
||||
static int md_set_readonly(struct mddev * mddev, struct block_device *bdev);
|
||||
static int do_md_run(struct mddev * mddev);
|
||||
static int restart_array(struct mddev *mddev);
|
||||
|
||||
|
@ -3943,14 +3944,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
|||
/* stopping an active array */
|
||||
if (atomic_read(&mddev->openers) > 0)
|
||||
return -EBUSY;
|
||||
err = do_md_stop(mddev, 0, 0);
|
||||
err = do_md_stop(mddev, 0, NULL);
|
||||
break;
|
||||
case inactive:
|
||||
/* stopping an active array */
|
||||
if (mddev->pers) {
|
||||
if (atomic_read(&mddev->openers) > 0)
|
||||
return -EBUSY;
|
||||
err = do_md_stop(mddev, 2, 0);
|
||||
err = do_md_stop(mddev, 2, NULL);
|
||||
} else
|
||||
err = 0; /* already inactive */
|
||||
break;
|
||||
|
@ -3958,7 +3959,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
|||
break; /* not supported yet */
|
||||
case readonly:
|
||||
if (mddev->pers)
|
||||
err = md_set_readonly(mddev, 0);
|
||||
err = md_set_readonly(mddev, NULL);
|
||||
else {
|
||||
mddev->ro = 1;
|
||||
set_disk_ro(mddev->gendisk, 1);
|
||||
|
@ -3968,7 +3969,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
|||
case read_auto:
|
||||
if (mddev->pers) {
|
||||
if (mddev->ro == 0)
|
||||
err = md_set_readonly(mddev, 0);
|
||||
err = md_set_readonly(mddev, NULL);
|
||||
else if (mddev->ro == 1)
|
||||
err = restart_array(mddev);
|
||||
if (err == 0) {
|
||||
|
@ -5351,15 +5352,17 @@ void md_stop(struct mddev *mddev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(md_stop);
|
||||
|
||||
static int md_set_readonly(struct mddev *mddev, int is_open)
|
||||
static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
|
||||
{
|
||||
int err = 0;
|
||||
mutex_lock(&mddev->open_mutex);
|
||||
if (atomic_read(&mddev->openers) > is_open) {
|
||||
if (atomic_read(&mddev->openers) > !!bdev) {
|
||||
printk("md: %s still in use.\n",mdname(mddev));
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
if (bdev)
|
||||
sync_blockdev(bdev);
|
||||
if (mddev->pers) {
|
||||
__md_stop_writes(mddev);
|
||||
|
||||
|
@ -5381,18 +5384,26 @@ out:
|
|||
* 0 - completely stop and dis-assemble array
|
||||
* 2 - stop but do not disassemble array
|
||||
*/
|
||||
static int do_md_stop(struct mddev * mddev, int mode, int is_open)
|
||||
static int do_md_stop(struct mddev * mddev, int mode,
|
||||
struct block_device *bdev)
|
||||
{
|
||||
struct gendisk *disk = mddev->gendisk;
|
||||
struct md_rdev *rdev;
|
||||
|
||||
mutex_lock(&mddev->open_mutex);
|
||||
if (atomic_read(&mddev->openers) > is_open ||
|
||||
if (atomic_read(&mddev->openers) > !!bdev ||
|
||||
mddev->sysfs_active) {
|
||||
printk("md: %s still in use.\n",mdname(mddev));
|
||||
mutex_unlock(&mddev->open_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
if (bdev)
|
||||
/* It is possible IO was issued on some other
|
||||
* open file which was closed before we took ->open_mutex.
|
||||
* As that was not the last close __blkdev_put will not
|
||||
* have called sync_blockdev, so we must.
|
||||
*/
|
||||
sync_blockdev(bdev);
|
||||
|
||||
if (mddev->pers) {
|
||||
if (mddev->ro)
|
||||
|
@ -5466,7 +5477,7 @@ static void autorun_array(struct mddev *mddev)
|
|||
err = do_md_run(mddev);
|
||||
if (err) {
|
||||
printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
|
||||
do_md_stop(mddev, 0, 0);
|
||||
do_md_stop(mddev, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6481,11 +6492,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
|||
goto done_unlock;
|
||||
|
||||
case STOP_ARRAY:
|
||||
err = do_md_stop(mddev, 0, 1);
|
||||
err = do_md_stop(mddev, 0, bdev);
|
||||
goto done_unlock;
|
||||
|
||||
case STOP_ARRAY_RO:
|
||||
err = md_set_readonly(mddev, 1);
|
||||
err = md_set_readonly(mddev, bdev);
|
||||
goto done_unlock;
|
||||
|
||||
case BLKROSET:
|
||||
|
|
|
@ -1818,8 +1818,14 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
|
|||
|
||||
if (atomic_dec_and_test(&r1_bio->remaining)) {
|
||||
/* if we're here, all write(s) have completed, so clean up */
|
||||
md_done_sync(mddev, r1_bio->sectors, 1);
|
||||
put_buf(r1_bio);
|
||||
int s = r1_bio->sectors;
|
||||
if (test_bit(R1BIO_MadeGood, &r1_bio->state) ||
|
||||
test_bit(R1BIO_WriteError, &r1_bio->state))
|
||||
reschedule_retry(r1_bio);
|
||||
else {
|
||||
put_buf(r1_bio);
|
||||
md_done_sync(mddev, s, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue