diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2013-07-02 00:40:21 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-07-03 18:32:57 -0400 |
commit | 6ee6b95373dfa1d0a4c9bc76689ec10a60c1d6f2 (patch) | |
tree | 7173050cd5f444db41e62b5d1d6b813042dca0e1 /fs/ceph | |
parent | b1530f57042297f85330a140a6921b6f95fe74d3 (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>
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/caps.c | 29 |
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 | */ |
809 | int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) | 809 | int __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 | |||
824 | int 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 |