Commit eb1f031c authored by Maciej Szwed's avatar Maciej Szwed Committed by Tomasz Zawadzki
Browse files

spdk_dd: Add posix flags support



Signed-off-by: default avatarMaciej Szwed <maciej.szwed@intel.com>
Change-Id: Ie051a399af6dea694faa942a412844c267500d2e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3060


Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
parent dcd2a253
Loading
Loading
Loading
Loading
+116 −6
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@
struct spdk_dd_opts {
	char		*input_file;
	char		*output_file;
	char		*input_file_flags;
	char		*output_file_flags;
	char		*input_bdev;
	char		*output_bdev;
	uint64_t	input_offset;
@@ -119,6 +121,24 @@ struct dd_job {
	uint64_t		copy_size;
};

struct dd_flags {
	char *name;
	int flag;
};

static struct dd_flags g_flags[] = {
	{"append", O_APPEND},
	{"direct", O_DIRECT},
	{"directory", O_DIRECTORY},
	{"dsync", O_DSYNC},
	{"noatime", O_NOATIME},
	{"noctty", O_NOCTTY},
	{"nofollow", O_NOFOLLOW},
	{"nonblock", O_NONBLOCK},
	{"sync", O_SYNC},
	{NULL, 0}
};

static struct dd_job g_job = {};
static int g_error = 0;
static struct timespec g_start_time;
@@ -489,14 +509,19 @@ dd_output_poll(void *ctx)
}

static int
dd_open_file(struct dd_target *target, const char *fname, uint64_t skip_blocks, bool input)
dd_open_file(struct dd_target *target, const char *fname, int flags, uint64_t skip_blocks,
	     bool input)
{
	int flags = O_RDWR;
	flags |= O_RDWR;

	if (input == false) {
	if (input == false && ((flags & O_DIRECTORY) == 0)) {
		flags |= O_CREAT;
	}

	if (input == false && ((flags & O_APPEND) == 0)) {
		flags |= O_TRUNC;
	}

	target->type = DD_TARGET_TYPE_FILE;
	target->u.aio.fd = open(fname, flags, 0600);
	if (target->u.aio.fd < 0) {
@@ -565,15 +590,48 @@ static void dd_finish(void)
	g_interrupt = true;
}

static int
parse_flags(char *file_flags)
{
	char *input_flag;
	int flags = 0;
	int i;
	bool found = false;

	/* Translate input flags to file open flags */
	while ((input_flag = strsep(&file_flags, ","))) {
		for (i = 0; g_flags[i].name != NULL; i++) {
			if (!strcmp(input_flag, g_flags[i].name)) {
				flags |= g_flags[i].flag;
				found = true;
				break;
			}
		}

		if (found == false) {
			SPDK_ERRLOG("Unknown file flag: %s\n", input_flag);
			return -EINVAL;
		}

		found = false;
	}

	return flags;
}

static void
dd_run(void *arg1)
{
	uint64_t write_size;
	uint32_t i;
	int rc;
	int rc, flags = 0;

	if (g_opts.input_file) {
		if (dd_open_file(&g_job.input, g_opts.input_file, g_opts.input_offset, true) < 0) {
		if (g_opts.input_file_flags) {
			flags = parse_flags(g_opts.input_file_flags);
		}

		if (dd_open_file(&g_job.input, g_opts.input_file, flags, g_opts.input_offset, true) < 0) {
			SPDK_ERRLOG("%s: %s\n", g_opts.input_file, strerror(errno));
			dd_exit(-errno);
			return;
@@ -617,7 +675,13 @@ dd_run(void *arg1)
	g_job.output.pos = g_opts.output_offset * g_opts.io_unit_size;

	if (g_opts.output_file) {
		if (dd_open_file(&g_job.output, g_opts.output_file, g_opts.output_offset, false) < 0) {
		flags = 0;

		if (g_opts.output_file_flags) {
			flags = parse_flags(g_opts.output_file_flags);
		}

		if (dd_open_file(&g_job.output, g_opts.output_file, flags, g_opts.output_offset, false) < 0) {
			SPDK_ERRLOG("%s: %s\n", g_opts.output_file, strerror(errno));
			dd_exit(-errno);
			return;
@@ -681,6 +745,8 @@ dd_run(void *arg1)
enum dd_cmdline_opts {
	DD_OPTION_IF = 0x1000,
	DD_OPTION_OF,
	DD_OPTION_IFLAGS,
	DD_OPTION_OFLAGS,
	DD_OPTION_IB,
	DD_OPTION_OB,
	DD_OPTION_SKIP,
@@ -703,6 +769,18 @@ static struct option g_cmdline_opts[] = {
		.flag = NULL,
		.val = DD_OPTION_OF,
	},
	{
		.name = "iflag",
		.has_arg = 1,
		.flag = NULL,
		.val = DD_OPTION_IFLAGS,
	},
	{
		.name = "oflag",
		.has_arg = 1,
		.flag = NULL,
		.val = DD_OPTION_OFLAGS,
	},
	{
		.name = "ib",
		.has_arg = 1,
@@ -758,11 +836,23 @@ usage(void)
	printf(" --ib Input bdev. Must specifier either --if or --ib\n");
	printf(" --of Output file. Must specify either --of or --ob.\n");
	printf(" --ob Output bdev. Must specify either --of or --ob.\n");
	printf(" --iflag Input file flags.\n");
	printf(" --oflag Onput file flags.\n");
	printf(" --bs I/O unit size (default: %" PRId64 ")\n", g_opts.io_unit_size);
	printf(" --qd Queue depth (default: %d)\n", g_opts.queue_depth);
	printf(" --count I/O unit count. The number of I/O units to copy. (default: all)\n");
	printf(" --skip Skip this many I/O units at start of input. (default: 0)\n");
	printf(" --seek Skip this many I/O units at start of output. (default: 0)\n");
	printf(" Available iflag and oflag values:\n");
	printf("  append - append mode\n");
	printf("  direct - use direct I/O for data\n");
	printf("  directory - fail unless a directory\n");
	printf("  dsync - use synchronized I/O for data\n");
	printf("  noatime - do not update access time\n");
	printf("  noctty - do not assign controlling terminal from file\n");
	printf("  nofollow - do not follow symlinks\n");
	printf("  nonblock - use non-blocking I/O\n");
	printf("  sync - use synchronized I/O for data and metadata\n");
}

static int
@@ -775,6 +865,12 @@ parse_args(int argc, char *argv)
	case DD_OPTION_OF:
		g_opts.output_file = strdup(argv);
		break;
	case DD_OPTION_IFLAGS:
		g_opts.input_file_flags = strdup(argv);
		break;
	case DD_OPTION_OFLAGS:
		g_opts.output_file_flags = strdup(argv);
		break;
	case DD_OPTION_IB:
		g_opts.input_bdev = strdup(argv);
		break;
@@ -812,6 +908,8 @@ dd_free(void)
	free(g_opts.output_file);
	free(g_opts.input_bdev);
	free(g_opts.output_bdev);
	free(g_opts.input_file_flags);
	free(g_opts.output_file_flags);

	if (g_job.ios) {
		for (i = 0; i < g_opts.queue_depth; i++) {
@@ -875,6 +973,18 @@ main(int argc, char **argv)
		goto end;
	}

	if (g_opts.output_file == NULL && g_opts.output_file_flags != NULL) {
		SPDK_ERRLOG("--oflags may be used only with --of\n");
		rc = EINVAL;
		goto end;
	}

	if (g_opts.input_file == NULL && g_opts.input_file_flags != NULL) {
		SPDK_ERRLOG("--iflags may be used only with --if\n");
		rc = EINVAL;
		goto end;
	}

	rc = spdk_app_start(&opts, dd_run, NULL);
	if (rc) {
		SPDK_ERRLOG("Error occured while performing copy\n");