diff options
author | Yehuda Sadeh <yehuda@hq.newdream.net> | 2010-02-09 14:14:41 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-02-11 14:48:51 -0500 |
commit | 29065a513aa4c7e4b46b77cbcd25f814a4ca0bfe (patch) | |
tree | 74607baf067fe47a5eeeeb07257186fdd15de989 /fs | |
parent | 3d497d858ae6e5f23a28783030aecc69074e102d (diff) |
ceph: sync read/write considers page cache
In the cases where we either do a sync read or a write, we
need to make sure that everything in the page cache is flushed.
In the case of a sync write we invalidate the relevant pages,
so that subsequent read/write reflects the new data written.
Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/file.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 43bd2f2e51a5..bbf1ccf2d56e 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -409,7 +409,7 @@ static void zero_page_vector_range(int off, int len, struct page **pages) | |||
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 len=%d\n", i, pages[i], len); |
413 | zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE); | 413 | zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE); |
414 | len -= PAGE_CACHE_SIZE; | 414 | len -= PAGE_CACHE_SIZE; |
415 | i++; | 415 | i++; |
@@ -542,13 +542,16 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data, | |||
542 | * but it will at least behave sensibly when they are | 542 | * but it will at least behave sensibly when they are |
543 | * in sequence. | 543 | * in sequence. |
544 | */ | 544 | */ |
545 | filemap_write_and_wait(inode->i_mapping); | ||
546 | } else { | 545 | } else { |
547 | pages = alloc_page_vector(num_pages); | 546 | pages = alloc_page_vector(num_pages); |
548 | } | 547 | } |
549 | if (IS_ERR(pages)) | 548 | if (IS_ERR(pages)) |
550 | return PTR_ERR(pages); | 549 | return PTR_ERR(pages); |
551 | 550 | ||
551 | ret = filemap_write_and_wait(inode->i_mapping); | ||
552 | if (ret < 0) | ||
553 | goto done; | ||
554 | |||
552 | ret = striped_read(inode, off, len, pages, num_pages); | 555 | ret = striped_read(inode, off, len, pages, num_pages); |
553 | 556 | ||
554 | if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) | 557 | if (ret >= 0 && (file->f_flags & O_DIRECT) == 0) |
@@ -556,6 +559,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data, | |||
556 | if (ret >= 0) | 559 | if (ret >= 0) |
557 | *poff = off + ret; | 560 | *poff = off + ret; |
558 | 561 | ||
562 | done: | ||
559 | if (file->f_flags & O_DIRECT) | 563 | if (file->f_flags & O_DIRECT) |
560 | put_page_vector(pages, num_pages); | 564 | put_page_vector(pages, num_pages); |
561 | else | 565 | else |
@@ -617,6 +621,16 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, | |||
617 | else | 621 | else |
618 | pos = *offset; | 622 | pos = *offset; |
619 | 623 | ||
624 | ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left); | ||
625 | if (ret < 0) | ||
626 | return ret; | ||
627 | |||
628 | ret = invalidate_inode_pages2_range(inode->i_mapping, | ||
629 | pos >> PAGE_CACHE_SHIFT, | ||
630 | (pos + left) >> PAGE_CACHE_SHIFT); | ||
631 | if (ret < 0) | ||
632 | dout("invalidate_inode_pages2_range returned %d\n", ret); | ||
633 | |||
620 | flags = CEPH_OSD_FLAG_ORDERSNAP | | 634 | flags = CEPH_OSD_FLAG_ORDERSNAP | |
621 | CEPH_OSD_FLAG_ONDISK | | 635 | CEPH_OSD_FLAG_ONDISK | |
622 | CEPH_OSD_FLAG_WRITE; | 636 | CEPH_OSD_FLAG_WRITE; |