From 33e110755a112ea273f96baf045ce2cab253477e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 14 Aug 2017 22:13:45 -0500 Subject: [PATCH] unmap: merge allocation/free code Merge unmap_state allocation/free code. This fixes a tiny possibly leak where handle_unmap_in_writesame did not pthread_mutex_destroy in the error path. Signed-off-by: Mike Christie --- tcmur_cmd_handler.c | 100 ++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/tcmur_cmd_handler.c b/tcmur_cmd_handler.c index 62f3e5fe..e1aff126 100644 --- a/tcmur_cmd_handler.c +++ b/tcmur_cmd_handler.c @@ -176,6 +176,50 @@ struct unmap_descriptor { struct tcmulib_cmd *origcmd; }; +static struct unmap_state *unmap_state_alloc(struct tcmu_device *dev, + struct tcmulib_cmd *cmd, + int *return_err) +{ + uint8_t *sense = cmd->sense_buf; + struct unmap_state *state; + int ret; + + *return_err = 0; + + state = calloc(1, sizeof(*state)); + if (!state) { + tcmu_dev_err(dev, "Failed to calloc memory for unmap_state!\n"); + *return_err = tcmu_set_sense_data(sense, HARDWARE_ERROR, + ASC_INTERNAL_TARGET_FAILURE, + NULL); + return NULL; + } + + ret = pthread_mutex_init(&state->lock, NULL); + if (ret == -1) { + tcmu_dev_err(dev, "Failed to init spin lock in state!\n"); + *return_err = tcmu_set_sense_data(sense, HARDWARE_ERROR, + ASC_INTERNAL_TARGET_FAILURE, + NULL); + goto out_free_state; + } + + state->refcount = 0; + state->error = false; + cmd->cmdstate = state; + return state; + +out_free_state: + free(state); + return NULL; +} + +static void unmap_state_free(struct unmap_state *state) +{ + pthread_mutex_destroy(&state->lock); + free(state); +} + static void handle_unmap_cbk(struct tcmu_device *dev, struct tcmulib_cmd *ucmd, int ret) { @@ -208,8 +252,7 @@ static void handle_unmap_cbk(struct tcmu_device *dev, struct tcmulib_cmd *ucmd, error = state->error; pthread_mutex_unlock(&state->lock); - pthread_mutex_destroy(&state->lock); - free(state); + unmap_state_free(state); aio_command_finish(dev, origcmd, error ? status : ret); } @@ -381,8 +424,7 @@ static int handle_unmap_internal(struct tcmu_device *dev, struct tcmulib_cmd *or * No unmaps have been dispatched, so return the error and free * resources now. */ - pthread_mutex_destroy(&state->lock); - free(state); + unmap_state_free(state); return ret; } @@ -495,35 +537,15 @@ static int handle_unmap(struct tcmu_device *dev, struct tcmulib_cmd *origcmd) goto out_free_par; } - state = calloc(1, sizeof(*state)); - if (!state) { - tcmu_dev_err(dev, "Failed to calloc memory for unmap_state!\n"); - ret = tcmu_set_sense_data(sense, HARDWARE_ERROR, - ASC_INTERNAL_TARGET_FAILURE, - NULL); + state = unmap_state_alloc(dev, origcmd, &ret); + if (!state) goto out_free_par; - } - - ret = pthread_mutex_init(&state->lock, NULL); - if (ret == -1) { - tcmu_dev_err(dev, "Failed to init spin lock in state!\n"); - ret = tcmu_set_sense_data(sense, HARDWARE_ERROR, - ASC_INTERNAL_TARGET_FAILURE, - NULL); - goto out_free_state; - } - - state->refcount = 0; - state->error = false; - origcmd->cmdstate = state; ret = handle_unmap_internal(dev, origcmd, bddl, par); free(par); return ret; -out_free_state: - free(state); out_free_par: free(par); return ret; @@ -668,7 +690,6 @@ static int handle_writesame_check(struct tcmu_device *dev, struct tcmulib_cmd *c static int handle_unmap_in_writesame(struct tcmu_device *dev, struct tcmulib_cmd *cmd) { - uint8_t *sense = cmd->sense_buf; uint8_t *cdb = cmd->cdb; uint64_t lba = tcmu_get_lba(cdb); uint64_t nlbas = tcmu_get_xfer_length(cdb); @@ -678,28 +699,9 @@ static int handle_unmap_in_writesame(struct tcmu_device *dev, tcmu_dev_dbg(dev, "Do UNMAP in WRITE_SAME cmd!\n"); - state = calloc(1, sizeof(*state)); - if (!state) { - tcmu_dev_err(dev, "Failed to calloc memory for unmap_state!\n"); - ret = tcmu_set_sense_data(sense, HARDWARE_ERROR, - ASC_INTERNAL_TARGET_FAILURE, - NULL); - return ret; - } - - ret = pthread_mutex_init(&state->lock, NULL); - if (ret == -1) { - tcmu_dev_err(dev, "Failed to init spin lock in state!\n"); - ret = tcmu_set_sense_data(sense, HARDWARE_ERROR, - ASC_INTERNAL_TARGET_FAILURE, - NULL); - free(state); + state = unmap_state_alloc(dev, cmd, &ret); + if (!state) return ret; - } - - state->refcount = 0; - state->error = false; - cmd->cmdstate = state; pthread_mutex_lock(&state->lock); ret = align_and_split_unmap(dev, cmd, lba, nlbas); @@ -711,7 +713,7 @@ static int handle_unmap_in_writesame(struct tcmu_device *dev, /* Or will let the cbk to do the release */ if (!refcount) - free(state); + unmap_state_free(state); return ret; }