Commit c2c0b4c5 authored by Maciej Sosnowski's avatar Maciej Sosnowski Committed by David S. Miller

[2/4] I/OAT: fix dma_pin_iovec_pages() error handling

Error handling needs to be modified in dma_pin_iovec_pages().
It should return NULL instead of ERR_PTR
(pinned_list is checked for NULL in tcp_recvmsg() to determine
if iovec pages have been successfully pinned down).
In case of error for the first iovec,
local_list->nr_iovecs needs to be initialized.

Cc: <stable@kernel.org>
Signed-off-by: default avatarMaciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c3d4f44f
...@@ -55,7 +55,6 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) ...@@ -55,7 +55,6 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len)
int nr_iovecs = 0; int nr_iovecs = 0;
int iovec_len_used = 0; int iovec_len_used = 0;
int iovec_pages_used = 0; int iovec_pages_used = 0;
long err;
/* don't pin down non-user-based iovecs */ /* don't pin down non-user-based iovecs */
if (segment_eq(get_fs(), KERNEL_DS)) if (segment_eq(get_fs(), KERNEL_DS))
...@@ -72,23 +71,21 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) ...@@ -72,23 +71,21 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len)
local_list = kmalloc(sizeof(*local_list) local_list = kmalloc(sizeof(*local_list)
+ (nr_iovecs * sizeof (struct dma_page_list)) + (nr_iovecs * sizeof (struct dma_page_list))
+ (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL);
if (!local_list) { if (!local_list)
err = -ENOMEM;
goto out; goto out;
}
/* list of pages starts right after the page list array */ /* list of pages starts right after the page list array */
pages = (struct page **) &local_list->page_list[nr_iovecs]; pages = (struct page **) &local_list->page_list[nr_iovecs];
local_list->nr_iovecs = 0;
for (i = 0; i < nr_iovecs; i++) { for (i = 0; i < nr_iovecs; i++) {
struct dma_page_list *page_list = &local_list->page_list[i]; struct dma_page_list *page_list = &local_list->page_list[i];
len -= iov[i].iov_len; len -= iov[i].iov_len;
if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) { if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len))
err = -EFAULT;
goto unpin; goto unpin;
}
page_list->nr_pages = num_pages_spanned(&iov[i]); page_list->nr_pages = num_pages_spanned(&iov[i]);
page_list->base_address = iov[i].iov_base; page_list->base_address = iov[i].iov_base;
...@@ -109,10 +106,8 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) ...@@ -109,10 +106,8 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len)
NULL); NULL);
up_read(&current->mm->mmap_sem); up_read(&current->mm->mmap_sem);
if (ret != page_list->nr_pages) { if (ret != page_list->nr_pages)
err = -ENOMEM;
goto unpin; goto unpin;
}
local_list->nr_iovecs = i + 1; local_list->nr_iovecs = i + 1;
} }
...@@ -122,7 +117,7 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) ...@@ -122,7 +117,7 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len)
unpin: unpin:
dma_unpin_iovec_pages(local_list); dma_unpin_iovec_pages(local_list);
out: out:
return ERR_PTR(err); return NULL;
} }
void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment