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>
This commit is contained in:
Yan, Zheng 2013-07-02 12:40:21 +08:00 committed by Sage Weil
parent b1530f5704
commit 6ee6b95373
1 changed files with 22 additions and 11 deletions

View File

@ -806,22 +806,28 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
/* /*
* Return true if mask caps are currently being revoked by an MDS. * Return true if mask caps are currently being revoked by an MDS.
*/ */
int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
struct ceph_cap *ocap, int mask)
{
struct ceph_cap *cap;
struct rb_node *p;
for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
cap = rb_entry(p, struct ceph_cap, ci_node);
if (cap != ocap && __cap_is_valid(cap) &&
(cap->implemented & ~cap->issued & mask))
return 1;
}
return 0;
}
int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) int ceph_caps_revoking(struct ceph_inode_info *ci, int mask)
{ {
struct inode *inode = &ci->vfs_inode; struct inode *inode = &ci->vfs_inode;
struct ceph_cap *cap; int ret;
struct rb_node *p;
int ret = 0;
spin_lock(&ci->i_ceph_lock); spin_lock(&ci->i_ceph_lock);
for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { ret = __ceph_caps_revoking_other(ci, NULL, mask);
cap = rb_entry(p, struct ceph_cap, ci_node);
if (__cap_is_valid(cap) &&
(cap->implemented & ~cap->issued & mask)) {
ret = 1;
break;
}
}
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
dout("ceph_caps_revoking %p %s = %d\n", inode, dout("ceph_caps_revoking %p %s = %d\n", inode,
ceph_cap_string(mask), ret); ceph_cap_string(mask), ret);
@ -2488,6 +2494,11 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
} else { } else {
dout("grant: %s -> %s\n", ceph_cap_string(cap->issued), dout("grant: %s -> %s\n", ceph_cap_string(cap->issued),
ceph_cap_string(newcaps)); ceph_cap_string(newcaps));
/* non-auth MDS is revoking the newly grant caps ? */
if (cap == ci->i_auth_cap &&
__ceph_caps_revoking_other(ci, cap, newcaps))
check_caps = 2;
cap->issued = newcaps; cap->issued = newcaps;
cap->implemented |= newcaps; /* add bits only, to cap->implemented |= newcaps; /* add bits only, to
* avoid stepping on a * avoid stepping on a