Commit c2c0b4c5434c0a25f7f7796b29155d53805909f5

Authored by Maciej Sosnowski
Committed by David S. Miller
1 parent c3d4f44f50

[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: Maciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 6 additions and 11 deletions Side-by-side Diff

drivers/dma/iovlock.c
... ... @@ -55,7 +55,6 @@
55 55 int nr_iovecs = 0;
56 56 int iovec_len_used = 0;
57 57 int iovec_pages_used = 0;
58   - long err;
59 58  
60 59 /* don't pin down non-user-based iovecs */
61 60 if (segment_eq(get_fs(), KERNEL_DS))
62 61  
63 62  
64 63  
65 64  
... ... @@ -72,23 +71,21 @@
72 71 local_list = kmalloc(sizeof(*local_list)
73 72 + (nr_iovecs * sizeof (struct dma_page_list))
74 73 + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL);
75   - if (!local_list) {
76   - err = -ENOMEM;
  74 + if (!local_list)
77 75 goto out;
78   - }
79 76  
80 77 /* list of pages starts right after the page list array */
81 78 pages = (struct page **) &local_list->page_list[nr_iovecs];
82 79  
  80 + local_list->nr_iovecs = 0;
  81 +
83 82 for (i = 0; i < nr_iovecs; i++) {
84 83 struct dma_page_list *page_list = &local_list->page_list[i];
85 84  
86 85 len -= iov[i].iov_len;
87 86  
88   - if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) {
89   - err = -EFAULT;
  87 + if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len))
90 88 goto unpin;
91   - }
92 89  
93 90 page_list->nr_pages = num_pages_spanned(&iov[i]);
94 91 page_list->base_address = iov[i].iov_base;
95 92  
... ... @@ -109,10 +106,8 @@
109 106 NULL);
110 107 up_read(&current->mm->mmap_sem);
111 108  
112   - if (ret != page_list->nr_pages) {
113   - err = -ENOMEM;
  109 + if (ret != page_list->nr_pages)
114 110 goto unpin;
115   - }
116 111  
117 112 local_list->nr_iovecs = i + 1;
118 113 }
... ... @@ -122,7 +117,7 @@
122 117 unpin:
123 118 dma_unpin_iovec_pages(local_list);
124 119 out:
125   - return ERR_PTR(err);
  120 + return NULL;
126 121 }
127 122  
128 123 void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list)