ksmbd: reorganize ksmbd_iov_pin_rsp()
authorNamjae Jeon <linkinjeon@kernel.org>
Mon, 9 Oct 2023 14:57:20 +0000 (23:57 +0900)
committerSteve French <stfrench@microsoft.com>
Mon, 23 Oct 2023 00:06:27 +0000 (19:06 -0500)
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: e2b76ab8b5c9 ("ksmbd: add support for read compound")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/ksmbd_work.c

index 51def3ca74c018b4ba2de392888a86db6ad9db87..a2ed441e837ae44827ef59aae7313d8ec7779c99 100644 (file)
@@ -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;
@@ -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);
        }