aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-03-16 18:01:07 -0400
committerSage Weil <sage@newdream.net>2010-03-23 10:46:55 -0400
commit916623da10e270c7e9e802a7ddfe1ec8f890982d (patch)
tree892f703ce8a4200ab27b0c1db14f4c2057d7b2f3
parent15637c8b1251c38694c32214eba69b72a30e9d9b (diff)
ceph: only release unused caps with mds requests
We were releasing used caps (e.g. FILE_CACHE) from encode_inode_release with MDS requests (e.g. setattr). We don't carry refs on most caps, so this code worked most of the time, but for setattr (utimes) we try to drop Fscr. This causes cap state to get slightly out of sync with reality, and may result in subsequent mds revoke messages getting ignored. Fix by only releasing unused caps. Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--fs/ceph/caps.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index d9e860ff9f3a..7d0a0d0adc18 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2836,11 +2836,18 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
2836 struct ceph_cap *cap; 2836 struct ceph_cap *cap;
2837 struct ceph_mds_request_release *rel = *p; 2837 struct ceph_mds_request_release *rel = *p;
2838 int ret = 0; 2838 int ret = 0;
2839 2839 int used = 0;
2840 dout("encode_inode_release %p mds%d drop %s unless %s\n", inode,
2841 mds, ceph_cap_string(drop), ceph_cap_string(unless));
2842 2840
2843 spin_lock(&inode->i_lock); 2841 spin_lock(&inode->i_lock);
2842 used = __ceph_caps_used(ci);
2843
2844 dout("encode_inode_release %p mds%d used %s drop %s unless %s\n", inode,
2845 mds, ceph_cap_string(used), ceph_cap_string(drop),
2846 ceph_cap_string(unless));
2847
2848 /* only drop unused caps */
2849 drop &= ~used;
2850
2844 cap = __get_cap_for_mds(ci, mds); 2851 cap = __get_cap_for_mds(ci, mds);
2845 if (cap && __cap_is_valid(cap)) { 2852 if (cap && __cap_is_valid(cap)) {
2846 if (force || 2853 if (force ||