[PATCH] nvme-cli: fix leaks in subcommands

Minwoo Im minwoo.im.dev at gmail.com
Fri Jan 26 07:36:01 PST 2018


Fix leaks(a single memory leak, file descriptors leaks) in subcommands
by adding explicit close for opened things.

Signed-off-by: Minwoo Im <minwoo.im.dev at gmail.com>
---
 nvme.c | 474 +++++++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 345 insertions(+), 129 deletions(-)

diff --git a/nvme.c b/nvme.c
index aa2b8ec..8eda8cc 100644
--- a/nvme.c
+++ b/nvme.c
@@ -201,8 +201,10 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 
@@ -220,6 +222,10 @@ static int get_smart_log(int argc, char **argv, struct command *cmd, struct plug
 					nvme_status_to_string(err), err);
 	else
 		perror("smart log");
+
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -256,14 +262,15 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
 
 	if (!cfg.file_name) {
 		fprintf(stderr, "Please provide an output file!\n");
-		close(fd);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	output = open(cfg.file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 	if (output < 0) {
 		fprintf(stderr, "Failed to open output file!\n");
-		return output;
+		err = output;
+		goto close_fd;
 	}
 
 	cfg.host_gen = !!cfg.host_gen;
@@ -277,18 +284,17 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
 			nvme_status_to_string(err), err);
 		fprintf(stderr, "Failed to aquire telemetry header %d!\n", err);
 		free(hdr);
-		goto close_out;
+		goto close_output;
 	}
 
 	err = write(output, (void *) hdr, 4096);
 	if (err != 4096) {
 		fprintf(stderr, "Failed to flush all data to file!");
-		goto close_out;
+		goto free_hdr;
 	}
 
 	num_blocks = max(hdr->dalb1, max(hdr->dalb2, hdr->dalb3));
 
-	free(hdr);
 	full_size = num_blocks * 512;
 	/* Round to page boundary */
 	full_size += (4096 - (full_size % 4096));
@@ -301,7 +307,7 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
 		fprintf(stderr, "Failed to allocate %zu bytes for log\n",
 			full_size);
 		err = ENOMEM;
-		goto close_out;
+		goto free_hdr;
 	}
 
 	while (full_size) {
@@ -310,22 +316,25 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
 			fprintf(stderr, "Failed to aquire full telemetry log!\n");
 			fprintf(stderr, "NVMe Status:%s(%x)\n",
 				nvme_status_to_string(err), err);
-			goto out;
+			break;
 		}
 
 		err = write(output, (void *) page_log, 4096);
 		if (err != 4096) {
 			fprintf(stderr, "Failed to flush all data to file!");
-			goto out;
+			break;
 		}
 		full_size -= 4096;
 		offset += 4096;
 	}
- out:
+
 	free(page_log);
- close_out:
-	close(fd);
+ free_hdr:
+	free(hdr);
+ close_output:
 	close(output);
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -362,8 +371,10 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 
@@ -384,6 +395,9 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl
 				nvme_status_to_string(err), err);
 	else
 		perror("effects log page");
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -420,14 +434,17 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 
 	if (!cfg.log_entries) {
 		fprintf(stderr, "non-zero log-entries is required param\n");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_identify_ctrl(fd, &ctrl);
@@ -443,7 +460,8 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
 		err_log = calloc(cfg.log_entries, sizeof(struct nvme_error_log_page));
 		if (!err_log) {
 			fprintf(stderr, "could not alloc buffer for error log\n");
-			return ENOMEM;
+			err = ENOMEM;
+			goto close_fd;
 		}
 
 		err = nvme_error_log(fd, cfg.log_entries, err_log);
@@ -462,6 +480,9 @@ static int get_error_log(int argc, char **argv, struct command *cmd, struct plug
 			perror("error log");
 		free(err_log);
 	}
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -493,8 +514,10 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 
@@ -512,6 +535,9 @@ static int get_fw_log(int argc, char **argv, struct command *cmd, struct plugin
 				nvme_status_to_string(err), err);
 	else
 		perror("fw log");
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -569,14 +595,15 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl
 
 	if (!cfg.log_len) {
 		fprintf(stderr, "non-zero log-len is required param\n");
-		return EINVAL;
+		err = EINVAL;
 	} else {
 		unsigned char *log;
 
 		log = malloc(cfg.log_len);
 		if (!log) {
 			fprintf(stderr, "could not alloc buffer for log\n");
-			return EINVAL;
+			err = EINVAL;
+			goto close_fd;
 		}
 
 		err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id,
@@ -596,8 +623,11 @@ static int get_log(int argc, char **argv, struct command *cmd, struct plugin *pl
 		else
 			perror("log page");
 		free(log);
-		return err;
 	}
+
+ close_fd:
+	close(fd);
+	return err;
 }
 
 static int sanitize_log(int argc, char **argv, struct command *command, struct plugin *plugin)
@@ -633,8 +663,10 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		ret = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 
@@ -655,6 +687,9 @@ static int sanitize_log(int argc, char **argv, struct command *command, struct p
 	else
 		perror("sanitize status log");
 
+ close_fd:
+	close(fd);
+
 	return ret;
 }
 
@@ -706,6 +741,8 @@ static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *
 
 	free(cntlist);
 
+	close(fd);
+
 	return err;
 }
 
@@ -748,6 +785,9 @@ static int list_ns(int argc, char **argv, struct command *cmd, struct plugin *pl
 			nvme_status_to_string(err), err, cfg.namespace_id);
 	else
 		perror("id namespace list");
+
+	close(fd);
+
 	return err;
 }
 
@@ -782,7 +822,8 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *
 	if (!cfg.namespace_id) {
 		fprintf(stderr, "%s: namespace-id parameter required\n",
 						cmd->name);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_ns_delete(fd, cfg.namespace_id);
@@ -794,6 +835,10 @@ static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *
 					nvme_status_to_string(err), err);
 	else
 		perror("delete namespace");
+
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -827,7 +872,8 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s
 	if (!cfg.namespace_id) {
 		fprintf(stderr, "%s: namespace-id parameter required\n",
 						cmd->name);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	num = argconfig_parse_comma_sep_array(cfg.cntlist,
@@ -847,6 +893,10 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s
 					nvme_status_to_string(err), err);
 	else
 		perror(attach ? "attach namespace" : "detach namespace");
+
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -917,6 +967,9 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
 					nvme_status_to_string(err), err);
 	else
 		perror("create namespace");
+
+	close(fd);
+
 	return err;
 }
 
@@ -958,8 +1011,10 @@ static void *get_registers(void)
 	membase = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
 	if (membase == MAP_FAILED) {
 		fprintf(stderr, "%s failed to map\n", base);
-		return NULL;
+		membase = NULL;
 	}
+
+	close(fd);
 	return membase;
 }
 
@@ -1503,8 +1558,10 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin,
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary) {
 		fprintf(stderr, "binary output\n");
 		fmt = BINARY;
@@ -1532,6 +1589,9 @@ int __id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin,
 	else
 		perror("identify controller");
 
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -1572,8 +1632,10 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 	if (!cfg.namespace_id)
@@ -1581,7 +1643,8 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p
 
 	if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) {
 		fprintf(stderr, "can not allocate controller list payload\n");
-		return ENOMEM;
+		err = ENOMEM;
+		goto close_fd;
 	}
 
 	err = nvme_identify_ns_descs(fd, cfg.namespace_id, nsdescs);
@@ -1603,6 +1666,9 @@ static int ns_descs(int argc, char **argv, struct command *cmd, struct plugin *p
 
 	free(nsdescs);
 
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -1650,8 +1716,10 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 	if (cfg.vendor_specific)
@@ -1680,6 +1748,10 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
 			nvme_status_to_string(err), err, cfg.namespace_id);
 	else
 		perror("identify namespace");
+
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -1698,9 +1770,12 @@ static int get_ns_id(int argc, char **argv, struct command *cmd, struct plugin *
 	nsid = nvme_get_nsid(fd);
 	if (nsid <= 0) {
 		perror(devicename);
+		close(fd);
 		return errno;
 	}
 	printf("%s: namespace-id:%d\n", devicename, nsid);
+
+	close(fd);
 	return 0;
 }
 
@@ -1761,11 +1836,13 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin
 
 	if (cfg.sel > 7) {
 		fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (!cfg.feature_id) {
 		fprintf(stderr, "feature-id required param\n");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	
 	switch (cfg.feature_id) {
@@ -1792,7 +1869,8 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin
 	if (cfg.data_len) {
 		if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
 			fprintf(stderr, "can not allocate feature payload\n");
-			return ENOMEM;
+			err = ENOMEM;
+			goto close_fd;
 		}
 		memset(buf, 0, cfg.data_len);
 	}
@@ -1818,6 +1896,10 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin
 
 	if (buf)
 		free(buf);
+
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -1866,28 +1948,33 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin
 	cfg.offset <<= 2;
 	if (fw_fd < 0) {
 		fprintf(stderr, "no firmware file provided\n");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = fstat(fw_fd, &sb);
 	if (err < 0) {
 		perror("fstat");
-		return errno;
+		goto close_fw_fd;
 	}
 
 	fw_size = sb.st_size;
 	if (fw_size & 0x3) {
 		fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fw_fd;
 	}
 	if (posix_memalign(&fw_buf, getpagesize(), fw_size)) {
 		fprintf(stderr, "No memory for f/w size:%d\n", fw_size);
-		return ENOMEM;
+		err = ENOMEM;
+		goto close_fw_fd;
 	}
 	if (cfg.xfer == 0 || cfg.xfer % 4096)
 		cfg.xfer = 4096;
-	if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size)))
-		return EIO;
+	if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size))) {
+		err = EIO;
+		goto free;
+	}
 
 	while (fw_size > 0) {
 		cfg.xfer = min(cfg.xfer, fw_size);
@@ -1908,7 +1995,12 @@ static int fw_download(int argc, char **argv, struct command *cmd, struct plugin
 	if (!err)
 		printf("Firmware download success\n");
 
+ free:
 	free(fw_buf);
+ close_fw_fd:
+	close(fw_fd);
+ close_fd:
+	close(fd);
 
 	return err;
 }
@@ -1960,15 +2052,18 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *
 
 	if (cfg.slot > 7) {
 		fprintf(stderr, "invalid slot:%d\n", cfg.slot);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.action > 7 || cfg.action == 4 || cfg.action == 5) {
 		fprintf(stderr, "invalid action:%d\n", cfg.action);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.bpid > 1) {
 		fprintf(stderr, "invalid boot partition id:%d\n", cfg.bpid);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_fw_commit(fd, cfg.slot, cfg.action, cfg.bpid);
@@ -1997,6 +2092,10 @@ static int fw_commit(int argc, char **argv, struct command *cmd, struct plugin *
 			printf(" bpid:%d", cfg.bpid);
 		printf("\n");
 	}
+
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -2015,9 +2114,12 @@ static int subsystem_reset(int argc, char **argv, struct command *cmd, struct pl
 
 	err = nvme_subsystem_reset(fd);
 	if (err < 0) {
+		close(fd);
 		perror("Subsystem-reset");
 		return errno;
 	}
+
+	close(fd);
 	return err;
 }
 
@@ -2036,9 +2138,12 @@ static int reset(int argc, char **argv, struct command *cmd, struct plugin *plug
 
 	err = nvme_reset_controller(fd);
 	if (err < 0) {
+		close(fd);
 		perror("Reset");
 		return errno;
 	}
+
+	close(fd);
 	return err;
 }
 
@@ -2057,9 +2162,12 @@ static int ns_rescan(int argc, char **argv, struct command *cmd, struct plugin *
 
 	err = nvme_ns_rescan(fd);
 	if (err < 0) {
+		close(fd);
 		perror("Namespace Rescan");
 		return errno;
 	}
+
+	close(fd);
 	return err;
 }
 
@@ -2124,7 +2232,8 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
 		break;
 	default:
 		fprintf(stderr, "Invalid Sanitize Action\n");
-		return -1;
+		ret = -1;
+		goto close_fd;
 	}
 
 	if (cfg.sanact != NVME_SANITIZE_ACT_EXIT && cfg.ause)
@@ -2135,7 +2244,8 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
 			sanitize_cdw10 |= (cfg.owpass << NVME_SANITIZE_OWPASS_SHIFT);
 		} else {
 			fprintf(stderr, "owpass out of range [0-16] or sanitize action is not set to overwrite\n");
-			return -1;
+			ret = -1;
+			goto close_fd;
 		}
 		if (cfg.oipbp)
 			sanitize_cdw10 |= NVME_SANITIZE_OIPBP;
@@ -2152,6 +2262,10 @@ static int sanitize(int argc, char **argv, struct command *cmd, struct plugin *p
 	ret = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd);
 
 	fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+
+ close_fd:
+	close(fd);
+
 	return ret;
 }
 
@@ -2186,13 +2300,19 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu
 		bar = get_registers();
 		fabrics = false;
 	}
-	if (!bar)
-		return ENODEV;
+	if (!bar) {
+		err = ENODEV;
+		goto close_fd;
+	}
 	show_ctrl_registers(bar, cfg.human_readable ? HUMAN : 0, fabrics);
 
 	if (fabrics)
 		free(bar);
-	return 0;
+
+ close_fd:
+	close(fd);
+
+	return err;
 }
 
 static int set_property(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -2225,17 +2345,18 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi
 
 	if (cfg.offset == -1) {
 		fprintf(stderr, "offset required param");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.value == -1) {
 		fprintf(stderr, "value required param");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_set_property(fd, cfg.offset, cfg.value);
 	if (err < 0) {
 		perror("set-property");
-		return errno;
 	} else if (!err) {
 		printf("set-property: %02x (%s), value: %#08x\n", cfg.offset,
 				nvme_register_to_string(cfg.offset), cfg.value);
@@ -2244,6 +2365,9 @@ static int set_property(int argc, char **argv, struct command *cmd, struct plugi
 				nvme_status_to_string(err), err);
 	}
 
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -2322,23 +2446,28 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
 	/* ses & pi checks set to 7 for forward-compatibility */
 	if (cfg.ses > 7) {
 		fprintf(stderr, "invalid secure erase settings:%d\n", cfg.ses);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.lbaf > 15) {
 		fprintf(stderr, "invalid lbaf:%d\n", cfg.lbaf);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.pi > 7) {
 		fprintf(stderr, "invalid pi:%d\n", cfg.pi);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.pil > 1) {
 		fprintf(stderr, "invalid pil:%d\n", cfg.pil);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.ms > 1) {
 		fprintf(stderr, "invalid ms:%d\n", cfg.ms);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_format(fd, cfg.namespace_id, cfg.lbaf, cfg.ses, cfg.pi,
@@ -2354,6 +2483,10 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
 		if (cfg.reset && S_ISCHR(nvme_stat.st_mode))
 			nvme_reset_controller(fd);
 	}
+
+ close_fd:
+	close(fd);
+
 	return err;
 }
 
@@ -2413,14 +2546,16 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
 
 	if (!cfg.feature_id) {
 		fprintf(stderr, "feature-id required param\n");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.feature_id == NVME_FEAT_LBA_RANGE)
 		cfg.data_len = 4096;
 	if (cfg.data_len) {
 		if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
 			fprintf(stderr, "can not allocate feature payload\n");
-			return ENOMEM;
+			err = ENOMEM;
+			goto close_fd;
 		}
 		memset(buf, 0, cfg.data_len);
 	}
@@ -2437,7 +2572,7 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
 		if (read(ffd, (void *)buf, cfg.data_len) < 0) {
 			fprintf(stderr, "failed to read data buffer from input file\n");
 			err = EINVAL;
-			goto free;
+			goto close_ffd;
 		}
 	}
 
@@ -2445,7 +2580,6 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
 				cfg.data_len, buf, &result);
 	if (err < 0) {
 		perror("set-feature");
-		goto free;
 	} else if (!err) {
 		printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
 			nvme_feature_to_string(cfg.feature_id), cfg.value);
@@ -2460,9 +2594,13 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
 		fprintf(stderr, "NVMe Status:%s(%x)\n",
 				nvme_status_to_string(err), err);
 
-free:
+ close_ffd:
+	close(ffd);
+ free:
 	if (buf)
 		free(buf);
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -2518,19 +2656,21 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p
 	sec_fd = open(cfg.file, O_RDONLY);
 	if (sec_fd < 0) {
 		fprintf(stderr, "no firmware file provided\n");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = fstat(sec_fd, &sb);
 	if (err < 0) {
 		perror("fstat");
-		return errno;
+		goto close_sec_fd;
 	}
 
 	sec_size = sb.st_size;
 	if (posix_memalign(&sec_buf, getpagesize(), sec_size)) {
 		fprintf(stderr, "No memory for security size:%d\n", sec_size);
-		return ENOMEM;
+		err = ENOMEM;
+		goto close_sec_fd;
 	}
 
 	if (read(sec_fd, sec_buf, sec_size) < 0) {
@@ -2549,8 +2689,12 @@ static int sec_send(int argc, char **argv, struct command *cmd, struct plugin *p
 	else
 		printf("NVME Security Send Command Success:%d\n", result);
 
-free:
+ free:
 	free(sec_buf);
+ close_sec_fd:
+	close(sec_fd);
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -2620,13 +2764,15 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
                 case NVME_DIR_SND_ID_OP_ENABLE:
                         if (!cfg.ttype) {
                                 fprintf(stderr, "target-dir required param\n");
-                                return EINVAL;
+                                err = EINVAL;
+				goto close_fd;
                         }
                         dw12 = cfg.ttype << 8 | cfg.endir;
                         break;
                 default:
                         fprintf(stderr, "invalid directive operations for Identify Directives\n");
-                        return EINVAL;
+                        err = EINVAL;
+			goto close_fd;
                 }
                 break;
         case NVME_DIR_STREAMS:
@@ -2636,19 +2782,22 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
                         break;
                 default:
                         fprintf(stderr, "invalid directive operations for Streams Directives\n");
-                        return EINVAL;
+                        err = EINVAL;
+			goto close_fd;
                 }
                 break;
         default:
                 fprintf(stderr, "invalid directive type\n");
-                return EINVAL;
-                break;
+                err = EINVAL;
+		goto close_fd;
         }
 
 
         if (cfg.data_len) {
-                if (posix_memalign(&buf, getpagesize(), cfg.data_len))
-                        exit(ENOMEM);
+                if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
+			err = ENOMEM;
+			goto close_fd;
+		}
                 memset(buf, 0, cfg.data_len);
         }
 
@@ -2664,7 +2813,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
                 if (read(ffd, (void *)buf, cfg.data_len) < 0) {
                         fprintf(stderr, "failed to read data buffer from input file\n");
 			err = EINVAL;
-			goto free;
+			goto close_ffd;
                 }
         }
 
@@ -2672,7 +2821,7 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
                                 cfg.data_len, dw12, buf, &result);
         if (err < 0) {
                 perror("dir-send");
-		goto free;
+		goto close_ffd;
         }
         if (!err) {
                 printf("dir-send: type %#x, operation %#x, spec_val %#x, nsid %#x, result %#x \n",
@@ -2688,9 +2837,13 @@ static int dir_send(int argc, char **argv, struct command *cmd, struct plugin *p
                 fprintf(stderr, "NVMe Status:%s(%x)\n",
                                 nvme_status_to_string(err), err);
 
-free:
+ close_ffd:
+	close(ffd);
+ free:
         if (buf)
                 free(buf);
+ close_fd:
+	close(fd);
         return err;
 }
 
@@ -2738,6 +2891,9 @@ static int write_uncor(int argc, char **argv, struct command *cmd, struct plugin
 					nvme_status_to_string(err), err);
 	else
 		printf("NVME Write Uncorrectable Success\n");
+
+	close(fd);
+
 	return err;
 }
 
@@ -2798,8 +2954,10 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
 	if (fd < 0)
 		return fd;
 
-	if (cfg.prinfo > 0xf)
-		return EINVAL;
+	if (cfg.prinfo > 0xf) {
+		err = EINVAL;
+		goto close_fd;
+	}
 
 	control |= (cfg.prinfo << 10);
 	if (cfg.limited_retry)
@@ -2820,6 +2978,9 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
 					nvme_status_to_string(err), err);
 	else
 		printf("NVME Write Zeroes Success\n");
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -2889,7 +3050,8 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin
 	nr = max(nc, max(nb, ns));
 	if (!nr || nr > 256) {
 		fprintf(stderr, "No range definition provided\n");
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	if (!cfg.namespace_id)
@@ -2900,7 +3062,8 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin
 	dsm = nvme_setup_dsm_range((__u32 *)ctx_attrs, (__u32 *)nlbs, (__u64 *)slbas, nr);
 	if (!dsm) {
 		fprintf(stderr, "failed to allocate data set payload\n");
-		return ENOMEM;
+		err = ENOMEM;
+		goto close_fd;
 	}
 
 	err = nvme_dsm(fd, cfg.namespace_id, cfg.cdw11, dsm, nr);
@@ -2911,6 +3074,9 @@ static int dsm(int argc, char **argv, struct command *cmd, struct plugin *plugin
 				nvme_status_to_string(err), err);
 	else
 		printf("NVMe DSM: success\n");
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -3004,7 +3170,8 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi
 		cfg.namespace_id = get_nsid(fd);
 	if (cfg.racqa > 7) {
 		fprintf(stderr, "invalid racqa:%d\n", cfg.racqa);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_resv_acquire(fd, cfg.namespace_id, cfg.rtype, cfg.racqa,
@@ -3015,6 +3182,9 @@ static int resv_acquire(int argc, char **argv, struct command *cmd, struct plugi
 		fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err);
 	else
 		printf("NVME Reservation Acquire success\n");
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -3066,7 +3236,8 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug
 		cfg.namespace_id = get_nsid(fd);
 	if (cfg.cptpl > 3) {
 		fprintf(stderr, "invalid cptpl:%d\n", cfg.cptpl);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_resv_register(fd, cfg.namespace_id, cfg.rrega, cfg.cptpl,
@@ -3077,6 +3248,9 @@ static int resv_register(int argc, char **argv, struct command *cmd, struct plug
 		fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err);
 	else
 		printf("NVME Reservation  success\n");
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -3130,11 +3304,13 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi
 		cfg.namespace_id = get_nsid(fd);
 	if (cfg.iekey > 1) {
 		fprintf(stderr, "invalid iekey:%d\n", cfg.iekey);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 	if (cfg.rrela > 7) {
 		fprintf(stderr, "invalid rrela:%d\n", cfg.rrela);
-		return EINVAL;
+		err = EINVAL;
+		goto close_fd;
 	}
 
 	err = nvme_resv_release(fd, cfg.namespace_id, cfg.rtype, cfg.rrela,
@@ -3145,6 +3321,9 @@ static int resv_release(int argc, char **argv, struct command *cmd, struct plugi
 		fprintf(stderr, "NVME IO command error:%s(%x)\n", nvme_status_to_string(err), err);
 	else
 		printf("NVME Reservation Release success\n");
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -3192,8 +3371,10 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin
 		return fd;
 
 	fmt = validate_output_format(cfg.output_format);
-	if (fmt < 0)
-		return fmt;
+	if (fmt < 0) {
+		err = fmt;
+		goto close_fd;
+	}
 	if (cfg.raw_binary)
 		fmt = BINARY;
 
@@ -3206,7 +3387,8 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin
 
 	if (posix_memalign((void **)&status, getpagesize(), cfg.numd << 2)) {
 		fprintf(stderr, "No memory for resv report:%d\n", cfg.numd << 2);
-		return ENOMEM;
+		err = ENOMEM;
+		goto close_fd;
 	}
 	memset(status, 0, cfg.numd << 2);
 
@@ -3226,6 +3408,9 @@ static int resv_report(int argc, char **argv, struct command *cmd, struct plugin
 		}
 	}
 	free(status);
+
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -3323,8 +3508,10 @@ static int submit_io(int opcode, char *command, const char *desc,
 		return fd;
 
 	dfd = mfd = opcode & 1 ? STDIN_FILENO : STDOUT_FILENO;
-	if (cfg.prinfo > 0xf)
-		return EINVAL;
+	if (cfg.prinfo > 0xf) {
+		err = EINVAL;
+		goto close_fd;
+	}
 
 	dsmgmt = cfg.dsmgmt;
 	control |= (cfg.prinfo << 10);
@@ -3336,7 +3523,8 @@ static int submit_io(int opcode, char *command, const char *desc,
 		if (cfg.dtype > 0xf) {
 			fprintf(stderr, "Invalid directive type, %x\n",
 				cfg.dtype);
-			return EINVAL;
+			err = EINVAL;
+			goto close_fd;
 		}
 		control |= cfg.dtype << 4;
 		dsmgmt |= ((__u32)cfg.dspec) << 16;
@@ -3346,7 +3534,8 @@ static int submit_io(int opcode, char *command, const char *desc,
 		dfd = open(cfg.data, flags, mode);
 		if (dfd < 0) {
 			perror(cfg.data);
-			return EINVAL;
+			err = EINVAL;
+			goto close_fd;
 		}
 		mfd = dfd;
 	}
@@ -3354,17 +3543,19 @@ static int submit_io(int opcode, char *command, const char *desc,
 		mfd = open(cfg.metadata, flags, mode);
 		if (mfd < 0) {
 			perror(cfg.metadata);
-			return EINVAL;
+			err = EINVAL;
+			goto close_dfd;
 		}
 	}
 
 	if (!cfg.data_size)	{
 		fprintf(stderr, "data size not provided\n");
-		return EINVAL;
+		err = EINVAL;
+		goto close_mfd;
 	}
 
 	if (ioctl(fd, BLKPBSZGET, &phys_sector_size) < 0)
-		return errno;
+		goto close_mfd;
 
 	buffer_size = (cfg.block_count + 1) * phys_sector_size;
 	if (cfg.data_size < buffer_size) {
@@ -3376,30 +3567,31 @@ static int submit_io(int opcode, char *command, const char *desc,
 
 	if (posix_memalign(&buffer, getpagesize(), buffer_size)) {
 		fprintf(stderr, "can not allocate io payload\n");
-		return ENOMEM;
+		err = ENOMEM;
+		goto close_mfd;
 	}
 	memset(buffer, 0, cfg.data_size);
 
 	if (cfg.metadata_size) {
 		mbuffer = malloc(cfg.metadata_size);
 		if (!mbuffer) {
- 			free(buffer);
 			fprintf(stderr, "can not allocate io metadata payload\n");
-			return ENOMEM;
+			err = ENOMEM;
+			goto free_buffer;
 		}
 	}
 
 	if ((opcode & 1) && read(dfd, (void *)buffer, cfg.data_size) < 0) {
 		fprintf(stderr, "failed to read data buffer from input file\n");
 		err = EINVAL;
-		goto free_and_return;
+		goto free_mbuffer;
 	}
 
 	if ((opcode & 1) && cfg.metadata_size &&
 				read(mfd, (void *)mbuffer, cfg.metadata_size) < 0) {
 		fprintf(stderr, "failed to read meta-data buffer from input file\n");
 		err = EINVAL;
-		goto free_and_return;
+		goto free_mbuffer;
 	}
 
 	if (cfg.show) {
@@ -3416,7 +3608,7 @@ static int submit_io(int opcode, char *command, const char *desc,
 		printf("apptag       : %04x\n", cfg.app_tag);
 		printf("appmask      : %04x\n", cfg.app_tag_mask);
 		if (cfg.dry_run)
-			goto free_and_return;
+			goto free_mbuffer;
 	}
 
 	gettimeofday(&start_time, NULL);
@@ -3434,19 +3626,26 @@ static int submit_io(int opcode, char *command, const char *desc,
 		if (!(opcode & 1) && write(dfd, (void *)buffer, cfg.data_size) < 0) {
 			fprintf(stderr, "failed to write buffer to output file\n");
 			err = EINVAL;
-			goto free_and_return;
 		} else if (!(opcode & 1) && cfg.metadata_size &&
 				write(mfd, (void *)mbuffer, cfg.metadata_size) < 0) {
 			fprintf(stderr, "failed to write meta-data buffer to output file\n");
 			err = EINVAL;
-			goto free_and_return;
 		} else
 			fprintf(stderr, "%s: Success\n", command);
 	}
- free_and_return:
-	free(buffer);
+
+ free_mbuffer:
 	if (cfg.metadata_size)
 		free(mbuffer);
+ free_buffer:
+	free(buffer);
+ close_mfd:
+	if (strlen(cfg.metadata))
+		close(mfd);
+ close_dfd:
+	close(dfd);
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -3528,7 +3727,8 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
 		if (posix_memalign(&sec_buf, getpagesize(), cfg.size)) {
 			fprintf(stderr, "No memory for security size:%d\n",
 								cfg.size);
-			return ENOMEM;
+			err = ENOMEM;
+			goto close_fd;
 		}
 	}
 
@@ -3550,6 +3750,8 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
 
 	free(sec_buf);
 
+ close_fd:
+	close(fd);
 	return err;
 }
 
@@ -3615,7 +3817,8 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin
                         break;
                 default:
                         fprintf(stderr, "invalid directive operations for Identify Directives\n");
-                        return EINVAL;
+                        err = EINVAL;
+			goto close_fd;
                 }
                 break;
         case NVME_DIR_STREAMS:
@@ -3633,18 +3836,21 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin
                         break;
                 default:
                         fprintf(stderr, "invalid directive operations for Streams Directives\n");
-                        return EINVAL;
+                        err = EINVAL;
+			goto close_fd;
                 }
                 break;
         default:
                 fprintf(stderr, "invalid directive type\n");
-                return EINVAL;
-                break;
+                err = EINVAL;
+		goto close_fd;
         }
 
         if (cfg.data_len) {
-                if (posix_memalign(&buf, getpagesize(), cfg.data_len))
-                        exit(ENOMEM);
+                if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
+			err = ENOMEM;
+			goto close_fd;
+		}
                 memset(buf, 0, cfg.data_len);
         }
 
@@ -3672,10 +3878,12 @@ static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin
         else if (err > 0)
                 fprintf(stderr, "NVMe Status:%s(%x)\n",
                                 nvme_status_to_string(err), err);
-free:
-        if (buf)
-                free(buf);
-        return err;
+ free:
+	if (cfg.data_len)
+		free(buf);
+ close_fd:
+	close(fd);
+	return err;
 }
 
 static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, struct command *cmd)
@@ -3787,7 +3995,8 @@ static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, stru
 			   S_IRUSR | S_IRGRP | S_IROTH);
 		if (wfd < 0) {
 			perror(cfg.input_file);
-			return EINVAL;
+			err = EINVAL;
+			goto close_fd;
 		}
 	}
 
@@ -3795,7 +4004,8 @@ static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, stru
 		metadata = malloc(cfg.metadata_len);
 		if (!metadata) {
 			fprintf(stderr, "can not allocate metadata payload\n");
-			return ENOMEM;
+			err = ENOMEM;
+			goto close_fd;
 		}
 	}
 	if (cfg.data_len) {
@@ -3803,19 +4013,20 @@ static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, stru
 			if (metadata)
 				free(metadata);
 			fprintf(stderr, "can not allocate data payload\n");
-			return ENOMEM;
+			err = ENOMEM;
+			goto free_metadata;
 		}
 
 		memset(data, cfg.prefill, cfg.data_len);
 		if (!cfg.read && !cfg.write) {
 			fprintf(stderr, "data direction not given\n");
 			err = EINVAL;
-			goto free_and_return;
+			goto free_data;
 		} else if (cfg.write) {
 			if (read(wfd, data, cfg.data_len) < 0) {
 				fprintf(stderr, "failed to read write buffer\n");
 				err = EINVAL;
-				goto free_and_return;
+				goto free_data;
 			}
 		}
 	}
@@ -3839,7 +4050,7 @@ static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, stru
 		printf("cdw15        : %08x\n", cfg.cdw15);
 		printf("timeout_ms   : %08x\n", cfg.timeout);
 		if (cfg.dry_run)
-			goto free_and_return;
+			goto free_data;
 	}
 
 	err = nvme_passthru(fd, ioctl_cmd, cfg.opcode, cfg.flags, cfg.rsvd,
@@ -3861,9 +4072,14 @@ static int passthru(int argc, char **argv, int ioctl_cmd, const char *desc, stru
 			d_raw((unsigned char *)data, cfg.data_len);
 	}
 
-free_and_return:
-	free(data);
-	free(metadata);
+ free_data:
+	if (cfg.data_len)
+		free(data);
+ free_metadata:
+	if (cfg.metadata_len)
+		free(metadata);
+ close_fd:
+	close(fd);
 	return err;
 }
 
-- 
2.7.4




More information about the Linux-nvme mailing list