diff options
Diffstat (limited to 'net/ceph/pagevec.c')
| -rw-r--r-- | net/ceph/pagevec.c | 18 | 
1 files changed, 13 insertions, 5 deletions
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index 1a040e64c69..cd9c21df87d 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c @@ -16,22 +16,30 @@ struct page **ceph_get_direct_page_vector(const char __user *data,  					  int num_pages, bool write_page)  {  	struct page **pages; -	int rc; +	int got = 0; +	int rc = 0;  	pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS);  	if (!pages)  		return ERR_PTR(-ENOMEM);  	down_read(¤t->mm->mmap_sem); -	rc = get_user_pages(current, current->mm, (unsigned long)data, -			    num_pages, write_page, 0, pages, NULL); +	while (got < num_pages) { +		rc = get_user_pages(current, current->mm, +		    (unsigned long)data + ((unsigned long)got * PAGE_SIZE), +		    num_pages - got, write_page, 0, pages + got, NULL); +		if (rc < 0) +			break; +		BUG_ON(rc == 0); +		got += rc; +	}  	up_read(¤t->mm->mmap_sem); -	if (rc < num_pages) +	if (rc < 0)  		goto fail;  	return pages;  fail: -	ceph_put_page_vector(pages, rc > 0 ? rc : 0, false); +	ceph_put_page_vector(pages, got, false);  	return ERR_PTR(rc);  }  EXPORT_SYMBOL(ceph_get_direct_page_vector);  |