diff options
-rw-r--r-- | fs/ceph/file.c | 46 | ||||
-rw-r--r-- | include/linux/ceph/libceph.h | 2 | ||||
-rw-r--r-- | net/ceph/pagevec.c | 35 |
3 files changed, 22 insertions, 61 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index c9a24ba98c9a..672b0fedb17b 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -418,7 +418,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i, | |||
418 | struct page **pages; | 418 | struct page **pages; |
419 | u64 off = iocb->ki_pos; | 419 | u64 off = iocb->ki_pos; |
420 | int num_pages, ret; | 420 | int num_pages, ret; |
421 | size_t len = i->count; | 421 | size_t len = iov_iter_count(i); |
422 | 422 | ||
423 | dout("sync_read on file %p %llu~%u %s\n", file, off, | 423 | dout("sync_read on file %p %llu~%u %s\n", file, off, |
424 | (unsigned)len, | 424 | (unsigned)len, |
@@ -436,25 +436,26 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i, | |||
436 | 436 | ||
437 | if (file->f_flags & O_DIRECT) { | 437 | if (file->f_flags & O_DIRECT) { |
438 | while (iov_iter_count(i)) { | 438 | while (iov_iter_count(i)) { |
439 | void __user *data = i->iov[0].iov_base + i->iov_offset; | 439 | size_t start; |
440 | size_t len = i->iov[0].iov_len - i->iov_offset; | 440 | ssize_t n; |
441 | 441 | ||
442 | num_pages = calc_pages_for((unsigned long)data, len); | 442 | n = iov_iter_get_pages_alloc(i, &pages, INT_MAX, &start); |
443 | pages = ceph_get_direct_page_vector(data, | 443 | if (n < 0) |
444 | num_pages, true); | 444 | return n; |
445 | if (IS_ERR(pages)) | ||
446 | return PTR_ERR(pages); | ||
447 | 445 | ||
448 | ret = striped_read(inode, off, len, | 446 | num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE; |
447 | |||
448 | ret = striped_read(inode, off, n, | ||
449 | pages, num_pages, checkeof, | 449 | pages, num_pages, checkeof, |
450 | 1, (unsigned long)data & ~PAGE_MASK); | 450 | 1, start); |
451 | |||
451 | ceph_put_page_vector(pages, num_pages, true); | 452 | ceph_put_page_vector(pages, num_pages, true); |
452 | 453 | ||
453 | if (ret <= 0) | 454 | if (ret <= 0) |
454 | break; | 455 | break; |
455 | off += ret; | 456 | off += ret; |
456 | iov_iter_advance(i, ret); | 457 | iov_iter_advance(i, ret); |
457 | if (ret < len) | 458 | if (ret < n) |
458 | break; | 459 | break; |
459 | } | 460 | } |
460 | } else { | 461 | } else { |
@@ -466,25 +467,14 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i, | |||
466 | num_pages, checkeof, 0, 0); | 467 | num_pages, checkeof, 0, 0); |
467 | if (ret > 0) { | 468 | if (ret > 0) { |
468 | int l, k = 0; | 469 | int l, k = 0; |
469 | size_t left = len = ret; | 470 | size_t left = ret; |
470 | 471 | ||
471 | while (left) { | 472 | while (left) { |
472 | void __user *data = i->iov[0].iov_base | 473 | int copy = min_t(size_t, PAGE_SIZE, left); |
473 | + i->iov_offset; | 474 | l = copy_page_to_iter(pages[k++], 0, copy, i); |
474 | l = min(i->iov[0].iov_len - i->iov_offset, | 475 | off += l; |
475 | left); | 476 | left -= l; |
476 | 477 | if (l < copy) | |
477 | ret = ceph_copy_page_vector_to_user(&pages[k], | ||
478 | data, off, | ||
479 | l); | ||
480 | if (ret > 0) { | ||
481 | iov_iter_advance(i, ret); | ||
482 | left -= ret; | ||
483 | off += ret; | ||
484 | k = calc_pages_for(iocb->ki_pos, | ||
485 | len - left + 1) - 1; | ||
486 | BUG_ON(k >= num_pages && left); | ||
487 | } else | ||
488 | break; | 478 | break; |
489 | } | 479 | } |
490 | } | 480 | } |
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 2f49aa4c4f7f..279b0afac1c1 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h | |||
@@ -222,8 +222,6 @@ extern void ceph_copy_to_page_vector(struct page **pages, | |||
222 | extern void ceph_copy_from_page_vector(struct page **pages, | 222 | extern void ceph_copy_from_page_vector(struct page **pages, |
223 | void *data, | 223 | void *data, |
224 | loff_t off, size_t len); | 224 | loff_t off, size_t len); |
225 | extern int ceph_copy_page_vector_to_user(struct page **pages, void __user *data, | ||
226 | loff_t off, size_t len); | ||
227 | extern void ceph_zero_page_vector_range(int off, int len, struct page **pages); | 225 | extern void ceph_zero_page_vector_range(int off, int len, struct page **pages); |
228 | 226 | ||
229 | 227 | ||
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index 815a2249cfa9..555013034f7a 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c | |||
@@ -53,7 +53,10 @@ void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty) | |||
53 | set_page_dirty_lock(pages[i]); | 53 | set_page_dirty_lock(pages[i]); |
54 | put_page(pages[i]); | 54 | put_page(pages[i]); |
55 | } | 55 | } |
56 | kfree(pages); | 56 | if (is_vmalloc_addr(pages)) |
57 | vfree(pages); | ||
58 | else | ||
59 | kfree(pages); | ||
57 | } | 60 | } |
58 | EXPORT_SYMBOL(ceph_put_page_vector); | 61 | EXPORT_SYMBOL(ceph_put_page_vector); |
59 | 62 | ||
@@ -165,36 +168,6 @@ void ceph_copy_from_page_vector(struct page **pages, | |||
165 | EXPORT_SYMBOL(ceph_copy_from_page_vector); | 168 | EXPORT_SYMBOL(ceph_copy_from_page_vector); |
166 | 169 | ||
167 | /* | 170 | /* |
168 | * copy user data from a page vector into a user pointer | ||
169 | */ | ||
170 | int ceph_copy_page_vector_to_user(struct page **pages, | ||
171 | void __user *data, | ||
172 | loff_t off, size_t len) | ||
173 | { | ||
174 | int i = 0; | ||
175 | int po = off & ~PAGE_CACHE_MASK; | ||
176 | int left = len; | ||
177 | int l, bad; | ||
178 | |||
179 | while (left > 0) { | ||
180 | l = min_t(int, left, PAGE_CACHE_SIZE-po); | ||
181 | bad = copy_to_user(data, page_address(pages[i]) + po, l); | ||
182 | if (bad == l) | ||
183 | return -EFAULT; | ||
184 | data += l - bad; | ||
185 | left -= l - bad; | ||
186 | if (po) { | ||
187 | po += l - bad; | ||
188 | if (po == PAGE_CACHE_SIZE) | ||
189 | po = 0; | ||
190 | } | ||
191 | i++; | ||
192 | } | ||
193 | return len; | ||
194 | } | ||
195 | EXPORT_SYMBOL(ceph_copy_page_vector_to_user); | ||
196 | |||
197 | /* | ||
198 | * Zero an extent within a page vector. Offset is relative to the | 171 | * Zero an extent within a page vector. Offset is relative to the |
199 | * start of the first page. | 172 | * start of the first page. |
200 | */ | 173 | */ |