瀏覽代碼

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>
Sage Weil 15 年之前
父節點
當前提交
916623da10
共有 1 個文件被更改,包括 10 次插入3 次删除
  1. 10 3
      fs/ceph/caps.c

+ 10 - 3
fs/ceph/caps.c

@@ -2836,11 +2836,18 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
 	struct ceph_cap *cap;
 	struct ceph_cap *cap;
 	struct ceph_mds_request_release *rel = *p;
 	struct ceph_mds_request_release *rel = *p;
 	int ret = 0;
 	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);
 	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);
 	cap = __get_cap_for_mds(ci, mds);
 	if (cap && __cap_is_valid(cap)) {
 	if (cap && __cap_is_valid(cap)) {
 		if (force ||
 		if (force ||