diff options
author | Yehuda Sadeh <yehuda@hq.newdream.net> | 2010-02-04 16:41:41 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-02-11 14:48:49 -0500 |
commit | 972f0d3ab1a15cb5d790dd8c53903066084b28f2 (patch) | |
tree | 42d47841a5bee10cea81c8e1eb44b6bc4f1f942e /fs/ceph/file.c | |
parent | 02f90c61096ec3ad691e808a4aa7ca5a06e550ec (diff) |
ceph: fix short synchronous reads
Zeroing of holes was not done correctly: page_off was miscalculated and
zeroing the tail didn't not adjust the 'read' value to include the zeroed
portion.
Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r-- | fs/ceph/file.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 2d88c805a56c..43bd2f2e51a5 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -395,23 +395,22 @@ static void zero_page_vector_range(int off, int len, struct page **pages) | |||
395 | { | 395 | { |
396 | int i = off >> PAGE_CACHE_SHIFT; | 396 | int i = off >> PAGE_CACHE_SHIFT; |
397 | 397 | ||
398 | off &= ~PAGE_CACHE_MASK; | ||
399 | |||
398 | dout("zero_page_vector_page %u~%u\n", off, len); | 400 | dout("zero_page_vector_page %u~%u\n", off, len); |
399 | BUG_ON(len < PAGE_CACHE_SIZE); | ||
400 | 401 | ||
401 | /* leading partial page? */ | 402 | /* leading partial page? */ |
402 | if (off & ~PAGE_CACHE_MASK) { | 403 | if (off) { |
404 | int end = min((int)PAGE_CACHE_SIZE, off + len); | ||
403 | dout("zeroing %d %p head from %d\n", i, pages[i], | 405 | dout("zeroing %d %p head from %d\n", i, pages[i], |
404 | (int)(off & ~PAGE_CACHE_MASK)); | 406 | (int)off); |
405 | zero_user_segment(pages[i], off & ~PAGE_CACHE_MASK, | 407 | zero_user_segment(pages[i], off, end); |
406 | PAGE_CACHE_SIZE); | 408 | len -= (end - off); |
407 | off += PAGE_CACHE_SIZE; | ||
408 | off &= PAGE_CACHE_MASK; | ||
409 | i++; | 409 | i++; |
410 | } | 410 | } |
411 | while (len >= PAGE_CACHE_SIZE) { | 411 | while (len >= PAGE_CACHE_SIZE) { |
412 | dout("zeroing %d %p\n", i, pages[i]); | 412 | dout("zeroing %d %p\n", i, pages[i]); |
413 | zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE); | 413 | zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE); |
414 | off += PAGE_CACHE_SIZE; | ||
415 | len -= PAGE_CACHE_SIZE; | 414 | len -= PAGE_CACHE_SIZE; |
416 | i++; | 415 | i++; |
417 | } | 416 | } |
@@ -437,7 +436,7 @@ static int striped_read(struct inode *inode, | |||
437 | struct ceph_client *client = ceph_inode_to_client(inode); | 436 | struct ceph_client *client = ceph_inode_to_client(inode); |
438 | struct ceph_inode_info *ci = ceph_inode(inode); | 437 | struct ceph_inode_info *ci = ceph_inode(inode); |
439 | u64 pos, this_len; | 438 | u64 pos, this_len; |
440 | int page_off = off & ~PAGE_CACHE_SIZE; /* first byte's offset in page */ | 439 | int page_off = off & ~PAGE_CACHE_MASK; /* first byte's offset in page */ |
441 | int left, pages_left; | 440 | int left, pages_left; |
442 | int read; | 441 | int read; |
443 | struct page **page_pos; | 442 | struct page **page_pos; |
@@ -493,6 +492,7 @@ more: | |||
493 | dout("zero tail\n"); | 492 | dout("zero tail\n"); |
494 | zero_page_vector_range(page_off + read, len - read, | 493 | zero_page_vector_range(page_off + read, len - read, |
495 | pages); | 494 | pages); |
495 | read = len; | ||
496 | goto out; | 496 | goto out; |
497 | } | 497 | } |
498 | 498 | ||