Add support for specifying UID/GID

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/HOWTO b/HOWTO
index 0b40f75..45a96bb 100644
--- a/HOWTO
+++ b/HOWTO
@@ -1015,6 +1015,11 @@
 		the documentation that comes with the kernel, allowed values
 		are in the range of 100..1000.
 
+uid=int		Instead of running as the invoking user, set the user ID to
+		this value before the thread/process does any work.
+
+gid=int		Set group ID, see uid.
+
 6.0 Interpreting the output
 ---------------------------
 
diff --git a/fio.1 b/fio.1
index 2e0a283..dfca43e 100644
--- a/fio.1
+++ b/fio.1
@@ -735,6 +735,13 @@
 .BI cgroup_weight \fR=\fPint
 Set the weight of the cgroup to this value. See the documentation that comes
 with the kernel, allowed values are in the range of 100..1000.
+.TP
+.BI uid \fR=\fPint
+Instead of running as the invoking user, set the user ID to this value before
+the thread/process does any work.
+.TP
+.BI gid \fR=\fPint
+Set group ID, see \fBuid\fR.
 .SH OUTPUT
 While running, \fBfio\fR will display the status of the created jobs.  For
 example:
diff --git a/fio.c b/fio.c
index 7d4c96a..728addd 100644
--- a/fio.c
+++ b/fio.c
@@ -1041,6 +1041,15 @@
 	 */
 	fio_mutex_remove(td->mutex);
 
+	if (td->o.uid != -1U && setuid(td->o.uid)) {
+		td_verror(td, errno, "setuid");
+		goto err;
+	}
+	if (td->o.gid != -1U && setgid(td->o.gid)) {
+		td_verror(td, errno, "setgid");
+		goto err;
+	}
+
 	/*
 	 * May alter parameters that init_io_u() will use, so we need to
 	 * do this first.
diff --git a/fio.h b/fio.h
index b1af7b1..3b2dd6e 100644
--- a/fio.h
+++ b/fio.h
@@ -277,6 +277,9 @@
 	 */
 	char *cgroup;
 	unsigned int cgroup_weight;
+
+	unsigned int uid;
+	unsigned int gid;
 };
 
 #define FIO_VERROR_SIZE	128
diff --git a/init.c b/init.c
index 873a0ba..95c7efb 100644
--- a/init.c
+++ b/init.c
@@ -181,6 +181,8 @@
 	td = &threads[thread_number++];
 	*td = *parent;
 
+	td->o.uid = td->o.gid = -1U;
+
 	dup_files(td, parent);
 	options_mem_dupe(td);
 
diff --git a/options.c b/options.c
index 16908a0..f628062 100644
--- a/options.c
+++ b/options.c
@@ -1741,6 +1741,18 @@
 		.maxval	= 1000,
 	},
 	{
+		.name	= "uid",
+		.type	= FIO_OPT_INT,
+		.off1	= td_var_offset(uid),
+		.help	= "Run job with this user ID",
+	},
+	{
+		.name	= "gid",
+		.type	= FIO_OPT_INT,
+		.off1	= td_var_offset(gid),
+		.help	= "Run job with this group ID",
+	},
+	{
 		.name = NULL,
 	},
 };