Commit 092b5648 authored by John Pittman's avatar John Pittman Committed by Mike Snitzer

dm zoned: target: use refcount_t for dm zoned reference counters

The API surrounding refcount_t should be used in place of atomic_t
when variables are being used as reference counters.  This API can
prevent issues such as counter overflows and use-after-free
conditions.  Within the dm zoned target stack, the atomic_t API is
used for bioctx->ref and cw->refcount.  Change these to use
refcount_t, avoiding the issues mentioned.
Signed-off-by: default avatarJohn Pittman <jpittman@redhat.com>
Reviewed-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
Tested-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 22d4c291
...@@ -19,7 +19,7 @@ struct dmz_bioctx { ...@@ -19,7 +19,7 @@ struct dmz_bioctx {
struct dmz_target *target; struct dmz_target *target;
struct dm_zone *zone; struct dm_zone *zone;
struct bio *bio; struct bio *bio;
atomic_t ref; refcount_t ref;
blk_status_t status; blk_status_t status;
}; };
...@@ -28,7 +28,7 @@ struct dmz_bioctx { ...@@ -28,7 +28,7 @@ struct dmz_bioctx {
*/ */
struct dm_chunk_work { struct dm_chunk_work {
struct work_struct work; struct work_struct work;
atomic_t refcount; refcount_t refcount;
struct dmz_target *target; struct dmz_target *target;
unsigned int chunk; unsigned int chunk;
struct bio_list bio_list; struct bio_list bio_list;
...@@ -115,7 +115,7 @@ static int dmz_submit_read_bio(struct dmz_target *dmz, struct dm_zone *zone, ...@@ -115,7 +115,7 @@ static int dmz_submit_read_bio(struct dmz_target *dmz, struct dm_zone *zone,
if (nr_blocks == dmz_bio_blocks(bio)) { if (nr_blocks == dmz_bio_blocks(bio)) {
/* Setup and submit the BIO */ /* Setup and submit the BIO */
bio->bi_iter.bi_sector = sector; bio->bi_iter.bi_sector = sector;
atomic_inc(&bioctx->ref); refcount_inc(&bioctx->ref);
generic_make_request(bio); generic_make_request(bio);
return 0; return 0;
} }
...@@ -134,7 +134,7 @@ static int dmz_submit_read_bio(struct dmz_target *dmz, struct dm_zone *zone, ...@@ -134,7 +134,7 @@ static int dmz_submit_read_bio(struct dmz_target *dmz, struct dm_zone *zone,
bio_advance(bio, clone->bi_iter.bi_size); bio_advance(bio, clone->bi_iter.bi_size);
/* Submit the clone */ /* Submit the clone */
atomic_inc(&bioctx->ref); refcount_inc(&bioctx->ref);
generic_make_request(clone); generic_make_request(clone);
return 0; return 0;
...@@ -240,7 +240,7 @@ static void dmz_submit_write_bio(struct dmz_target *dmz, struct dm_zone *zone, ...@@ -240,7 +240,7 @@ static void dmz_submit_write_bio(struct dmz_target *dmz, struct dm_zone *zone,
/* Setup and submit the BIO */ /* Setup and submit the BIO */
bio_set_dev(bio, dmz->dev->bdev); bio_set_dev(bio, dmz->dev->bdev);
bio->bi_iter.bi_sector = dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block); bio->bi_iter.bi_sector = dmz_start_sect(dmz->metadata, zone) + dmz_blk2sect(chunk_block);
atomic_inc(&bioctx->ref); refcount_inc(&bioctx->ref);
generic_make_request(bio); generic_make_request(bio);
if (dmz_is_seq(zone)) if (dmz_is_seq(zone))
...@@ -456,7 +456,7 @@ static void dmz_handle_bio(struct dmz_target *dmz, struct dm_chunk_work *cw, ...@@ -456,7 +456,7 @@ static void dmz_handle_bio(struct dmz_target *dmz, struct dm_chunk_work *cw,
*/ */
static inline void dmz_get_chunk_work(struct dm_chunk_work *cw) static inline void dmz_get_chunk_work(struct dm_chunk_work *cw)
{ {
atomic_inc(&cw->refcount); refcount_inc(&cw->refcount);
} }
/* /*
...@@ -465,7 +465,7 @@ static inline void dmz_get_chunk_work(struct dm_chunk_work *cw) ...@@ -465,7 +465,7 @@ static inline void dmz_get_chunk_work(struct dm_chunk_work *cw)
*/ */
static void dmz_put_chunk_work(struct dm_chunk_work *cw) static void dmz_put_chunk_work(struct dm_chunk_work *cw)
{ {
if (atomic_dec_and_test(&cw->refcount)) { if (refcount_dec_and_test(&cw->refcount)) {
WARN_ON(!bio_list_empty(&cw->bio_list)); WARN_ON(!bio_list_empty(&cw->bio_list));
radix_tree_delete(&cw->target->chunk_rxtree, cw->chunk); radix_tree_delete(&cw->target->chunk_rxtree, cw->chunk);
kfree(cw); kfree(cw);
...@@ -546,7 +546,7 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio) ...@@ -546,7 +546,7 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
goto out; goto out;
INIT_WORK(&cw->work, dmz_chunk_work); INIT_WORK(&cw->work, dmz_chunk_work);
atomic_set(&cw->refcount, 0); refcount_set(&cw->refcount, 0);
cw->target = dmz; cw->target = dmz;
cw->chunk = chunk; cw->chunk = chunk;
bio_list_init(&cw->bio_list); bio_list_init(&cw->bio_list);
...@@ -599,7 +599,7 @@ static int dmz_map(struct dm_target *ti, struct bio *bio) ...@@ -599,7 +599,7 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
bioctx->target = dmz; bioctx->target = dmz;
bioctx->zone = NULL; bioctx->zone = NULL;
bioctx->bio = bio; bioctx->bio = bio;
atomic_set(&bioctx->ref, 1); refcount_set(&bioctx->ref, 1);
bioctx->status = BLK_STS_OK; bioctx->status = BLK_STS_OK;
/* Set the BIO pending in the flush list */ /* Set the BIO pending in the flush list */
...@@ -633,7 +633,7 @@ static int dmz_end_io(struct dm_target *ti, struct bio *bio, blk_status_t *error ...@@ -633,7 +633,7 @@ static int dmz_end_io(struct dm_target *ti, struct bio *bio, blk_status_t *error
if (bioctx->status == BLK_STS_OK && *error) if (bioctx->status == BLK_STS_OK && *error)
bioctx->status = *error; bioctx->status = *error;
if (!atomic_dec_and_test(&bioctx->ref)) if (!refcount_dec_and_test(&bioctx->ref))
return DM_ENDIO_INCOMPLETE; return DM_ENDIO_INCOMPLETE;
/* Done */ /* Done */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment