Commit f0d3699a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'io_uring-6.12-20241101' of git://git.kernel.dk/linux

Pull io_uring fix from Jens Axboe:

 - Fix not honoring IOCB_NOWAIT for starting buffered writes in terms of
   calling sb_start_write(), leading to a deadlock if someone is
   attempting to freeze the file system with writes in progress, as each
   side will end up waiting for the other to make progress.

* tag 'io_uring-6.12-20241101' of git://git.kernel.dk/linux:
  io_uring/rw: fix missing NOWAIT check for O_DIRECT start write
parents c4264568 1d60d74e
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -1014,6 +1014,25 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
	return IOU_OK;
}

static bool io_kiocb_start_write(struct io_kiocb *req, struct kiocb *kiocb)
{
	struct inode *inode;
	bool ret;

	if (!(req->flags & REQ_F_ISREG))
		return true;
	if (!(kiocb->ki_flags & IOCB_NOWAIT)) {
		kiocb_start_write(kiocb);
		return true;
	}

	inode = file_inode(kiocb->ki_filp);
	ret = sb_start_write_trylock(inode->i_sb);
	if (ret)
		__sb_writers_release(inode->i_sb, SB_FREEZE_WRITE);
	return ret;
}

int io_write(struct io_kiocb *req, unsigned int issue_flags)
{
	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
@@ -1051,8 +1070,8 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
	if (unlikely(ret))
		return ret;

	if (req->flags & REQ_F_ISREG)
		kiocb_start_write(kiocb);
	if (unlikely(!io_kiocb_start_write(req, kiocb)))
		return -EAGAIN;
	kiocb->ki_flags |= IOCB_WRITE;

	if (likely(req->file->f_op->write_iter))