mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 23:32:14 +00:00
new helper: iov_iter_get_pages_alloc()
same as iov_iter_get_pages(), except that pages array is allocated (kmalloc if possible, vmalloc if that fails) and left for caller to free. Lustre and NFS ->direct_IO() switched to it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
f67da30c1d
commit
91f79c43d1
4 changed files with 168 additions and 258 deletions
|
@ -1,6 +1,8 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
||||
struct iov_iter *i)
|
||||
|
@ -263,6 +265,44 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
|
|||
}
|
||||
EXPORT_SYMBOL(iov_iter_get_pages);
|
||||
|
||||
ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
|
||||
struct page ***pages, size_t maxsize,
|
||||
size_t *start)
|
||||
{
|
||||
size_t offset = i->iov_offset;
|
||||
const struct iovec *iov = i->iov;
|
||||
size_t len;
|
||||
unsigned long addr;
|
||||
void *p;
|
||||
int n;
|
||||
int res;
|
||||
|
||||
len = iov->iov_len - offset;
|
||||
if (len > i->count)
|
||||
len = i->count;
|
||||
if (len > maxsize)
|
||||
len = maxsize;
|
||||
addr = (unsigned long)iov->iov_base + offset;
|
||||
len += *start = addr & (PAGE_SIZE - 1);
|
||||
addr &= ~(PAGE_SIZE - 1);
|
||||
n = (len + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
p = kmalloc(n * sizeof(struct page *), GFP_KERNEL);
|
||||
if (!p)
|
||||
p = vmalloc(n * sizeof(struct page *));
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, p);
|
||||
if (unlikely(res < 0)) {
|
||||
kvfree(p);
|
||||
return res;
|
||||
}
|
||||
*pages = p;
|
||||
return (res == n ? len : res * PAGE_SIZE) - *start;
|
||||
}
|
||||
EXPORT_SYMBOL(iov_iter_get_pages_alloc);
|
||||
|
||||
int iov_iter_npages(const struct iov_iter *i, int maxpages)
|
||||
{
|
||||
size_t offset = i->iov_offset;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue