ceph: fix rdcache_gen usage and invalidate
We used to use rdcache_gen to indicate whether we "might" have cached pages. Now we just look at the mapping to determine that. However, some old behavior remains from that transition. First, rdcache_gen == 0 no longer means we have no pages. That can happen at any time (presumably when we carry FILE_CACHE). We should not reset it to zero, and we should not check that it is zero. That means that the only purpose for rdcache_revoking is to resolve races between new issues of FILE_CACHE and an async invalidate. If they are equal, we should invalidate. On success, we decrement rdcache_revoking, so that it is no longer equal to rdcache_gen. Similarly, if we success in doing a sync invalidate, set revoking = gen - 1. (This is a small optimization to avoid doing unnecessary invalidate work and does not affect correctness.) Signed-off-by: Sage Weil <sage@newdream.net>
This commit is contained in:
@@ -1430,8 +1430,8 @@ static int try_nonblocking_invalidate(struct inode *inode)
|
|||||||
invalidating_gen == ci->i_rdcache_gen) {
|
invalidating_gen == ci->i_rdcache_gen) {
|
||||||
/* success. */
|
/* success. */
|
||||||
dout("try_nonblocking_invalidate %p success\n", inode);
|
dout("try_nonblocking_invalidate %p success\n", inode);
|
||||||
ci->i_rdcache_gen = 0;
|
/* save any racing async invalidate some trouble */
|
||||||
ci->i_rdcache_revoking = 0;
|
ci->i_rdcache_revoking = ci->i_rdcache_gen - 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dout("try_nonblocking_invalidate %p failed\n", inode);
|
dout("try_nonblocking_invalidate %p failed\n", inode);
|
||||||
|
@@ -1394,11 +1394,8 @@ static void ceph_invalidate_work(struct work_struct *work)
|
|||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
dout("invalidate_pages %p gen %d revoking %d\n", inode,
|
dout("invalidate_pages %p gen %d revoking %d\n", inode,
|
||||||
ci->i_rdcache_gen, ci->i_rdcache_revoking);
|
ci->i_rdcache_gen, ci->i_rdcache_revoking);
|
||||||
if (ci->i_rdcache_gen == 0 ||
|
if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
|
||||||
ci->i_rdcache_revoking != ci->i_rdcache_gen) {
|
|
||||||
BUG_ON(ci->i_rdcache_revoking > ci->i_rdcache_gen);
|
|
||||||
/* nevermind! */
|
/* nevermind! */
|
||||||
ci->i_rdcache_revoking = 0;
|
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1408,15 +1405,16 @@ static void ceph_invalidate_work(struct work_struct *work)
|
|||||||
ceph_invalidate_nondirty_pages(inode->i_mapping);
|
ceph_invalidate_nondirty_pages(inode->i_mapping);
|
||||||
|
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
if (orig_gen == ci->i_rdcache_gen) {
|
if (orig_gen == ci->i_rdcache_gen &&
|
||||||
|
orig_gen == ci->i_rdcache_revoking) {
|
||||||
dout("invalidate_pages %p gen %d successful\n", inode,
|
dout("invalidate_pages %p gen %d successful\n", inode,
|
||||||
ci->i_rdcache_gen);
|
ci->i_rdcache_gen);
|
||||||
ci->i_rdcache_gen = 0;
|
ci->i_rdcache_revoking--;
|
||||||
ci->i_rdcache_revoking = 0;
|
|
||||||
check = 1;
|
check = 1;
|
||||||
} else {
|
} else {
|
||||||
dout("invalidate_pages %p gen %d raced, gen now %d\n",
|
dout("invalidate_pages %p gen %d raced, now %d revoking %d\n",
|
||||||
inode, orig_gen, ci->i_rdcache_gen);
|
inode, orig_gen, ci->i_rdcache_gen,
|
||||||
|
ci->i_rdcache_revoking);
|
||||||
}
|
}
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
|
|
||||||
|
@@ -293,9 +293,7 @@ struct ceph_inode_info {
|
|||||||
int i_rd_ref, i_rdcache_ref, i_wr_ref;
|
int i_rd_ref, i_rdcache_ref, i_wr_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; /* we increment this each time we get
|
u32 i_rdcache_gen; /* incremented each time we get FILE_CACHE. */
|
||||||
FILE_CACHE. If it's non-zero, we
|
|
||||||
_may_ have cached pages. */
|
|
||||||
u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */
|
u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */
|
||||||
|
|
||||||
struct list_head i_unsafe_writes; /* uncommitted sync writes */
|
struct list_head i_unsafe_writes; /* uncommitted sync writes */
|
||||||
|
Reference in New Issue
Block a user