Commit 1819a904 authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French
Browse files

ksmbd: reorganize ksmbd_iov_pin_rsp()



If ksmbd_iov_pin_rsp fail, io vertor should be rollback.
This patch moves memory allocations to before setting the io vector
to avoid rollbacks.

Fixes: e2b76ab8 ("ksmbd: add support for read compound")
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent eacc655e
Loading
Loading
Loading
Loading
+22 −21
Original line number Diff line number Diff line
@@ -95,11 +95,28 @@ bool ksmbd_queue_work(struct ksmbd_work *work)
	return queue_work(ksmbd_wq, &work->work);
}

static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib,
static inline void __ksmbd_iov_pin(struct ksmbd_work *work, void *ib,
				   unsigned int ib_len)
{
	work->iov[++work->iov_idx].iov_base = ib;
	work->iov[work->iov_idx].iov_len = ib_len;
	work->iov_cnt++;
}

static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
			       void *aux_buf, unsigned int aux_size)
{
	struct aux_read *ar;
	int need_iov_cnt = 1;

	if (aux_size) {
		need_iov_cnt++;
		ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
		if (!ar)
			return -ENOMEM;
	}

	if (work->iov_alloc_cnt <= work->iov_cnt) {
	if (work->iov_alloc_cnt < work->iov_cnt + need_iov_cnt) {
		struct kvec *new;

		work->iov_alloc_cnt += 4;
@@ -111,16 +128,6 @@ static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib,
		work->iov = new;
	}

	work->iov[++work->iov_idx].iov_base = ib;
	work->iov[work->iov_idx].iov_len = ib_len;
	work->iov_cnt++;

	return 0;
}

static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
			       void *aux_buf, unsigned int aux_size)
{
	/* Plus rfc_length size on first iov */
	if (!work->iov_idx) {
		work->iov[work->iov_idx].iov_base = work->response_buf;
@@ -129,19 +136,13 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
		work->iov_cnt++;
	}

	ksmbd_realloc_iov_pin(work, ib, len);
	__ksmbd_iov_pin(work, ib, len);
	inc_rfc1001_len(work->iov[0].iov_base, len);

	if (aux_size) {
		struct aux_read *ar;

		ksmbd_realloc_iov_pin(work, aux_buf, aux_size);
		__ksmbd_iov_pin(work, aux_buf, aux_size);
		inc_rfc1001_len(work->iov[0].iov_base, aux_size);

		ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
		if (!ar)
			return -ENOMEM;

		ar->buf = aux_buf;
		list_add(&ar->entry, &work->aux_read_list);
	}