Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
ksmbd: reorganize ksmbd_iov_pin_rsp()
Browse files Browse the repository at this point in the history
[ Upstream commit 1819a90 ]

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: e2b76ab ("ksmbd: add support for read compound")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
namjaejeon authored and Sasha Levin committed Jan 1, 2024
1 parent abf5d27 commit 4a9f322
Showing 1 changed file with 22 additions and 21 deletions.
43 changes: 22 additions & 21 deletions fs/smb/server/ksmbd_work.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
unsigned int ib_len)
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 (work->iov_alloc_cnt <= work->iov_cnt) {
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 + need_iov_cnt) {
struct kvec *new;

work->iov_alloc_cnt += 4;
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down

0 comments on commit 4a9f322

Please sign in to comment.