Commit 2962507c authored by Sage Weil's avatar Sage Weil

ceph: perform lazy reads when file mode and caps permit

If the file mode is marked as "lazy," perform cached/buffered reads when
the caps permit it.  Adjust the rdcache_gen and invalidation logic
accordingly so that we manage our cache based on the FILE_CACHE -or-
FILE_LAZYIO cap bits.
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent 33caad32
...@@ -552,7 +552,7 @@ static void writepages_finish(struct ceph_osd_request *req, ...@@ -552,7 +552,7 @@ static void writepages_finish(struct ceph_osd_request *req,
* page truncation thread, possibly losing some data that * page truncation thread, possibly losing some data that
* raced its way in * raced its way in
*/ */
if ((issued & CEPH_CAP_FILE_CACHE) == 0) if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0)
generic_error_remove_page(inode->i_mapping, page); generic_error_remove_page(inode->i_mapping, page);
unlock_page(page); unlock_page(page);
......
...@@ -482,8 +482,8 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap, ...@@ -482,8 +482,8 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
* Each time we receive FILE_CACHE anew, we increment * Each time we receive FILE_CACHE anew, we increment
* i_rdcache_gen. * i_rdcache_gen.
*/ */
if ((issued & CEPH_CAP_FILE_CACHE) && if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
(had & CEPH_CAP_FILE_CACHE) == 0) (had & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0)
ci->i_rdcache_gen++; ci->i_rdcache_gen++;
/* /*
...@@ -1509,11 +1509,13 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, ...@@ -1509,11 +1509,13 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
ci->i_wrbuffer_ref == 0 && /* no dirty pages... */ ci->i_wrbuffer_ref == 0 && /* no dirty pages... */
ci->i_rdcache_gen && /* may have cached pages */ ci->i_rdcache_gen && /* may have cached pages */
(file_wanted == 0 || /* no open files */ (file_wanted == 0 || /* no open files */
(revoking & CEPH_CAP_FILE_CACHE)) && /* or revoking cache */ (revoking & (CEPH_CAP_FILE_CACHE|
CEPH_CAP_FILE_LAZYIO))) && /* or revoking cache */
!tried_invalidate) { !tried_invalidate) {
dout("check_caps trying to invalidate on %p\n", inode); dout("check_caps trying to invalidate on %p\n", inode);
if (try_nonblocking_invalidate(inode) < 0) { if (try_nonblocking_invalidate(inode) < 0) {
if (revoking & CEPH_CAP_FILE_CACHE) { if (revoking & (CEPH_CAP_FILE_CACHE|
CEPH_CAP_FILE_LAZYIO)) {
dout("check_caps queuing invalidate\n"); dout("check_caps queuing invalidate\n");
queue_invalidate = 1; queue_invalidate = 1;
ci->i_rdcache_revoking = ci->i_rdcache_gen; ci->i_rdcache_revoking = ci->i_rdcache_gen;
...@@ -2276,7 +2278,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, ...@@ -2276,7 +2278,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
* try to invalidate (once). (If there are dirty buffers, we * try to invalidate (once). (If there are dirty buffers, we
* will invalidate _after_ writeback.) * will invalidate _after_ writeback.)
*/ */
if (((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) && if (((cap->issued & ~newcaps) & (CEPH_CAP_FILE_CACHE|
CEPH_CAP_FILE_LAZYIO)) &&
!ci->i_wrbuffer_ref) { !ci->i_wrbuffer_ref) {
if (try_nonblocking_invalidate(inode) == 0) { if (try_nonblocking_invalidate(inode) == 0) {
revoked_rdcache = 1; revoked_rdcache = 1;
...@@ -2374,7 +2377,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, ...@@ -2374,7 +2377,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
writeback = 1; /* will delay ack */ writeback = 1; /* will delay ack */
else if (dirty & ~newcaps) else if (dirty & ~newcaps)
check_caps = 1; /* initiate writeback in check_caps */ check_caps = 1; /* initiate writeback in check_caps */
else if (((used & ~newcaps) & CEPH_CAP_FILE_CACHE) == 0 || else if (((used & ~newcaps) & (CEPH_CAP_FILE_CACHE|
CEPH_CAP_FILE_LAZYIO)) == 0 ||
revoked_rdcache) revoked_rdcache)
check_caps = 2; /* send revoke ack in check_caps */ check_caps = 2; /* send revoke ack in check_caps */
cap->issued = newcaps; cap->issued = newcaps;
......
...@@ -740,28 +740,32 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov, ...@@ -740,28 +740,32 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos) unsigned long nr_segs, loff_t pos)
{ {
struct file *filp = iocb->ki_filp; struct file *filp = iocb->ki_filp;
struct ceph_file_info *fi = filp->private_data;
loff_t *ppos = &iocb->ki_pos; loff_t *ppos = &iocb->ki_pos;
size_t len = iov->iov_len; size_t len = iov->iov_len;
struct inode *inode = filp->f_dentry->d_inode; struct inode *inode = filp->f_dentry->d_inode;
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
void *base = iov->iov_base; void *base = iov->iov_base;
ssize_t ret; ssize_t ret;
int got = 0; int want, got = 0;
int checkeof = 0, read = 0; int checkeof = 0, read = 0;
dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n", dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
inode, ceph_vinop(inode), pos, (unsigned)len, inode); inode, ceph_vinop(inode), pos, (unsigned)len, inode);
again: again:
__ceph_do_pending_vmtruncate(inode); __ceph_do_pending_vmtruncate(inode);
ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_CACHE, if (fi->fmode & CEPH_FILE_MODE_LAZY)
&got, -1); want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
else
want = CEPH_CAP_FILE_CACHE;
ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, &got, -1);
if (ret < 0) if (ret < 0)
goto out; goto out;
dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n", dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
inode, ceph_vinop(inode), pos, (unsigned)len, inode, ceph_vinop(inode), pos, (unsigned)len,
ceph_cap_string(got)); ceph_cap_string(got));
if ((got & CEPH_CAP_FILE_CACHE) == 0 || if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
(iocb->ki_filp->f_flags & O_DIRECT) || (iocb->ki_filp->f_flags & O_DIRECT) ||
(inode->i_sb->s_flags & MS_SYNCHRONOUS)) (inode->i_sb->s_flags & MS_SYNCHRONOUS))
/* hmm, this isn't really async... */ /* hmm, this isn't really async... */
......
...@@ -442,8 +442,9 @@ int ceph_fill_file_size(struct inode *inode, int issued, ...@@ -442,8 +442,9 @@ int ceph_fill_file_size(struct inode *inode, int issued,
* the file is either opened or mmaped * the file is either opened or mmaped
*/ */
if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_RD| if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_RD|
CEPH_CAP_FILE_WR|CEPH_CAP_FILE_BUFFER| CEPH_CAP_FILE_WR|CEPH_CAP_FILE_BUFFER|
CEPH_CAP_FILE_EXCL)) || CEPH_CAP_FILE_EXCL|
CEPH_CAP_FILE_LAZYIO)) ||
mapping_mapped(inode->i_mapping) || mapping_mapped(inode->i_mapping) ||
__ceph_caps_file_wanted(ci)) { __ceph_caps_file_wanted(ci)) {
ci->i_truncate_pending++; ci->i_truncate_pending++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment