aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-07-02 00:40:21 -0400
committerSage Weil <sage@inktank.com>2013-07-03 18:32:57 -0400
commit6ee6b95373dfa1d0a4c9bc76689ec10a60c1d6f2 (patch)
tree7173050cd5f444db41e62b5d1d6b813042dca0e1
parentb1530f57042297f85330a140a6921b6f95fe74d3 (diff)
ceph: fix race between cap issue and revoke
If we receive new caps from the auth MDS and the non-auth MDS is revoking the newly issued caps, we should release the caps from the non-auth MDS. The scenario is filelock's state changes from SYNC to LOCK. Non-auth MDS revokes Fc cap, the client gets Fc cap from the auth MDS at the same time. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com> Reviewed-by: Sage Weil <sage@inktank.com>
-rw-r--r--fs/ceph/caps.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 7045a8dfaad4..25442b40c25a 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -806,22 +806,28 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
806/* 806/*
807 * Return true if mask caps are currently being revoked by an MDS. 807 * Return true if mask caps are currently being revoked by an MDS.
808 */ 808 */
809int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) 809int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
810 struct ceph_cap *ocap, int mask)
810{ 811{
811 struct inode *inode = &ci->vfs_inode;
812 struct ceph_cap *cap; 812 struct ceph_cap *cap;
813 struct rb_node *p; 813 struct rb_node *p;
814 int ret = 0;
815 814
816 spin_lock(&ci->i_ceph_lock);
817 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { 815 for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
818 cap = rb_entry(p, struct ceph_cap, ci_node); 816 cap = rb_entry(p, struct ceph_cap, ci_node);
819 if (__cap_is_valid(cap) && 817 if (cap != ocap && __cap_is_valid(cap) &&
820 (cap->implemented & ~cap->issued & mask)) { 818 (cap->implemented & ~cap->issued & mask))
821 ret = 1; 819 return 1;
822 break;
823 }
824 } 820 }
821 return 0;
822}
823
824int ceph_caps_revoking(struct ceph_inode_info *ci, int mask)
825{
826 struct inode *inode = &ci->vfs_inode;
827 int ret;
828
829 spin_lock(&ci->i_ceph_lock);
830 ret = __ceph_caps_revoking_other(ci, NULL, mask);
825 spin_unlock(&ci->i_ceph_lock); 831 spin_unlock(&ci->i_ceph_lock);
826 dout("ceph_caps_revoking %p %s = %d\n", inode, 832 dout("ceph_caps_revoking %p %s = %d\n", inode,
827 ceph_cap_string(mask), ret); 833 ceph_cap_string(mask), ret);
@@ -2488,6 +2494,11 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
2488 } else { 2494 } else {
2489 dout("grant: %s -> %s\n", ceph_cap_string(cap->issued), 2495 dout("grant: %s -> %s\n", ceph_cap_string(cap->issued),
2490 ceph_cap_string(newcaps)); 2496 ceph_cap_string(newcaps));
2497 /* non-auth MDS is revoking the newly grant caps ? */
2498 if (cap == ci->i_auth_cap &&
2499 __ceph_caps_revoking_other(ci, cap, newcaps))
2500 check_caps = 2;
2501
2491 cap->issued = newcaps; 2502 cap->issued = newcaps;
2492 cap->implemented |= newcaps; /* add bits only, to 2503 cap->implemented |= newcaps; /* add bits only, to
2493 * avoid stepping on a 2504 * avoid stepping on a