summaryrefslogtreecommitdiffstats
path: root/fs/ceph/caps.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2014-12-23 02:30:54 -0500
committerIlya Dryomov <idryomov@gmail.com>2015-02-19 05:31:38 -0500
commit982d6011bc30a26e8a3d546e0e7fc7db2c255d85 (patch)
tree3d1ee68f03edac2d64b7683baf15821cf14bdef7 /fs/ceph/caps.c
parent1487a688d8ea596e6710b0d256300ab10ce99284 (diff)
ceph: improve reference tracking for snaprealm
When snaprealm is created, its initial reference count is zero. But in some rare cases, the newly created snaprealm is not referenced by anyone. This causes snaprealm with zero reference count not freed. The fix is set reference count of newly snaprealm to 1. The reference is return the function who requests to create the snaprealm. When the function finishes its job, it releases the reference. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r--fs/ceph/caps.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index d0618e8412fd..8ed1192606d9 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -577,7 +577,6 @@ void ceph_add_cap(struct inode *inode,
577 struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc, 577 struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc,
578 realmino); 578 realmino);
579 if (realm) { 579 if (realm) {
580 ceph_get_snap_realm(mdsc, realm);
581 spin_lock(&realm->inodes_with_caps_lock); 580 spin_lock(&realm->inodes_with_caps_lock);
582 ci->i_snap_realm = realm; 581 ci->i_snap_realm = realm;
583 list_add(&ci->i_snap_realm_item, 582 list_add(&ci->i_snap_realm_item,
@@ -2447,13 +2446,13 @@ static void invalidate_aliases(struct inode *inode)
2447 */ 2446 */
2448static void handle_cap_grant(struct ceph_mds_client *mdsc, 2447static void handle_cap_grant(struct ceph_mds_client *mdsc,
2449 struct inode *inode, struct ceph_mds_caps *grant, 2448 struct inode *inode, struct ceph_mds_caps *grant,
2450 void *snaptrace, int snaptrace_len,
2451 u64 inline_version, 2449 u64 inline_version,
2452 void *inline_data, int inline_len, 2450 void *inline_data, int inline_len,
2453 struct ceph_buffer *xattr_buf, 2451 struct ceph_buffer *xattr_buf,
2454 struct ceph_mds_session *session, 2452 struct ceph_mds_session *session,
2455 struct ceph_cap *cap, int issued) 2453 struct ceph_cap *cap, int issued)
2456 __releases(ci->i_ceph_lock) 2454 __releases(ci->i_ceph_lock)
2455 __releases(mdsc->snap_rwsem)
2457{ 2456{
2458 struct ceph_inode_info *ci = ceph_inode(inode); 2457 struct ceph_inode_info *ci = ceph_inode(inode);
2459 int mds = session->s_mds; 2458 int mds = session->s_mds;
@@ -2654,10 +2653,6 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
2654 spin_unlock(&ci->i_ceph_lock); 2653 spin_unlock(&ci->i_ceph_lock);
2655 2654
2656 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) { 2655 if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
2657 down_write(&mdsc->snap_rwsem);
2658 ceph_update_snap_trace(mdsc, snaptrace,
2659 snaptrace + snaptrace_len, false);
2660 downgrade_write(&mdsc->snap_rwsem);
2661 kick_flushing_inode_caps(mdsc, session, inode); 2656 kick_flushing_inode_caps(mdsc, session, inode);
2662 up_read(&mdsc->snap_rwsem); 2657 up_read(&mdsc->snap_rwsem);
2663 if (newcaps & ~issued) 2658 if (newcaps & ~issued)
@@ -3067,6 +3062,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3067 struct ceph_cap *cap; 3062 struct ceph_cap *cap;
3068 struct ceph_mds_caps *h; 3063 struct ceph_mds_caps *h;
3069 struct ceph_mds_cap_peer *peer = NULL; 3064 struct ceph_mds_cap_peer *peer = NULL;
3065 struct ceph_snap_realm *realm;
3070 int mds = session->s_mds; 3066 int mds = session->s_mds;
3071 int op, issued; 3067 int op, issued;
3072 u32 seq, mseq; 3068 u32 seq, mseq;
@@ -3168,11 +3164,23 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3168 goto done_unlocked; 3164 goto done_unlocked;
3169 3165
3170 case CEPH_CAP_OP_IMPORT: 3166 case CEPH_CAP_OP_IMPORT:
3167 realm = NULL;
3168 if (snaptrace_len) {
3169 down_write(&mdsc->snap_rwsem);
3170 ceph_update_snap_trace(mdsc, snaptrace,
3171 snaptrace + snaptrace_len,
3172 false, &realm);
3173 downgrade_write(&mdsc->snap_rwsem);
3174 } else {
3175 down_read(&mdsc->snap_rwsem);
3176 }
3171 handle_cap_import(mdsc, inode, h, peer, session, 3177 handle_cap_import(mdsc, inode, h, peer, session,
3172 &cap, &issued); 3178 &cap, &issued);
3173 handle_cap_grant(mdsc, inode, h, snaptrace, snaptrace_len, 3179 handle_cap_grant(mdsc, inode, h,
3174 inline_version, inline_data, inline_len, 3180 inline_version, inline_data, inline_len,
3175 msg->middle, session, cap, issued); 3181 msg->middle, session, cap, issued);
3182 if (realm)
3183 ceph_put_snap_realm(mdsc, realm);
3176 goto done_unlocked; 3184 goto done_unlocked;
3177 } 3185 }
3178 3186
@@ -3192,7 +3200,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
3192 case CEPH_CAP_OP_GRANT: 3200 case CEPH_CAP_OP_GRANT:
3193 __ceph_caps_issued(ci, &issued); 3201 __ceph_caps_issued(ci, &issued);
3194 issued |= __ceph_caps_dirty(ci); 3202 issued |= __ceph_caps_dirty(ci);
3195 handle_cap_grant(mdsc, inode, h, NULL, 0, 3203 handle_cap_grant(mdsc, inode, h,
3196 inline_version, inline_data, inline_len, 3204 inline_version, inline_data, inline_len,
3197 msg->middle, session, cap, issued); 3205 msg->middle, session, cap, issued);
3198 goto done_unlocked; 3206 goto done_unlocked;