summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-03-16 15:01:07 -0700
committerSage Weil <sage@newdream.net>2010-03-23 07:46:55 -0700
commit916623da10e270c7e9e802a7ddfe1ec8f890982d (patch)
tree892f703ce8a4200ab27b0c1db14f4c2057d7b2f3
parent15637c8b1251c38694c32214eba69b72a30e9d9b (diff)
downloadop-kernel-dev-916623da10e270c7e9e802a7ddfe1ec8f890982d.zip
op-kernel-dev-916623da10e270c7e9e802a7ddfe1ec8f890982d.tar.gz
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 d9e860f..7d0a0d0 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,
struct ceph_cap *cap;
struct ceph_mds_request_release *rel = *p;
int ret = 0;
-
- dout("encode_inode_release %p mds%d drop %s unless %s\n", inode,
- mds, ceph_cap_string(drop), ceph_cap_string(unless));
+ int used = 0;
spin_lock(&inode->i_lock);
+ used = __ceph_caps_used(ci);
+
+ dout("encode_inode_release %p mds%d used %s drop %s unless %s\n", inode,
+ mds, ceph_cap_string(used), ceph_cap_string(drop),
+ ceph_cap_string(unless));
+
+ /* only drop unused caps */
+ drop &= ~used;
+
cap = __get_cap_for_mds(ci, mds);
if (cap && __cap_is_valid(cap)) {
if (force ||
OpenPOWER on IntegriCloud