Commit a929fa04 authored by yidong0635's avatar yidong0635 Committed by Tomasz Zawadzki
Browse files

spdk_dd: Fix SEGV on the error path.



We can see this app using dd_exit to cleanup.
Some error cases:
spdk_bdev_get_io_channel failed for -ENOMEM,
or it results in dd_open_bdev failed and then
dd_exit.

For a bdev, dd_exit does cleanup using spdk_put_io_channel.
And spdk_put_io_channel allows `ch == NULL`.
This causes SEGV.

So here add a separate function to check ch, and put
cleanup together.

This is found by xnvme pre-test.

Signed-off-by: default avataryidong0635 <dongx.yi@intel.com>
Change-Id: I9dd860da250a86f52139e69c690dd257a7ff7717
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14195


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarKrzysztof Karas <krzysztof.karas@intel.com>
parent 43c5293e
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -144,6 +144,19 @@ static bool g_interrupt;

static void dd_target_populate_buffer(struct dd_io *io);

static void
dd_cleanup_bdev(struct dd_target io)
{
	/* This can be only on the error path.
	 * To prevent the SEGV, need add checks here.
	 */
	if (io.u.bdev.ch) {
		spdk_put_io_channel(io.u.bdev.ch);
	}

	spdk_bdev_close(io.u.bdev.desc);
}

static void
dd_exit(int rc)
{
@@ -157,8 +170,7 @@ dd_exit(int rc)
			close(g_job.input.u.aio.fd);
		}
	} else if (g_job.input.type == DD_TARGET_TYPE_BDEV && g_job.input.open) {
		spdk_put_io_channel(g_job.input.u.bdev.ch);
		spdk_bdev_close(g_job.input.u.bdev.desc);
		dd_cleanup_bdev(g_job.input);
	}

	if (g_job.output.type == DD_TARGET_TYPE_FILE) {
@@ -171,8 +183,7 @@ dd_exit(int rc)
			close(g_job.output.u.aio.fd);
		}
	} else if (g_job.output.type == DD_TARGET_TYPE_BDEV && g_job.output.open) {
		spdk_put_io_channel(g_job.output.u.bdev.ch);
		spdk_bdev_close(g_job.output.u.bdev.desc);
		dd_cleanup_bdev(g_job.output);
	}

	if (g_job.input.type == DD_TARGET_TYPE_FILE || g_job.output.type == DD_TARGET_TYPE_FILE) {