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: Sage Weil <sage@newdream.net>
This commit is contained in:
parent
33caad324b
commit
2962507ca2
|
@ -552,7 +552,7 @@ static void writepages_finish(struct ceph_osd_request *req,
|
|||
* page truncation thread, possibly losing some data that
|
||||
* 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);
|
||||
|
||||
unlock_page(page);
|
||||
|
|
|
@ -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
|
||||
* i_rdcache_gen.
|
||||
*/
|
||||
if ((issued & CEPH_CAP_FILE_CACHE) &&
|
||||
(had & CEPH_CAP_FILE_CACHE) == 0)
|
||||
if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
|
||||
(had & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0)
|
||||
ci->i_rdcache_gen++;
|
||||
|
||||
/*
|
||||
|
@ -1509,11 +1509,13 @@ retry_locked:
|
|||
ci->i_wrbuffer_ref == 0 && /* no dirty pages... */
|
||||
ci->i_rdcache_gen && /* may have cached pages */
|
||||
(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) {
|
||||
dout("check_caps trying to invalidate on %p\n", inode);
|
||||
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");
|
||||
queue_invalidate = 1;
|
||||
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,
|
|||
* try to invalidate (once). (If there are dirty buffers, we
|
||||
* 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) {
|
||||
if (try_nonblocking_invalidate(inode) == 0) {
|
||||
revoked_rdcache = 1;
|
||||
|
@ -2374,7 +2377,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
|
|||
writeback = 1; /* will delay ack */
|
||||
else if (dirty & ~newcaps)
|
||||
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)
|
||||
check_caps = 2; /* send revoke ack in check_caps */
|
||||
cap->issued = newcaps;
|
||||
|
|
|
@ -740,28 +740,32 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
|||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
struct file *filp = iocb->ki_filp;
|
||||
struct ceph_file_info *fi = filp->private_data;
|
||||
loff_t *ppos = &iocb->ki_pos;
|
||||
size_t len = iov->iov_len;
|
||||
struct inode *inode = filp->f_dentry->d_inode;
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
void *base = iov->iov_base;
|
||||
ssize_t ret;
|
||||
int got = 0;
|
||||
int want, got = 0;
|
||||
int checkeof = 0, read = 0;
|
||||
|
||||
dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
|
||||
inode, ceph_vinop(inode), pos, (unsigned)len, inode);
|
||||
again:
|
||||
__ceph_do_pending_vmtruncate(inode);
|
||||
ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_CACHE,
|
||||
&got, -1);
|
||||
if (fi->fmode & CEPH_FILE_MODE_LAZY)
|
||||
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)
|
||||
goto out;
|
||||
dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
|
||||
inode, ceph_vinop(inode), pos, (unsigned)len,
|
||||
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) ||
|
||||
(inode->i_sb->s_flags & MS_SYNCHRONOUS))
|
||||
/* hmm, this isn't really async... */
|
||||
|
|
|
@ -442,8 +442,9 @@ int ceph_fill_file_size(struct inode *inode, int issued,
|
|||
* the file is either opened or mmaped
|
||||
*/
|
||||
if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_RD|
|
||||
CEPH_CAP_FILE_WR|CEPH_CAP_FILE_BUFFER|
|
||||
CEPH_CAP_FILE_EXCL)) ||
|
||||
CEPH_CAP_FILE_WR|CEPH_CAP_FILE_BUFFER|
|
||||
CEPH_CAP_FILE_EXCL|
|
||||
CEPH_CAP_FILE_LAZYIO)) ||
|
||||
mapping_mapped(inode->i_mapping) ||
|
||||
__ceph_caps_file_wanted(ci)) {
|
||||
ci->i_truncate_pending++;
|
||||
|
|
Loading…
Reference in New Issue