diff options
author | Yan, Zheng <zyan@redhat.com> | 2015-03-23 08:12:20 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2015-04-20 11:55:35 -0400 |
commit | db40cc1702d6a7049740d269cf6c1a42f979c7a7 (patch) | |
tree | 9e37f60353da7f0e04afc0aa5b775244da5f6345 | |
parent | 3ef650d3989677bd460497f9c3b0d58caaba0116 (diff) |
ceph: keep i_snap_realm while there are writers
when reconnecting to MDS is denied, we remove session caps
forcibly. But it's possible there are ongoing write, the
write code needs to reference i_snap_realm. So if there are
ongoing write, we keep i_snap_realm.
Signed-off-by: Yan, Zheng <zyan@redhat.com>
-rw-r--r-- | fs/ceph/caps.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 8172775428a0..4ddadc13d162 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -896,6 +896,18 @@ int ceph_is_any_caps(struct inode *inode) | |||
896 | return ret; | 896 | return ret; |
897 | } | 897 | } |
898 | 898 | ||
899 | static void drop_inode_snap_realm(struct ceph_inode_info *ci) | ||
900 | { | ||
901 | struct ceph_snap_realm *realm = ci->i_snap_realm; | ||
902 | spin_lock(&realm->inodes_with_caps_lock); | ||
903 | list_del_init(&ci->i_snap_realm_item); | ||
904 | ci->i_snap_realm_counter++; | ||
905 | ci->i_snap_realm = NULL; | ||
906 | spin_unlock(&realm->inodes_with_caps_lock); | ||
907 | ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc, | ||
908 | realm); | ||
909 | } | ||
910 | |||
899 | /* | 911 | /* |
900 | * Remove a cap. Take steps to deal with a racing iterate_session_caps. | 912 | * Remove a cap. Take steps to deal with a racing iterate_session_caps. |
901 | * | 913 | * |
@@ -946,15 +958,13 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release) | |||
946 | if (removed) | 958 | if (removed) |
947 | ceph_put_cap(mdsc, cap); | 959 | ceph_put_cap(mdsc, cap); |
948 | 960 | ||
949 | if (!__ceph_is_any_caps(ci) && ci->i_snap_realm) { | 961 | /* when reconnect denied, we remove session caps forcibly, |
950 | struct ceph_snap_realm *realm = ci->i_snap_realm; | 962 | * i_wr_ref can be non-zero. If there are ongoing write, |
951 | spin_lock(&realm->inodes_with_caps_lock); | 963 | * keep i_snap_realm. |
952 | list_del_init(&ci->i_snap_realm_item); | 964 | */ |
953 | ci->i_snap_realm_counter++; | 965 | if (!__ceph_is_any_caps(ci) && ci->i_wr_ref == 0 && ci->i_snap_realm) |
954 | ci->i_snap_realm = NULL; | 966 | drop_inode_snap_realm(ci); |
955 | spin_unlock(&realm->inodes_with_caps_lock); | 967 | |
956 | ceph_put_snap_realm(mdsc, realm); | ||
957 | } | ||
958 | if (!__ceph_is_any_real_caps(ci)) | 968 | if (!__ceph_is_any_real_caps(ci)) |
959 | __cap_delay_cancel(mdsc, ci); | 969 | __cap_delay_cancel(mdsc, ci); |
960 | } | 970 | } |
@@ -2309,6 +2319,9 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) | |||
2309 | wake = 1; | 2319 | wake = 1; |
2310 | } | 2320 | } |
2311 | } | 2321 | } |
2322 | /* see comment in __ceph_remove_cap() */ | ||
2323 | if (!__ceph_is_any_caps(ci) && ci->i_snap_realm) | ||
2324 | drop_inode_snap_realm(ci); | ||
2312 | } | 2325 | } |
2313 | spin_unlock(&ci->i_ceph_lock); | 2326 | spin_unlock(&ci->i_ceph_lock); |
2314 | 2327 | ||