Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
+10 −6
Original line number Diff line number Diff line
@@ -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 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
	    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;
+8 −4
Original line number Diff line number Diff line
@@ -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... */
+3 −2
Original line number Diff line number Diff line
@@ -443,7 +443,8 @@ int ceph_fill_file_size(struct inode *inode, int issued,
			 */
			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_EXCL|
				       CEPH_CAP_FILE_LAZYIO)) ||
			    mapping_mapped(inode->i_mapping) ||
			    __ceph_caps_file_wanted(ci)) {
				ci->i_truncate_pending++;