Recent changes (master)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit a3b4cf7dcae447729f0f4a4ea122f605b909ed70:

  diskutil: separate out stats from name (2014-04-11 12:17:53 -0600)

are available in the git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to fb73340c52bcab712dfb175dafbcb5156abdda12:

  Windows: set sizeof(sun_path) to 260 (MAX_PATH). (2014-04-14 20:19:54 -0600)

----------------------------------------------------------------
Bruce Cran (1):
      Windows: set sizeof(sun_path) to 260 (MAX_PATH).

Jens Axboe (43):
      init: fix more cases of leaking pid_file
      stat: check that TEMP environment variable is half-way sane
      server: ensure that dus->name is always NULL terminated
      init: fix potential buffer overrun in make_filename()
      verify: fix potential buffer overrun in dump_buf()
      file: fix potential buffer overrun in get_fs_free_counts()
      net engine: fix potential buffer overrun in socket path
      client: fix potential buffer overrun in socket path
      server: fix potential buffer overrun in bind string
      server: fix potential buffer overrun in socket setup path
      stat: fix wrong check for whether we have a description or not
      Fix missing sign conversion in ignore_error_type()
      Make td_verror() use an unsigned type
      gettime: use unsigned loop counter
      server: fix missing comma in fio_server_ops[] strings
      eta: fix potential divide by zero
      idletime: fix potential divide-by-zero
      stat: fix potential divide-by-zero
      backend: fix potential divide-by-zero
      init: remove dead code
      Error check fcntl() calls
      make_filename: another off-by-one buffer issue
      num2str: ensure we never access postfix[] out-of-bounds
      backend: better NULL termination fix for IO scheduler switching
      server: sanity check incoming command size (and payload)
      server: ensure that incoming iolog name is NULL terminated
      net engine: get rid of unused struct sockaddr_in6
      td_verror() needs errno style error
      e4defrag: pass 'error' into td_verror()
      filesetup: silence bogus warning on close(-1)
      init: silence bogus td == NULL warning
      gettime: handle pthread_create() failure
      stat: warn on failure to detach DU thread
      gettime: init 'failed' before use
      Avoid overwriting allocated pid_file
      idletime: unlock ->start_lock in error cases
      Fix is_power_of_2() for longs
      parse: make it clear that 'cp' can't be NULL for o->off1
      diskutil: make it clear that parent != NULL for json output
      Fix potential NULL dereference in alloc_mem_mmap()
      disk util: fix bug in strncpy() conversion
      init: fix leak bug fix from commit 60c5ec73
      init: improve command line check for when to print usage/help

 backend.c                         |   11 ++++--
 client.c                          |    2 +-
 diskutil.c                        |   12 ++++--
 engines/binject.c                 |    7 ++--
 engines/e4defrag.c                |    4 +-
 engines/net.c                     |    9 ++---
 engines/sg.c                      |    7 ++--
 eta.c                             |   24 ++++++++---
 filesetup.c                       |   16 ++++++--
 fio.h                             |    5 ++-
 gettime.c                         |   12 ++++--
 idletime.c                        |   13 ++++--
 init.c                            |   79 +++++++++++++++++++++++++++++--------
 io_u.c                            |    2 +-
 lib/num2str.c                     |    5 +++
 libfio.c                          |   16 ++++++++
 memory.c                          |    5 ++-
 options.c                         |    2 +-
 os/windows/posix/include/sys/un.h |    2 +-
 parse.c                           |    2 +-
 server.c                          |   40 +++++++++++++------
 server.h                          |    1 +
 stat.c                            |   26 +++++++++---
 verify.c                          |   22 +++++++++--
 24 files changed, 239 insertions(+), 85 deletions(-)

---

Diff of recent changes:

diff --git a/backend.c b/backend.c
index b05e543..62bca29 100644
--- a/backend.c
+++ b/backend.c
@@ -182,7 +182,11 @@ static int __check_min_rate(struct thread_data *td, struct timeval *now,
 								ratemin);
 				return 1;
 			} else {
-				rate = ((bytes - td->rate_bytes[ddir]) * 1000) / spent;
+				if (spent)
+					rate = ((bytes - td->rate_bytes[ddir]) * 1000) / spent;
+				else
+					rate = 0;
+
 				if (rate < ratemin ||
 				    bytes < td->rate_bytes[ddir]) {
 					log_err("%s: min rate %u not met, got"
@@ -1110,13 +1114,14 @@ static int switch_ioscheduler(struct thread_data *td)
 	/*
 	 * Read back and check that the selected scheduler is now the default.
 	 */
-	memset(tmp, 0, sizeof(tmp));
-	ret = fread(tmp, 1, sizeof(tmp) - 1, f);
+	ret = fread(tmp, sizeof(tmp), 1, f);
 	if (ferror(f) || ret < 0) {
 		td_verror(td, errno, "fread");
 		fclose(f);
 		return 1;
 	}
+	tmp[sizeof(tmp) - 1] = '\0';
+
 
 	sprintf(tmp2, "[%s]", td->o.ioscheduler);
 	if (!strstr(tmp, tmp2)) {
diff --git a/client.c b/client.c
index 05439e1..af6621d 100644
--- a/client.c
+++ b/client.c
@@ -388,7 +388,7 @@ static int fio_client_connect_sock(struct fio_client *client)
 
 	memset(addr, 0, sizeof(*addr));
 	addr->sun_family = AF_UNIX;
-	strcpy(addr->sun_path, client->hostname);
+	strncpy(addr->sun_path, client->hostname, sizeof(addr->sun_path) - 1);
 
 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (fd < 0) {
diff --git a/diskutil.c b/diskutil.c
index d97c5ca..cb285cf 100644
--- a/diskutil.c
+++ b/diskutil.c
@@ -6,6 +6,7 @@
 #include <dirent.h>
 #include <libgen.h>
 #include <math.h>
+#include <assert.h>
 
 #include "fio.h"
 #include "smalloc.h"
@@ -299,7 +300,7 @@ static struct disk_util *disk_util_add(struct thread_data *td, int majdev,
 		sfree(du);
 		return NULL;
 	}
-	strncpy((char *) du->dus.name, basename(path) - 1, FIO_DU_NAME_SZ);
+	strncpy((char *) du->dus.name, basename(path), FIO_DU_NAME_SZ - 1);
 	du->sysfs_root = path;
 	du->major = majdev;
 	du->minor = mindev;
@@ -686,12 +687,15 @@ void show_disk_util(int terse, struct json_object *parent)
 		return;
 	}
 
-	if (!terse && !parent)
+	if (output_format == FIO_OUTPUT_JSON)
+		assert(parent);
+
+	if (!terse && output_format != FIO_OUTPUT_JSON)
 		log_info("\nDisk stats (read/write):\n");
 
-	if (output_format == FIO_OUTPUT_JSON) {
+	if (output_format == FIO_OUTPUT_JSON)
 		json_object_add_disk_utils(parent, &disk_list);
-	} else
+	else
 		flist_for_each(entry, &disk_list) {
 			du = flist_entry(entry, struct disk_util, list);
 
diff --git a/engines/binject.c b/engines/binject.c
index fb19062..0264d0a 100644
--- a/engines/binject.c
+++ b/engines/binject.c
@@ -109,10 +109,9 @@ static int fio_binject_getevents(struct thread_data *td, unsigned int min,
 		/*
 		 * don't block for min events == 0
 		 */
-		if (!min) {
-			bd->fd_flags[i] = fcntl(bf->fd, F_GETFL);
-			fcntl(bf->fd, F_SETFL, bd->fd_flags[i] | O_NONBLOCK);
-		}
+		if (!min)
+			fio_set_fd_nonblocking(bf->fd, "binject");
+
 		bd->pfds[i].fd = bf->fd;
 		bd->pfds[i].events = POLLIN;
 	}
diff --git a/engines/e4defrag.c b/engines/e4defrag.c
index 4d87f67..3599ab8 100644
--- a/engines/e4defrag.c
+++ b/engines/e4defrag.c
@@ -80,7 +80,7 @@ static int fio_e4defrag_init(struct thread_data *td)
 
 	ed = malloc(sizeof(*ed));
 	if (!ed) {
-		td_verror(td, -ENOMEM, "io_queue_init");
+		td_verror(td, ENOMEM, "io_queue_init");
 		return 1;
 	}
 	memset(ed, 0 ,sizeof(*ed));
@@ -91,7 +91,7 @@ static int fio_e4defrag_init(struct thread_data *td)
 
 	ed->donor_fd = open(donor_name, O_CREAT|O_WRONLY, 0644);
 	if (ed->donor_fd < 0) {
-		td_verror(td, ed->donor_fd, "io_queue_init");
+		td_verror(td, errno, "io_queue_init");
 		log_err("Can't open donor file %s err:%d", donor_name, ed->donor_fd);
 		free(ed);
 		return 1;
diff --git a/engines/net.c b/engines/net.c
index d036a58..8087207 100644
--- a/engines/net.c
+++ b/engines/net.c
@@ -945,7 +945,8 @@ static int fio_netio_setup_connect_unix(struct thread_data *td,
 	struct sockaddr_un *soun = &nd->addr_un;
 
 	soun->sun_family = AF_UNIX;
-	strcpy(soun->sun_path, path);
+	memset(soun->sun_path, 0, sizeof(soun->sun_path));
+	strncpy(soun->sun_path, path, sizeof(soun->sun_path) - 1);
 	return 0;
 }
 
@@ -976,7 +977,7 @@ static int fio_netio_setup_listen_unix(struct thread_data *td, const char *path)
 
 	memset(addr, 0, sizeof(*addr));
 	addr->sun_family = AF_UNIX;
-	strcpy(addr->sun_path, path);
+	strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
 	unlink(path);
 
 	len = sizeof(addr->sun_family) + strlen(path) + 1;
@@ -998,13 +999,11 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
 	struct netio_options *o = td->eo;
 	struct ip_mreq mr;
 	struct sockaddr_in sin;
-	struct sockaddr_in6 sin6;
 	struct sockaddr *saddr;
 	int fd, opt, type, domain;
 	socklen_t len;
 
 	memset(&sin, 0, sizeof(sin));
-	memset(&sin6, 0, sizeof(sin6));
 
 	if (o->proto == FIO_TYPE_TCP) {
 		type = SOCK_STREAM;
@@ -1087,7 +1086,7 @@ static int fio_netio_setup_listen_inet(struct thread_data *td, short port)
 		len = sizeof(nd->addr6);
 
 		nd->addr6.sin6_family = AF_INET6;
-		nd->addr6.sin6_addr = sin6.sin6_addr.s6_addr ? sin6.sin6_addr : in6addr_any;
+		nd->addr6.sin6_addr = in6addr_any;
 		nd->addr6.sin6_port = htons(port);
 	}
 
diff --git a/engines/sg.c b/engines/sg.c
index 88d9125..fcd9c41 100644
--- a/engines/sg.c
+++ b/engines/sg.c
@@ -77,10 +77,9 @@ static int fio_sgio_getevents(struct thread_data *td, unsigned int min,
 		/*
 		 * don't block for min events == 0
 		 */
-		if (!min) {
-			sd->fd_flags[i] = fcntl(f->fd, F_GETFL);
-			fcntl(f->fd, F_SETFL, sd->fd_flags[i] | O_NONBLOCK);
-		}
+		if (!min)
+			fio_set_fd_nonblocking(f->fd, "sg");
+
 		sd->pfds[i].fd = f->fd;
 		sd->pfds[i].events = POLLIN;
 	}
diff --git a/eta.c b/eta.c
index 42066e0..7500082 100644
--- a/eta.c
+++ b/eta.c
@@ -174,14 +174,26 @@ static int thread_eta(struct thread_data *td)
 		double perc, perc_t;
 
 		bytes_done = ddir_rw_sum(td->io_bytes);
-		perc = (double) bytes_done / (double) bytes_total;
-		if (perc > 1.0)
-			perc = 1.0;
+
+		if (bytes_total) {
+			perc = (double) bytes_done / (double) bytes_total;
+			if (perc > 1.0)
+				perc = 1.0;
+		} else
+			perc = 0.0;
 
 		if (td->o.time_based) {
-			perc_t = (double) elapsed / (double) timeout;
-			if (perc_t < perc)
-				perc = perc_t;
+			if (timeout) {
+				perc_t = (double) elapsed / (double) timeout;
+				if (perc_t < perc)
+					perc = perc_t;
+			} else {
+				/*
+				 * Will never hit, we can't have time_based
+				 * without a timeout set.
+				 */
+				perc = 0.0;
+			}
 		}
 
 		eta_sec = (unsigned long) (elapsed * (1.0 / perc)) - elapsed;
diff --git a/filesetup.c b/filesetup.c
index bf56112..490f0fc 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -688,7 +688,8 @@ static unsigned long long get_fs_free_counts(struct thread_data *td)
 		} else if (f->filetype != FIO_TYPE_FILE)
 			continue;
 
-		strcpy(buf, f->file_name);
+		buf[255] = '\0';
+		strncpy(buf, f->file_name, 255);
 
 		if (stat(buf, &sb) < 0) {
 			if (errno != ENOENT)
@@ -914,7 +915,13 @@ int setup_files(struct thread_data *td)
 
 			err = __file_invalidate_cache(td, f, old_len,
 								extend_len);
-			close(f->fd);
+
+			/*
+			 * Shut up static checker
+			 */
+			if (f->fd != -1)
+				close(f->fd);
+
 			f->fd = -1;
 			if (err)
 				break;
@@ -1325,8 +1332,11 @@ int put_file(struct thread_data *td, struct fio_file *f)
 	if (--f->references)
 		return 0;
 
-	if (should_fsync(td) && td->o.fsync_on_close)
+	if (should_fsync(td) && td->o.fsync_on_close) {
 		f_ret = fsync(f->fd);
+		if (f_ret < 0)
+			f_ret = errno;
+	}
 
 	if (td->io_ops->close_file)
 		ret = td->io_ops->close_file(td, f);
diff --git a/fio.h b/fio.h
index 3df5bd9..544916f 100644
--- a/fio.h
+++ b/fio.h
@@ -351,7 +351,7 @@ enum {
 
 #define __td_verror(td, err, msg, func)					\
 	do {								\
-		int ____e = (err);						\
+		unsigned int ____e = (err);				\
 		if ((td)->error)					\
 			break;						\
 		(td)->error = ____e;					\
@@ -441,6 +441,7 @@ extern char *num2str(unsigned long, int, int, int, int);
 extern int ioengine_load(struct thread_data *);
 extern int parse_dryrun(void);
 extern int fio_running_or_pending_io_threads(void);
+extern void fio_set_fd_nonblocking(int, const char *);
 
 extern uintptr_t page_mask;
 extern uintptr_t page_size;
@@ -587,7 +588,7 @@ static inline unsigned int td_min_bs(struct thread_data *td)
 	return min(td->o.min_bs[DDIR_TRIM], min_bs);
 }
 
-static inline int is_power_of_2(unsigned int val)
+static inline int is_power_of_2(unsigned long val)
 {
 	return (val != 0 && ((val & (val - 1)) == 0));
 }
diff --git a/gettime.c b/gettime.c
index c6d45f8..fa750ec 100644
--- a/gettime.c
+++ b/gettime.c
@@ -534,10 +534,10 @@ int fio_monotonic_clocktest(void)
 	struct clock_thread *threads;
 	unsigned int nr_cpus = cpus_online();
 	struct clock_entry *entries;
-	unsigned long tentries, failed;
+	unsigned long tentries, failed = 0;
 	struct clock_entry *prev, *this;
 	uint32_t seq = 0;
-	int i;
+	unsigned int i;
 
 	log_info("cs: reliable_tsc: %s\n", tsc_reliable ? "yes" : "no");
 
@@ -560,7 +560,11 @@ int fio_monotonic_clocktest(void)
 		pthread_mutex_init(&t->lock, NULL);
 		pthread_mutex_init(&t->started, NULL);
 		pthread_mutex_lock(&t->lock);
-		pthread_create(&t->thread, NULL, clock_thread_fn, t);
+		if (pthread_create(&t->thread, NULL, clock_thread_fn, t)) {
+			failed++;
+			nr_cpus = i;
+			break;
+		}
 	}
 
 	for (i = 0; i < nr_cpus; i++) {
@@ -575,7 +579,7 @@ int fio_monotonic_clocktest(void)
 		pthread_mutex_unlock(&t->lock);
 	}
 
-	for (failed = i = 0; i < nr_cpus; i++) {
+	for (i = 0; i < nr_cpus; i++) {
 		struct clock_thread *t = &threads[i];
 		void *ret;
 
diff --git a/idletime.c b/idletime.c
index c0bc0bf..8d23154 100644
--- a/idletime.c
+++ b/idletime.c
@@ -109,12 +109,16 @@ static void *idle_prof_thread_fn(void *data)
 	pthread_mutex_lock(&ipt->start_lock);
 
 	/* exit if other threads failed to initialize */
-	if (ipc.status == IDLE_PROF_STATUS_ABORT)
+	if (ipc.status == IDLE_PROF_STATUS_ABORT) {
+		pthread_mutex_unlock(&ipt->start_lock);
 		return NULL;
+	}
 
 	/* exit if we are doing calibration only */
-	if (ipc.status == IDLE_PROF_STATUS_CALI_STOP)
+	if (ipc.status == IDLE_PROF_STATUS_CALI_STOP) {
+		pthread_mutex_unlock(&ipt->start_lock);
 		return NULL;
+	}
 
 	fio_gettime(&ipt->tps, NULL);
 	ipt->state = TD_RUNNING;
@@ -336,7 +340,10 @@ void fio_idle_prof_stop(void)
 		/* calculate idleness */
 		if (ipc.cali_mean != 0.0) {
 			runt = utime_since(&ipt->tps, &ipt->tpe);
-			ipt->idleness = ipt->loops * ipc.cali_mean / runt;
+			if (runt)
+				ipt->idleness = ipt->loops * ipc.cali_mean / runt;
+			else
+				ipt->idleness = 0.0;
 		} else
 			ipt->idleness = 0.0;
 	}
diff --git a/init.c b/init.c
index 215b60d..7630978 100644
--- a/init.c
+++ b/init.c
@@ -942,6 +942,7 @@ static char *make_filename(char *buf, struct thread_options *o,
 {
 	struct fpre_keyword *f;
 	char copy[PATH_MAX];
+	size_t dst_left = PATH_MAX - 1;
 
 	if (!o->filename_format || !strlen(o->filename_format)) {
 		sprintf(buf, "%s.%d.%d", jobname, jobnum, filenum);
@@ -969,25 +970,47 @@ static char *make_filename(char *buf, struct thread_options *o,
 			if (pre_len) {
 				strncpy(dst, buf, pre_len);
 				dst += pre_len;
+				dst_left -= pre_len;
 			}
 
 			switch (f->key) {
-			case FPRE_JOBNAME:
-				dst += sprintf(dst, "%s", jobname);
+			case FPRE_JOBNAME: {
+				int ret;
+
+				ret = snprintf(dst, dst_left, "%s", jobname);
+				if (ret < 0)
+					break;
+				dst += ret;
+				dst_left -= ret;
 				break;
-			case FPRE_JOBNUM:
-				dst += sprintf(dst, "%d", jobnum);
+				}
+			case FPRE_JOBNUM: {
+				int ret;
+
+				ret = snprintf(dst, dst_left, "%d", jobnum);
+				if (ret < 0)
+					break;
+				dst += ret;
+				dst_left -= ret;
 				break;
-			case FPRE_FILENUM:
-				dst += sprintf(dst, "%d", filenum);
+				}
+			case FPRE_FILENUM: {
+				int ret;
+
+				ret = snprintf(dst, dst_left, "%d", filenum);
+				if (ret < 0)
+					break;
+				dst += ret;
+				dst_left -= ret;
 				break;
+				}
 			default:
 				assert(0);
 				break;
 			}
 
 			if (post_start)
-				strcpy(dst, buf + post_start);
+				strncpy(dst, buf + post_start, dst_left);
 
 			strcpy(buf, copy);
 		} while (1);
@@ -1435,9 +1458,6 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
 		i++;
 	}
 
-	for (i = 0; i < num_opts; i++)
-		free(opts[i]);
-
 	free(string);
 	free(name);
 	free(opts);
@@ -1694,8 +1714,6 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 	optind = 1;
 
 	while ((c = getopt_long_only(argc, argv, ostr, l_opts, &lidx)) != -1) {
-		did_arg = 1;
-
 		if ((c & FIO_CLIENT_FLAG) || client_flag_set(c)) {
 			parse_cmd_client(cur_client, argv[optind - 1]);
 			c &= ~FIO_CLIENT_FLAG;
@@ -1752,30 +1770,35 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			append_terse_output = 1;
 			break;
 		case 'h':
+			did_arg = 1;
 			if (!cur_client) {
 				usage(argv[0]);
 				do_exit++;
 			}
 			break;
 		case 'c':
+			did_arg = 1;
 			if (!cur_client) {
 				fio_show_option_help(optarg);
 				do_exit++;
 			}
 			break;
 		case 'i':
+			did_arg = 1;
 			if (!cur_client) {
 				fio_show_ioengine_help(optarg);
 				do_exit++;
 			}
 			break;
 		case 's':
+			did_arg = 1;
 			dump_cmdline = 1;
 			break;
 		case 'r':
 			read_only = 1;
 			break;
 		case 'v':
+			did_arg = 1;
 			if (!cur_client) {
 				log_info("%s\n", fio_version_string);
 				do_exit++;
@@ -1812,6 +1835,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 				do_exit++;
 			break;
 		case 'P':
+			did_arg = 1;
 			parse_only = 1;
 			break;
 		case 'x': {
@@ -1831,6 +1855,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			break;
 			}
 		case 'p':
+			did_arg = 1;
 			if (exec_profile)
 				free(exec_profile);
 			exec_profile = strdup(optarg);
@@ -1842,8 +1867,9 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			if (!strncmp(opt, "name", 4) && td) {
 				ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type);
 				if (ret)
-					return 0;
+					goto out_free;
 				td = NULL;
+				did_arg = 1;
 			}
 			if (!td) {
 				int is_section = !strncmp(opt, "name", 4);
@@ -1857,7 +1883,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 
 				td = get_new_job(global, &def_thread, 1);
 				if (!td || ioengine_load(td))
-					return 0;
+					goto out_free;
 				fio_options_set_ioengine_opts(l_opts, td);
 			}
 
@@ -1879,7 +1905,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			if (!ret && !strcmp(opt, "ioengine")) {
 				free_ioengine(td);
 				if (ioengine_load(td))
-					return 0;
+					goto out_free;
 				fio_options_set_ioengine_opts(l_opts, td);
 			}
 			break;
@@ -1887,7 +1913,12 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 		case FIO_GETOPT_IOENGINE: {
 			const char *opt = l_opts[lidx].name;
 			char *val = optarg;
+
+			if (!td)
+				break;
+
 			ret = fio_cmd_ioengine_option_parse(td, opt, val);
+			did_arg = 1;
 			break;
 		}
 		case 'w':
@@ -1902,6 +1933,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			}
 			break;
 		case 'S':
+			did_arg = 1;
 			if (nr_clients) {
 				log_err("fio: can't be both client and server\n");
 				do_exit++;
@@ -1914,17 +1946,21 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			backend = 1;
 			break;
 		case 'D':
+			if (pid_file)
+				free(pid_file);
 			pid_file = strdup(optarg);
 			break;
 		case 'I':
 			if ((ret = fio_idle_prof_parse_opt(optarg))) {
 				/* exit on error and calibration only */
+				did_arg = 1;
 				do_exit++;
-				if (ret == -1) 
+				if (ret == -1)
 					exit_val = 1;
 			}
 			break;
 		case 'C':
+			did_arg = 1;
 			if (is_backend) {
 				log_err("fio: can't be both client and server\n");
 				do_exit++;
@@ -1951,10 +1987,12 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 			}
 			break;
 		case 'T':
+			did_arg = 1;
 			do_exit++;
 			exit_val = fio_monotonic_clocktest();
 			break;
 		case 'G':
+			did_arg = 1;
 			do_exit++;
 			exit_val = fio_crctest(optarg);
 			break;
@@ -1994,8 +2032,11 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 		free(pid_file);
 
 	if (td) {
-		if (!ret)
+		if (!ret) {
 			ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type);
+			if (ret)
+				did_arg = 1;
+		}
 	}
 
 	while (!ret && optind < argc) {
@@ -2005,6 +2046,10 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
 		optind++;
 	}
 
+out_free:
+	if (pid_file)
+		free(pid_file);
+
 	return ini_idx;
 }
 
diff --git a/io_u.c b/io_u.c
index 411da32..4b0b5a7 100644
--- a/io_u.c
+++ b/io_u.c
@@ -678,7 +678,7 @@ static void set_rw_ddir(struct thread_data *td, struct io_u *io_u)
 
 void put_file_log(struct thread_data *td, struct fio_file *f)
 {
-	int ret = put_file(td, f);
+	unsigned int ret = put_file(td, f);
 
 	if (ret)
 		td_verror(td, ret, "file close");
diff --git a/lib/num2str.c b/lib/num2str.c
index 12d6f39..8961868 100644
--- a/lib/num2str.c
+++ b/lib/num2str.c
@@ -4,6 +4,8 @@
 
 #include "../fio.h"
 
+#define ARRAY_LENGTH(arr)	sizeof(arr) / sizeof((arr)[0])
+
 /*
  * Cheesy number->string conversion, complete with carry rounding error.
  */
@@ -46,6 +48,9 @@ char *num2str(unsigned long num, int maxlen, int base, int pow2, int unit_base)
 
 	if (modulo == -1U) {
 done:
+		if (post_index >= ARRAY_LENGTH(postfix))
+			post_index = 0;
+
 		sprintf(buf, "%lu%s%s", num, postfix[post_index],
 			byte_postfix[byte_post_index]);
 		return buf;
diff --git a/libfio.c b/libfio.c
index 3fde492..5ed8c60 100644
--- a/libfio.c
+++ b/libfio.c
@@ -27,6 +27,7 @@
 #include <signal.h>
 #include <stdint.h>
 #include <locale.h>
+#include <fcntl.h>
 
 #include "fio.h"
 #include "smalloc.h"
@@ -233,6 +234,21 @@ int fio_running_or_pending_io_threads(void)
 	return 0;
 }
 
+void fio_set_fd_nonblocking(int fd, const char *who)
+{
+	int flags;
+
+	flags = fcntl(fd, F_GETFL);
+	if (flags < 0)
+		log_err("fio: %s failed to get file flags: %s\n", who, strerror(errno));
+	else {
+		flags |= O_NONBLOCK;
+		flags = fcntl(fd, F_SETFL, flags);
+		if (flags < 0)
+			log_err("fio: %s failed to get file flags: %s\n", who, strerror(errno));
+	}
+}
+
 static int endian_check(void)
 {
 	union {
diff --git a/memory.c b/memory.c
index b208320..8c06d94 100644
--- a/memory.c
+++ b/memory.c
@@ -158,9 +158,10 @@ static int alloc_mem_mmap(struct thread_data *td, size_t total_mem)
 	if (td->orig_buffer == MAP_FAILED) {
 		td_verror(td, errno, "mmap");
 		td->orig_buffer = NULL;
-		if (td->mmapfd) {
+		if (td->mmapfd != 1) {
 			close(td->mmapfd);
-			unlink(td->o.mmapfile);
+			if (td->o.mmapfile)
+				unlink(td->o.mmapfile);
 		}
 
 		return 1;
diff --git a/options.c b/options.c
index 9096a32..50af7b4 100644
--- a/options.c
+++ b/options.c
@@ -269,7 +269,7 @@ static int ignore_error_type(struct thread_data *td, int etype, char *str)
 		} else {
 			error[i] = atoi(fname);
 			if (error[i] < 0)
-				error[i] = error[i];
+				error[i] = -error[i];
 		}
 		if (!error[i]) {
 			log_err("Unknown error %s, please use number value \n",
diff --git a/os/windows/posix/include/sys/un.h b/os/windows/posix/include/sys/un.h
index b9ea630..e418c6d 100644
--- a/os/windows/posix/include/sys/un.h
+++ b/os/windows/posix/include/sys/un.h
@@ -7,7 +7,7 @@ typedef int in_port_t;
  struct sockaddr_un
  {
 	sa_family_t	sun_family; /* Address family */
-	char		sun_path[]; /* Socket pathname */
+	char		sun_path[260]; /* Socket pathname */
 };
 
 #endif /* SYS_UN_H */
diff --git a/parse.c b/parse.c
index 83c59f7..188f728 100644
--- a/parse.c
+++ b/parse.c
@@ -624,7 +624,7 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data,
 			ret = 1;
 			for (i = 0; i < PARSE_MAX_VP; i++) {
 				vp = &posval[i];
-				if (!vp->ival || vp->ival[0] == '\0')
+				if (!vp->ival || vp->ival[0] == '\0' || !cp)
 					continue;
 				all_skipped = 0;
 				if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) {
diff --git a/server.c b/server.c
index 3346445..077dce5 100644
--- a/server.c
+++ b/server.c
@@ -4,7 +4,6 @@
 #include <unistd.h>
 #include <limits.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sys/poll.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -68,7 +67,7 @@ static const char *fio_server_ops[FIO_NET_CMD_NR] = {
 	"DISK_UTIL",
 	"SERVER_START",
 	"ADD_JOB",
-	"CMD_RUN"
+	"CMD_RUN",
 	"CMD_IOLOG",
 };
 
@@ -209,7 +208,7 @@ static int verify_convert_cmd(struct fio_net_cmd *cmd)
  */
 struct fio_net_cmd *fio_net_recv_cmd(int sk)
 {
-	struct fio_net_cmd cmd, *cmdret = NULL;
+	struct fio_net_cmd cmd, *tmp, *cmdret = NULL;
 	size_t cmd_size = 0, pdu_offset = 0;
 	uint16_t crc;
 	int ret, first = 1;
@@ -232,7 +231,19 @@ struct fio_net_cmd *fio_net_recv_cmd(int sk)
 		} else
 			cmd_size += cmd.pdu_len;
 
-		cmdret = realloc(cmdret, cmd_size);
+		if (cmd_size / 1024 > FIO_SERVER_MAX_CMD_MB * 1024) {
+			log_err("fio: cmd+pdu too large (%llu)\n", (unsigned long long) cmd_size);
+			ret = 1;
+			break;
+		}
+
+		tmp = realloc(cmdret, cmd_size);
+		if (!tmp) {
+			log_err("fio: server failed allocating cmd\n");
+			ret = 1;
+			break;
+		}
+		cmdret = tmp;
 
 		if (first)
 			memcpy(cmdret, &cmd, sizeof(cmd));
@@ -843,14 +854,12 @@ static int accept_loop(int listen_sk)
 	struct sockaddr_in6 addr6;
 	socklen_t len = use_ipv6 ? sizeof(addr6) : sizeof(addr);
 	struct pollfd pfd;
-	int ret = 0, sk, flags, exitval = 0;
+	int ret = 0, sk, exitval = 0;
 	FLIST_HEAD(conn_list);
 
 	dprint(FD_NET, "server enter accept loop\n");
 
-	flags = fcntl(listen_sk, F_GETFL);
-	flags |= O_NONBLOCK;
-	fcntl(listen_sk, F_SETFL, flags);
+	fio_set_fd_nonblocking(listen_sk, "server");
 
 	while (!exit_backend) {
 		const char *from;
@@ -1095,7 +1104,8 @@ static void convert_dus(struct disk_util_stat *dst, struct disk_util_stat *src)
 {
 	int i;
 
-	strcpy((char *) dst->name, (char *) src->name);
+	dst->name[FIO_DU_NAME_SZ - 1] = '\0';
+	strncpy((char *) dst->name, (char *) src->name, FIO_DU_NAME_SZ - 1);
 
 	for (i = 0; i < 2; i++) {
 		dst->s.ios[i]		= cpu_to_le32(src->s.ios[i]);
@@ -1215,7 +1225,9 @@ int fio_send_iolog(struct thread_data *td, struct io_log *log, const char *name)
 	pdu.nr_samples = __cpu_to_le32(log->nr_samples);
 	pdu.log_type = cpu_to_le32(log->log_type);
 	pdu.compressed = cpu_to_le32(use_zlib);
-	strcpy((char *) pdu.name, name);
+
+	strncpy((char *) pdu.name, name, FIO_NET_NAME_MAX);
+	pdu.name[FIO_NET_NAME_MAX - 1] = '\0';
 
 	for (i = 0; i < log->nr_samples; i++) {
 		struct io_sample *s = &log->log[i];
@@ -1338,7 +1350,7 @@ static int fio_init_server_sock(void)
 
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_UNIX;
-	strcpy(addr.sun_path, bind_sock);
+	strncpy(addr.sun_path, bind_sock, sizeof(addr.sun_path) - 1);
 
 	len = sizeof(addr.sun_family) + strlen(bind_sock) + 1;
 
@@ -1367,6 +1379,8 @@ static int fio_init_server_connection(void)
 	if (sk < 0)
 		return sk;
 
+	memset(bind_str, 0, sizeof(bind_str));
+
 	if (!bind_sock) {
 		char *p, port[16];
 		const void *src;
@@ -1386,9 +1400,9 @@ static int fio_init_server_connection(void)
 		if (p)
 			strcat(p, port);
 		else
-			strcpy(bind_str, port);
+			strncpy(bind_str, port, sizeof(bind_str) - 1);
 	} else
-		strcpy(bind_str, bind_sock);
+		strncpy(bind_str, bind_sock, sizeof(bind_str) - 1);
 
 	log_info("fio: server listening on %s\n", bind_str);
 
diff --git a/server.h b/server.h
index 3a279f0..2958e73 100644
--- a/server.h
+++ b/server.h
@@ -41,6 +41,7 @@ enum {
 	FIO_SERVER_VER			= 33,
 
 	FIO_SERVER_MAX_FRAGMENT_PDU	= 1024,
+	FIO_SERVER_MAX_CMD_MB		= 2048,
 
 	FIO_NET_CMD_QUIT		= 1,
 	FIO_NET_CMD_EXIT		= 2,
diff --git a/stat.c b/stat.c
index 509c6f0..fbf0118 100644
--- a/stat.c
+++ b/stat.c
@@ -831,7 +831,7 @@ static void show_thread_status_terse_v2(struct thread_stat *ts,
 	log_info("\n");
 
 	/* Additional output if description is set */
-	if (ts->description)
+	if (strlen(ts->description))
 		log_info(";%s", ts->description);
 
 	log_info("\n");
@@ -1471,7 +1471,12 @@ void show_running_run_stats(void)
 	fio_mutex_down(stat_mutex);
 
 	if (!pthread_create(&thread, NULL, __show_running_run_stats, NULL)) {
-		pthread_detach(thread);
+		int err;
+
+		err = pthread_detach(thread);
+		if (err)
+			log_err("fio: DU thread detach failed: %s\n", strerror(err));
+
 		return;
 	}
 
@@ -1494,8 +1499,11 @@ static int check_status_file(void)
 		return 0;
 
 	temp_dir = getenv("TMPDIR");
-	if (temp_dir == NULL)
+	if (temp_dir == NULL) {
 		temp_dir = getenv("TEMP");
+		if (temp_dir && strlen(temp_dir) >= PATH_MAX)
+			temp_dir = NULL;
+	}
 	if (temp_dir == NULL)
 		temp_dir = "/tmp";
 
@@ -1800,7 +1808,11 @@ void add_bw_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs,
 		if (!delta)
 			continue; /* No entries for interval */
 
-		rate = delta * 1000 / spent / 1024;
+		if (spent)
+			rate = delta * 1000 / spent / 1024;
+		else
+			rate = 0;
+
 		add_stat_sample(&ts->bw_stat[ddir], rate);
 
 		if (td->bw_log)
@@ -1835,7 +1847,11 @@ void add_iops_sample(struct thread_data *td, enum fio_ddir ddir, unsigned int bs
 		if (!delta)
 			continue; /* No entries for interval */
 
-		iops = (delta * 1000) / spent;
+		if (spent)
+			iops = (delta * 1000) / spent;
+		else
+			iops = 0;
+
 		add_stat_sample(&ts->iops_stat[ddir], iops);
 
 		if (td->iops_log)
diff --git a/verify.c b/verify.c
index 9eb532a..282a8cf 100644
--- a/verify.c
+++ b/verify.c
@@ -226,16 +226,32 @@ struct vcont {
 	unsigned int crc_len;
 };
 
+#define DUMP_BUF_SZ	255
+static int dump_buf_warned;
+
 static void dump_buf(char *buf, unsigned int len, unsigned long long offset,
 		     const char *type, struct fio_file *f)
 {
-	char *ptr, fname[256];
+	char *ptr, fname[DUMP_BUF_SZ];
+	size_t buf_left = DUMP_BUF_SZ;
 	int ret, fd;
 
 	ptr = strdup(f->file_name);
-	strcpy(fname, basename(ptr));
 
-	sprintf(fname + strlen(fname), ".%llu.%s", offset, type);
+	fname[DUMP_BUF_SZ - 1] = '\0';
+	strncpy(fname, basename(ptr), DUMP_BUF_SZ - 1);
+
+	buf_left -= strlen(fname);
+	if (buf_left <= 0) {
+		if (!dump_buf_warned) {
+			log_err("fio: verify failure dump buffer too small\n");
+			dump_buf_warned = 1;
+		}
+		free(ptr);
+		return;
+	}
+
+	snprintf(fname + strlen(fname), buf_left, ".%llu.%s", offset, type);
 
 	fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0644);
 	if (fd < 0) {
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux