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>
This commit is contained in:
parent
3d497d858a
commit
29065a513a
@ -409,7 +409,7 @@ static void zero_page_vector_range(int off, int len, struct page **pages)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
while (len >= PAGE_CACHE_SIZE) {
|
while (len >= PAGE_CACHE_SIZE) {
|
||||||
dout("zeroing %d %p\n", i, pages[i]);
|
dout("zeroing %d %p len=%d\n", i, pages[i], len);
|
||||||
zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
|
zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
|
||||||
len -= PAGE_CACHE_SIZE;
|
len -= PAGE_CACHE_SIZE;
|
||||||
i++;
|
i++;
|
||||||
@ -542,13 +542,16 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
|
|||||||
* but it will at least behave sensibly when they are
|
* but it will at least behave sensibly when they are
|
||||||
* in sequence.
|
* in sequence.
|
||||||
*/
|
*/
|
||||||
filemap_write_and_wait(inode->i_mapping);
|
|
||||||
} else {
|
} else {
|
||||||
pages = alloc_page_vector(num_pages);
|
pages = alloc_page_vector(num_pages);
|
||||||
}
|
}
|
||||||
if (IS_ERR(pages))
|
if (IS_ERR(pages))
|
||||||
return PTR_ERR(pages);
|
return PTR_ERR(pages);
|
||||||
|
|
||||||
|
ret = filemap_write_and_wait(inode->i_mapping);
|
||||||
|
if (ret < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
ret = striped_read(inode, off, len, pages, num_pages);
|
ret = striped_read(inode, off, len, pages, num_pages);
|
||||||
|
|
||||||
if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
|
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,
|
|||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
*poff = off + ret;
|
*poff = off + ret;
|
||||||
|
|
||||||
|
done:
|
||||||
if (file->f_flags & O_DIRECT)
|
if (file->f_flags & O_DIRECT)
|
||||||
put_page_vector(pages, num_pages);
|
put_page_vector(pages, num_pages);
|
||||||
else
|
else
|
||||||
@ -617,6 +621,16 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
|
|||||||
else
|
else
|
||||||
pos = *offset;
|
pos = *offset;
|
||||||
|
|
||||||
|
ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = invalidate_inode_pages2_range(inode->i_mapping,
|
||||||
|
pos >> PAGE_CACHE_SHIFT,
|
||||||
|
(pos + left) >> PAGE_CACHE_SHIFT);
|
||||||
|
if (ret < 0)
|
||||||
|
dout("invalidate_inode_pages2_range returned %d\n", ret);
|
||||||
|
|
||||||
flags = CEPH_OSD_FLAG_ORDERSNAP |
|
flags = CEPH_OSD_FLAG_ORDERSNAP |
|
||||||
CEPH_OSD_FLAG_ONDISK |
|
CEPH_OSD_FLAG_ONDISK |
|
||||||
CEPH_OSD_FLAG_WRITE;
|
CEPH_OSD_FLAG_WRITE;
|
||||||
|
Loading…
Reference in New Issue
Block a user