mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
Device-mapper fixes for 3.3.
Eight small device-mapper bug fixes. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPV8+yAAoJEK2W1qbAHj1nZVAQAI8TNKwnBpKSW3Y9XFHqWjEx 71wbjDkKkdEUWy52CAkSoRnQdX+ABxxGr5R60n/vJvHi4yDse56LddPzKAo4zD3c DVh6RB8CTIY+2IXGzjkDtelmKogKyAMlhmRoj0oLb5/29n6lnn6A0vkq4OimuFJO IIdgJxpRLqmV8NcSVC7qCEoErxzTNz9w7HaBBs73VhF8AcN/6Qi/z55zDOzT/Iz8 iMHGmOHJBb8OxMN8BWWFdDh2YUz3isbM1xbBerYxy3P3WCHpxGBt7yRiHm3Yd5il USnJN3Kz0w6Orhgu1eeAuJz1A9cdSP62AQDdM91+v3nHz3mtTdAljmJZgzgzqs5u SRO24J6FD201DNh/RitDC1UzNOBqeapfqprT/gH+qM4Pl6X+vuXiSe5cxx+lTOhJ GErI1XYpTfzymdpQfqj6VnDMevRf0Hz+mSjEiUh8qjUv9bXHkmTrzjxCvAIEM+4h fJSQ0Fp77eV7Du9HkkFbEXVTYOe8VO+6E9AaplBAjZxHS6w+5tMFkHTM28JPxS98 rYAks9QKbaZaEYZiNv7htux8n2OS9IeGHdLQpsooLh6lD4GxvBJ7NC8wUkfUzn27 zEr2vqAYuA3PiccSHnT7tlN0PN1JlOjDCf+cdQkKfJj5w0E/qS2Fiv2UFIRLRPEa blSbf7wU0mpvorQJn/bd =lLJB -----END PGP SIGNATURE----- Merge tag 'dm-3.3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm Pull device-mapper fixes for 3.3 from Alasdair Kergon Eight small device-mapper bug fixes. * tag 'dm-3.3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm: dm raid: fix flush support dm raid: set MD_CHANGE_DEVS when rebuilding dm thin metadata: decrement counter after removing mapped block dm thin metadata: unlock superblock in init_pmd error path dm thin metadata: remove incorrect close_device on creation error paths dm flakey: fix crash on read when corrupt_bio_byte not set dm io: fix discard support dm ioctl: do not leak argv if target message only contains whitespace
This commit is contained in:
commit
5d0edf2915
@ -323,7 +323,7 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
|
||||
* Corrupt successful READs while in down state.
|
||||
* If flags were specified, only corrupt those that match.
|
||||
*/
|
||||
if (!error && bio_submitted_while_down &&
|
||||
if (fc->corrupt_bio_byte && !error && bio_submitted_while_down &&
|
||||
(bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
|
||||
all_corrupt_bio_flags_match(bio, fc))
|
||||
corrupt_bio_data(bio, fc);
|
||||
|
@ -296,6 +296,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
|
||||
unsigned offset;
|
||||
unsigned num_bvecs;
|
||||
sector_t remaining = where->count;
|
||||
struct request_queue *q = bdev_get_queue(where->bdev);
|
||||
sector_t discard_sectors;
|
||||
|
||||
/*
|
||||
* where->count may be zero if rw holds a flush and we need to
|
||||
@ -305,9 +307,12 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
|
||||
/*
|
||||
* Allocate a suitably sized-bio.
|
||||
*/
|
||||
num_bvecs = dm_sector_div_up(remaining,
|
||||
(PAGE_SIZE >> SECTOR_SHIFT));
|
||||
num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs);
|
||||
if (rw & REQ_DISCARD)
|
||||
num_bvecs = 1;
|
||||
else
|
||||
num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev),
|
||||
dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT)));
|
||||
|
||||
bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
|
||||
bio->bi_sector = where->sector + (where->count - remaining);
|
||||
bio->bi_bdev = where->bdev;
|
||||
@ -315,10 +320,14 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
|
||||
bio->bi_destructor = dm_bio_destructor;
|
||||
store_io_and_region_in_bio(bio, io, region);
|
||||
|
||||
/*
|
||||
* Try and add as many pages as possible.
|
||||
*/
|
||||
while (remaining) {
|
||||
if (rw & REQ_DISCARD) {
|
||||
discard_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
|
||||
bio->bi_size = discard_sectors << SECTOR_SHIFT;
|
||||
remaining -= discard_sectors;
|
||||
} else while (remaining) {
|
||||
/*
|
||||
* Try and add as many pages as possible.
|
||||
*/
|
||||
dp->get_page(dp, &page, &len, &offset);
|
||||
len = min(len, to_bytes(remaining));
|
||||
if (!bio_add_page(bio, page, len, offset))
|
||||
|
@ -1437,7 +1437,7 @@ static int target_message(struct dm_ioctl *param, size_t param_size)
|
||||
|
||||
if (!argc) {
|
||||
DMWARN("Empty message received.");
|
||||
goto out;
|
||||
goto out_argv;
|
||||
}
|
||||
|
||||
table = dm_get_live_table(md);
|
||||
|
@ -668,7 +668,14 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
|
||||
return ret;
|
||||
|
||||
sb = page_address(rdev->sb_page);
|
||||
if (sb->magic != cpu_to_le32(DM_RAID_MAGIC)) {
|
||||
|
||||
/*
|
||||
* Two cases that we want to write new superblocks and rebuild:
|
||||
* 1) New device (no matching magic number)
|
||||
* 2) Device specified for rebuild (!In_sync w/ offset == 0)
|
||||
*/
|
||||
if ((sb->magic != cpu_to_le32(DM_RAID_MAGIC)) ||
|
||||
(!test_bit(In_sync, &rdev->flags) && !rdev->recovery_offset)) {
|
||||
super_sync(rdev->mddev, rdev);
|
||||
|
||||
set_bit(FirstUse, &rdev->flags);
|
||||
@ -745,11 +752,8 @@ static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev)
|
||||
*/
|
||||
rdev_for_each(r, t, mddev) {
|
||||
if (!test_bit(In_sync, &r->flags)) {
|
||||
if (!test_bit(FirstUse, &r->flags))
|
||||
DMERR("Superblock area of "
|
||||
"rebuild device %d should have been "
|
||||
"cleared.", r->raid_disk);
|
||||
set_bit(FirstUse, &r->flags);
|
||||
DMINFO("Device %d specified for rebuild: "
|
||||
"Clearing superblock", r->raid_disk);
|
||||
rebuilds++;
|
||||
} else if (test_bit(FirstUse, &r->flags))
|
||||
new_devs++;
|
||||
@ -971,6 +975,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
||||
|
||||
INIT_WORK(&rs->md.event_work, do_table_event);
|
||||
ti->private = rs;
|
||||
ti->num_flush_requests = 1;
|
||||
|
||||
mutex_lock(&rs->md.reconfig_mutex);
|
||||
ret = md_run(&rs->md);
|
||||
|
@ -385,6 +385,7 @@ static int init_pmd(struct dm_pool_metadata *pmd,
|
||||
data_sm = dm_sm_disk_create(tm, nr_blocks);
|
||||
if (IS_ERR(data_sm)) {
|
||||
DMERR("sm_disk_create failed");
|
||||
dm_tm_unlock(tm, sblock);
|
||||
r = PTR_ERR(data_sm);
|
||||
goto bad;
|
||||
}
|
||||
@ -789,6 +790,11 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* __open_device: Returns @td corresponding to device with id @dev,
|
||||
* creating it if @create is set and incrementing @td->open_count.
|
||||
* On failure, @td is undefined.
|
||||
*/
|
||||
static int __open_device(struct dm_pool_metadata *pmd,
|
||||
dm_thin_id dev, int create,
|
||||
struct dm_thin_device **td)
|
||||
@ -799,10 +805,16 @@ static int __open_device(struct dm_pool_metadata *pmd,
|
||||
struct disk_device_details details_le;
|
||||
|
||||
/*
|
||||
* Check the device isn't already open.
|
||||
* If the device is already open, return it.
|
||||
*/
|
||||
list_for_each_entry(td2, &pmd->thin_devices, list)
|
||||
if (td2->id == dev) {
|
||||
/*
|
||||
* May not create an already-open device.
|
||||
*/
|
||||
if (create)
|
||||
return -EEXIST;
|
||||
|
||||
td2->open_count++;
|
||||
*td = td2;
|
||||
return 0;
|
||||
@ -817,6 +829,9 @@ static int __open_device(struct dm_pool_metadata *pmd,
|
||||
if (r != -ENODATA || !create)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* Create new device.
|
||||
*/
|
||||
changed = 1;
|
||||
details_le.mapped_blocks = 0;
|
||||
details_le.transaction_id = cpu_to_le64(pmd->trans_id);
|
||||
@ -882,12 +897,10 @@ static int __create_thin(struct dm_pool_metadata *pmd,
|
||||
|
||||
r = __open_device(pmd, dev, 1, &td);
|
||||
if (r) {
|
||||
__close_device(td);
|
||||
dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
|
||||
dm_btree_del(&pmd->bl_info, dev_root);
|
||||
return r;
|
||||
}
|
||||
td->changed = 1;
|
||||
__close_device(td);
|
||||
|
||||
return r;
|
||||
@ -967,14 +980,14 @@ static int __create_snap(struct dm_pool_metadata *pmd,
|
||||
goto bad;
|
||||
|
||||
r = __set_snapshot_details(pmd, td, origin, pmd->time);
|
||||
__close_device(td);
|
||||
|
||||
if (r)
|
||||
goto bad;
|
||||
|
||||
__close_device(td);
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
__close_device(td);
|
||||
dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
|
||||
dm_btree_remove(&pmd->details_info, pmd->details_root,
|
||||
&key, &pmd->details_root);
|
||||
@ -1211,6 +1224,8 @@ static int __remove(struct dm_thin_device *td, dm_block_t block)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
td->mapped_blocks--;
|
||||
td->changed = 1;
|
||||
pmd->need_commit = 1;
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user