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

Commit d3d0720d authored by Henry C Chang's avatar Henry C Chang Committed by Sage Weil
Browse files

ceph: do not use i_wrbuffer_ref as refcount for Fb cap



We increments i_wrbuffer_ref when taking the Fb cap. This breaks
the dirty page accounting and causes looping in
__ceph_do_pending_vmtruncate, and ceph client hangs.

This bug can be reproduced occasionally by running blogbench.

Add a new field i_wb_ref to inode and dedicate it to Fb reference
counting.

Signed-off-by: default avatarHenry C Chang <henry.cy.chang@gmail.com>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent a26a185d
Loading
Loading
Loading
Loading
+8 −8
Original line number Original line Diff line number Diff line
@@ -819,7 +819,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci)
		used |= CEPH_CAP_FILE_CACHE;
		used |= CEPH_CAP_FILE_CACHE;
	if (ci->i_wr_ref)
	if (ci->i_wr_ref)
		used |= CEPH_CAP_FILE_WR;
		used |= CEPH_CAP_FILE_WR;
	if (ci->i_wrbuffer_ref)
	if (ci->i_wb_ref || ci->i_wrbuffer_ref)
		used |= CEPH_CAP_FILE_BUFFER;
		used |= CEPH_CAP_FILE_BUFFER;
	return used;
	return used;
}
}
@@ -1990,11 +1990,11 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got)
	if (got & CEPH_CAP_FILE_WR)
	if (got & CEPH_CAP_FILE_WR)
		ci->i_wr_ref++;
		ci->i_wr_ref++;
	if (got & CEPH_CAP_FILE_BUFFER) {
	if (got & CEPH_CAP_FILE_BUFFER) {
		if (ci->i_wrbuffer_ref == 0)
		if (ci->i_wb_ref == 0)
			ihold(&ci->vfs_inode);
			ihold(&ci->vfs_inode);
		ci->i_wrbuffer_ref++;
		ci->i_wb_ref++;
		dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n",
		dout("__take_cap_refs %p wb %d -> %d (?)\n",
		     &ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref);
		     &ci->vfs_inode, ci->i_wb_ref-1, ci->i_wb_ref);
	}
	}
}
}


@@ -2169,12 +2169,12 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had)
		if (--ci->i_rdcache_ref == 0)
		if (--ci->i_rdcache_ref == 0)
			last++;
			last++;
	if (had & CEPH_CAP_FILE_BUFFER) {
	if (had & CEPH_CAP_FILE_BUFFER) {
		if (--ci->i_wrbuffer_ref == 0) {
		if (--ci->i_wb_ref == 0) {
			last++;
			last++;
			put++;
			put++;
		}
		}
		dout("put_cap_refs %p wrbuffer %d -> %d (?)\n",
		dout("put_cap_refs %p wb %d -> %d (?)\n",
		     inode, ci->i_wrbuffer_ref+1, ci->i_wrbuffer_ref);
		     inode, ci->i_wb_ref+1, ci->i_wb_ref);
	}
	}
	if (had & CEPH_CAP_FILE_WR)
	if (had & CEPH_CAP_FILE_WR)
		if (--ci->i_wr_ref == 0) {
		if (--ci->i_wr_ref == 0) {
+1 −0
Original line number Original line Diff line number Diff line
@@ -355,6 +355,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
	ci->i_rd_ref = 0;
	ci->i_rd_ref = 0;
	ci->i_rdcache_ref = 0;
	ci->i_rdcache_ref = 0;
	ci->i_wr_ref = 0;
	ci->i_wr_ref = 0;
	ci->i_wb_ref = 0;
	ci->i_wrbuffer_ref = 0;
	ci->i_wrbuffer_ref = 0;
	ci->i_wrbuffer_ref_head = 0;
	ci->i_wrbuffer_ref_head = 0;
	ci->i_shared_gen = 0;
	ci->i_shared_gen = 0;
+1 −1
Original line number Original line Diff line number Diff line
@@ -293,7 +293,7 @@ struct ceph_inode_info {


	/* held references to caps */
	/* held references to caps */
	int i_pin_ref;
	int i_pin_ref;
	int i_rd_ref, i_rdcache_ref, i_wr_ref;
	int i_rd_ref, i_rdcache_ref, i_wr_ref, i_wb_ref;
	int i_wrbuffer_ref, i_wrbuffer_ref_head;
	int i_wrbuffer_ref, i_wrbuffer_ref_head;
	u32 i_shared_gen;       /* increment each time we get FILE_SHARED */
	u32 i_shared_gen;       /* increment each time we get FILE_SHARED */
	u32 i_rdcache_gen;      /* incremented each time we get FILE_CACHE. */
	u32 i_rdcache_gen;      /* incremented each time we get FILE_CACHE. */