aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-11-04 14:05:05 -0400
committerSage Weil <sage@newdream.net>2010-11-08 10:29:05 -0500
commitcd045cb42a266882ac24bc21a3a8d03683c72954 (patch)
tree2938560e8362804e829cc9feb23ef746d354140b
parentfeb4cc9bb433bf1491ac5ffbba133f3258dacf06 (diff)
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>
-rw-r--r--fs/ceph/caps.c4
-rw-r--r--fs/ceph/inode.c16
-rw-r--r--fs/ceph/super.h4
3 files changed, 10 insertions, 14 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 04b207b0c842..60d27bc9eb83 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1430,8 +1430,8 @@ static int try_nonblocking_invalidate(struct inode *inode)
1430 invalidating_gen == ci->i_rdcache_gen) { 1430 invalidating_gen == ci->i_rdcache_gen) {
1431 /* success. */ 1431 /* success. */
1432 dout("try_nonblocking_invalidate %p success\n", inode); 1432 dout("try_nonblocking_invalidate %p success\n", inode);
1433 ci->i_rdcache_gen = 0; 1433 /* save any racing async invalidate some trouble */
1434 ci->i_rdcache_revoking = 0; 1434 ci->i_rdcache_revoking = ci->i_rdcache_gen - 1;
1435 return 0; 1435 return 0;
1436 } 1436 }
1437 dout("try_nonblocking_invalidate %p failed\n", inode); 1437 dout("try_nonblocking_invalidate %p failed\n", inode);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 0a49ffde5bcb..5a9f907b805e 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1394,11 +1394,8 @@ static void ceph_invalidate_work(struct work_struct *work)
1394 spin_lock(&inode->i_lock); 1394 spin_lock(&inode->i_lock);
1395 dout("invalidate_pages %p gen %d revoking %d\n", inode, 1395 dout("invalidate_pages %p gen %d revoking %d\n", inode,
1396 ci->i_rdcache_gen, ci->i_rdcache_revoking); 1396 ci->i_rdcache_gen, ci->i_rdcache_revoking);
1397 if (ci->i_rdcache_gen == 0 || 1397 if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
1398 ci->i_rdcache_revoking != ci->i_rdcache_gen) {
1399 BUG_ON(ci->i_rdcache_revoking > ci->i_rdcache_gen);
1400 /* nevermind! */ 1398 /* nevermind! */
1401 ci->i_rdcache_revoking = 0;
1402 spin_unlock(&inode->i_lock); 1399 spin_unlock(&inode->i_lock);
1403 goto out; 1400 goto out;
1404 } 1401 }
@@ -1408,15 +1405,16 @@ static void ceph_invalidate_work(struct work_struct *work)
1408 ceph_invalidate_nondirty_pages(inode->i_mapping); 1405 ceph_invalidate_nondirty_pages(inode->i_mapping);
1409 1406
1410 spin_lock(&inode->i_lock); 1407 spin_lock(&inode->i_lock);
1411 if (orig_gen == ci->i_rdcache_gen) { 1408 if (orig_gen == ci->i_rdcache_gen &&
1409 orig_gen == ci->i_rdcache_revoking) {
1412 dout("invalidate_pages %p gen %d successful\n", inode, 1410 dout("invalidate_pages %p gen %d successful\n", inode,
1413 ci->i_rdcache_gen); 1411 ci->i_rdcache_gen);
1414 ci->i_rdcache_gen = 0; 1412 ci->i_rdcache_revoking--;
1415 ci->i_rdcache_revoking = 0;
1416 check = 1; 1413 check = 1;
1417 } else { 1414 } else {
1418 dout("invalidate_pages %p gen %d raced, gen now %d\n", 1415 dout("invalidate_pages %p gen %d raced, now %d revoking %d\n",
1419 inode, orig_gen, ci->i_rdcache_gen); 1416 inode, orig_gen, ci->i_rdcache_gen,
1417 ci->i_rdcache_revoking);
1420 } 1418 }
1421 spin_unlock(&inode->i_lock); 1419 spin_unlock(&inode->i_lock);
1422 1420
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 1886294e12f7..7f01728a4657 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -293,9 +293,7 @@ struct ceph_inode_info {
293 int i_rd_ref, i_rdcache_ref, i_wr_ref; 293 int i_rd_ref, i_rdcache_ref, i_wr_ref;
294 int i_wrbuffer_ref, i_wrbuffer_ref_head; 294 int i_wrbuffer_ref, i_wrbuffer_ref_head;
295 u32 i_shared_gen; /* increment each time we get FILE_SHARED */ 295 u32 i_shared_gen; /* increment each time we get FILE_SHARED */
296 u32 i_rdcache_gen; /* we increment this each time we get 296 u32 i_rdcache_gen; /* incremented each time we get FILE_CACHE. */
297 FILE_CACHE. If it's non-zero, we
298 _may_ have cached pages. */
299 u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */ 297 u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */
300 298
301 struct list_head i_unsafe_writes; /* uncommitted sync writes */ 299 struct list_head i_unsafe_writes; /* uncommitted sync writes */