diff options
author | Sage Weil <sage@newdream.net> | 2010-11-04 14:05:05 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-11-08 10:29:05 -0500 |
commit | cd045cb42a266882ac24bc21a3a8d03683c72954 (patch) | |
tree | 2938560e8362804e829cc9feb23ef746d354140b /fs | |
parent | feb4cc9bb433bf1491ac5ffbba133f3258dacf06 (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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/caps.c | 4 | ||||
-rw-r--r-- | fs/ceph/inode.c | 16 | ||||
-rw-r--r-- | fs/ceph/super.h | 4 |
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 */ |