Commit 66cac806 authored by Matthew Sakai's avatar Matthew Sakai Committed by Mikulas Patocka

dm vdo: handle unaligned discards correctly

Reset the data_vio properly for each discard block, and delay
acknowledgement and cleanup until all discard blocks are complete.
Signed-off-by: default avatarMatthew Sakai <msakai@redhat.com>
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
parent 9bcd9239
...@@ -501,6 +501,7 @@ static void launch_data_vio(struct data_vio *data_vio, logical_block_number_t lb ...@@ -501,6 +501,7 @@ static void launch_data_vio(struct data_vio *data_vio, logical_block_number_t lb
memset(&data_vio->record_name, 0, sizeof(data_vio->record_name)); memset(&data_vio->record_name, 0, sizeof(data_vio->record_name));
memset(&data_vio->duplicate, 0, sizeof(data_vio->duplicate)); memset(&data_vio->duplicate, 0, sizeof(data_vio->duplicate));
vdo_reset_completion(&data_vio->decrement_completion);
vdo_reset_completion(completion); vdo_reset_completion(completion);
completion->error_handler = handle_data_vio_error; completion->error_handler = handle_data_vio_error;
set_data_vio_logical_callback(data_vio, attempt_logical_block_lock); set_data_vio_logical_callback(data_vio, attempt_logical_block_lock);
...@@ -1273,12 +1274,14 @@ static void clean_hash_lock(struct vdo_completion *completion) ...@@ -1273,12 +1274,14 @@ static void clean_hash_lock(struct vdo_completion *completion)
static void finish_cleanup(struct data_vio *data_vio) static void finish_cleanup(struct data_vio *data_vio)
{ {
struct vdo_completion *completion = &data_vio->vio.completion; struct vdo_completion *completion = &data_vio->vio.completion;
u32 discard_size = min_t(u32, data_vio->remaining_discard,
VDO_BLOCK_SIZE - data_vio->offset);
VDO_ASSERT_LOG_ONLY(data_vio->allocation.lock == NULL, VDO_ASSERT_LOG_ONLY(data_vio->allocation.lock == NULL,
"complete data_vio has no allocation lock"); "complete data_vio has no allocation lock");
VDO_ASSERT_LOG_ONLY(data_vio->hash_lock == NULL, VDO_ASSERT_LOG_ONLY(data_vio->hash_lock == NULL,
"complete data_vio has no hash lock"); "complete data_vio has no hash lock");
if ((data_vio->remaining_discard <= VDO_BLOCK_SIZE) || if ((data_vio->remaining_discard <= discard_size) ||
(completion->result != VDO_SUCCESS)) { (completion->result != VDO_SUCCESS)) {
struct data_vio_pool *pool = completion->vdo->data_vio_pool; struct data_vio_pool *pool = completion->vdo->data_vio_pool;
...@@ -1287,12 +1290,12 @@ static void finish_cleanup(struct data_vio *data_vio) ...@@ -1287,12 +1290,12 @@ static void finish_cleanup(struct data_vio *data_vio)
return; return;
} }
data_vio->remaining_discard -= min_t(u32, data_vio->remaining_discard, data_vio->remaining_discard -= discard_size;
VDO_BLOCK_SIZE - data_vio->offset);
data_vio->is_partial = (data_vio->remaining_discard < VDO_BLOCK_SIZE); data_vio->is_partial = (data_vio->remaining_discard < VDO_BLOCK_SIZE);
data_vio->read = data_vio->is_partial; data_vio->read = data_vio->is_partial;
data_vio->offset = 0; data_vio->offset = 0;
completion->requeue = true; completion->requeue = true;
data_vio->first_reference_operation_complete = false;
launch_data_vio(data_vio, data_vio->logical.lbn + 1); launch_data_vio(data_vio, data_vio->logical.lbn + 1);
} }
...@@ -1965,7 +1968,8 @@ static void allocate_block(struct vdo_completion *completion) ...@@ -1965,7 +1968,8 @@ static void allocate_block(struct vdo_completion *completion)
.state = VDO_MAPPING_STATE_UNCOMPRESSED, .state = VDO_MAPPING_STATE_UNCOMPRESSED,
}; };
if (data_vio->fua) { if (data_vio->fua ||
data_vio->remaining_discard > (u32) (VDO_BLOCK_SIZE - data_vio->offset)) {
prepare_for_dedupe(data_vio); prepare_for_dedupe(data_vio);
return; return;
} }
...@@ -2042,7 +2046,6 @@ void continue_data_vio_with_block_map_slot(struct vdo_completion *completion) ...@@ -2042,7 +2046,6 @@ void continue_data_vio_with_block_map_slot(struct vdo_completion *completion)
return; return;
} }
/* /*
* We don't need to write any data, so skip allocation and just update the block map and * We don't need to write any data, so skip allocation and just update the block map and
* reference counts (via the journal). * reference counts (via the journal).
...@@ -2051,7 +2054,7 @@ void continue_data_vio_with_block_map_slot(struct vdo_completion *completion) ...@@ -2051,7 +2054,7 @@ void continue_data_vio_with_block_map_slot(struct vdo_completion *completion)
if (data_vio->is_zero) if (data_vio->is_zero)
data_vio->new_mapped.state = VDO_MAPPING_STATE_UNCOMPRESSED; data_vio->new_mapped.state = VDO_MAPPING_STATE_UNCOMPRESSED;
if (data_vio->remaining_discard > VDO_BLOCK_SIZE) { if (data_vio->remaining_discard > (u32) (VDO_BLOCK_SIZE - data_vio->offset)) {
/* This is not the final block of a discard so we can't acknowledge it yet. */ /* This is not the final block of a discard so we can't acknowledge it yet. */
update_metadata_for_data_vio_write(data_vio, NULL); update_metadata_for_data_vio_write(data_vio, NULL);
return; return;
......
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