Commit 4c446029 authored by Jim Harris's avatar Jim Harris Committed by Jim Harris
Browse files

bdev_aio: apply RWF_NOWAIT flag for S_ISBLK() files



This ensures the reactor doesn't block if we've exceeded the number of
tags available on the queue.

We can now get -EAGAIN in the completion path. Translate these to
bdev ENOMEM status, instead of directly passing -EAGAIN to bdev layer.

Note that we can't use RWF_NOWAIT in all cases, so only try to use it
for block devices (using S_ISBLK).

Fixes issue #2868.

Signed-off-by: default avatarJim Harris <james.r.harris@intel.com>
Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I03c257a1a31048da10d6eb38f6b0f94beca5dd74
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16406


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
parent 6007401f
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ struct file_disk {
	struct spdk_bdev	disk;
	char			*filename;
	int			fd;
	bool			use_nowait;
	TAILQ_ENTRY(file_disk)  link;
	bool			block_size_override;
	bool			readonly;
@@ -113,6 +114,7 @@ bdev_aio_open(struct file_disk *disk)
{
	int fd;
	int io_flag = disk->readonly ? O_RDONLY : O_RDWR;
	struct stat st;

	fd = open(disk->filename, io_flag | O_DIRECT);
	if (fd < 0) {
@@ -127,6 +129,11 @@ bdev_aio_open(struct file_disk *disk)
	}

	disk->fd = fd;
	/* Some aio operations can block, for example if number outstanding
	 * I/O exceeds number of block layer tags. But not all files can
	 * support RWF_NOWAIT flag. So use RWF_NOWAIT on block devices only.
	 */
	disk->use_nowait = fstat(fd, &st) == 0 && S_ISBLK(st.st_mode);

	return 0;
}
@@ -198,6 +205,9 @@ bdev_aio_submit_io(enum spdk_bdev_io_type type, struct file_disk *fdisk,
		io_set_eventfd(iocb, aio_ch->group_ch->efd);
	}
	iocb->data = aio_task;
	if (fdisk->use_nowait) {
		iocb->aio_rw_flags = RWF_NOWAIT;
	}
	aio_task->len = nbytes;
	aio_task->ch = aio_ch;

@@ -450,11 +460,16 @@ bdev_aio_io_channel_poll(struct bdev_aio_io_channel *io_ch)
			 * But from libaio.h, io_event.res is defined unsigned long, so
			 * convert it to signed value for error detection.
			 */
			SPDK_ERRLOG("failed to complete aio: rc %"PRId64"\n", events[i].res);
			res = (int)events[i].res;
			if (res < 0) {
				if (res == -EAGAIN) {
					spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_NOMEM);
				} else {
					SPDK_ERRLOG("failed to complete aio: rc %"PRId64"\n", events[i].res);
					spdk_bdev_io_complete_aio_status(spdk_bdev_io_from_ctx(aio_task), res);
				}
			} else {
				SPDK_ERRLOG("failed to complete aio: rc %"PRId64"\n", events[i].res);
				spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_FAILED);
			}
		}