From: dongdong tao Date: Wed, 27 Dec 2017 15:47:16 +0000 (+0800) Subject: client: fix dirty caps might never be flushed X-Git-Tag: v12.2.6~63^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d3afb44e5d9205372198fe6f8e8dedbfa46b48c6;p=ceph.git client: fix dirty caps might never be flushed Fixes: http://tracker.ceph.com/issues/22546 Signed-off-by: dongdong tao (cherry picked from commit aeb920be8ab5f0e5e47d82943c214b012bb8ec5c) Conflicts: src/client/Client.cc --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 044c29f3a081..b1b61757bd4b 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -3232,7 +3232,7 @@ void Client::cap_delay_requeue(Inode *in) ldout(cct, 10) << "cap_delay_requeue on " << *in << dendl; in->hold_caps_until = ceph_clock_now(); in->hold_caps_until += cct->_conf->client_caps_release_delay; - delayed_caps.push_back(&in->cap_item); + delayed_list.push_back(&in->delay_cap_item); } void Client::send_cap(Inode *in, MetaSession *session, Cap *cap, @@ -3901,7 +3901,6 @@ void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id cap->session = mds_session; cap->inode = in; cap->gen = mds_session->cap_gen; - cap_list.push_back(&in->cap_item); } check_cap_issue(in, cap, issued); @@ -4020,7 +4019,7 @@ void Client::remove_session_caps(MetaSession *s) in->flushing_cap_tids.clear(); } in->flushing_caps = 0; - in->dirty_caps = 0; + mark_caps_clean(in); put_inode(in); } } @@ -4161,11 +4160,19 @@ void Client::force_session_readonly(MetaSession *s) void Client::mark_caps_dirty(Inode *in, int caps) { - ldout(cct, 10) << "mark_caps_dirty " << *in << " " << ccap_string(in->dirty_caps) << " -> " + ldout(cct, 10) << __func__ << " " << *in << " " << ccap_string(in->dirty_caps) << " -> " << ccap_string(in->dirty_caps | caps) << dendl; if (caps && !in->caps_dirty()) in->get(); in->dirty_caps |= caps; + dirty_list.push_back(&in->dirty_cap_item); +} + +void Client::mark_caps_clean(Inode *in) +{ + ldout(cct, 10) << __func__ << " " << *in << dendl; + in->dirty_caps = 0; + in->dirty_cap_item.remove_myself(); } int Client::mark_caps_flushing(Inode *in, ceph_tid_t* ptid) @@ -4186,7 +4193,7 @@ int Client::mark_caps_flushing(Inode *in, ceph_tid_t* ptid) } in->flushing_caps |= flushing; - in->dirty_caps = 0; + mark_caps_clean(in); if (!in->flushing_cap_item.is_on_list()) session->flushing_caps.push_back(&in->flushing_cap_item); @@ -4222,20 +4229,20 @@ void Client::adjust_session_flushing_caps(Inode *in, MetaSession *old_s, MetaSe void Client::flush_caps_sync() { ldout(cct, 10) << __func__ << dendl; - xlist::iterator p = delayed_caps.begin(); + xlist::iterator p = delayed_list.begin(); while (!p.end()) { unsigned flags = CHECK_CAPS_NODELAY; Inode *in = *p; ++p; - delayed_caps.pop_front(); - if (p.end() && cap_list.empty()) + delayed_list.pop_front(); + if (p.end() && dirty_list.empty()) flags |= CHECK_CAPS_SYNCHRONOUS; check_caps(in, flags); } // other caps, too - p = cap_list.begin(); + p = dirty_list.begin(); while (!p.end()) { unsigned flags = CHECK_CAPS_NODELAY; Inode *in = *p; @@ -6054,14 +6061,13 @@ void Client::tick() } // delayed caps - xlist::iterator p = delayed_caps.begin(); + xlist::iterator p = delayed_list.begin(); while (!p.end()) { Inode *in = *p; ++p; if (in->hold_caps_until > now) break; - delayed_caps.pop_front(); - cap_list.push_back(&in->cap_item); + delayed_list.pop_front(); check_caps(in, CHECK_CAPS_NODELAY); } diff --git a/src/client/Client.h b/src/client/Client.h index 6c131182b8a4..6940053f87ce 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -432,8 +432,8 @@ protected: Inode* root_ancestor; LRU lru; // lru list of Dentry's in our local metadata cache. - // all inodes with caps sit on either cap_list or delayed_caps. - xlist delayed_caps, cap_list; + // dirty_list keeps all the dirty inodes before flushing. + xlist delayed_list, dirty_list; int num_flushing_caps; ceph::unordered_map snap_realms; @@ -636,6 +636,7 @@ protected: void remove_all_caps(Inode *in); void remove_session_caps(MetaSession *session); void mark_caps_dirty(Inode *in, int caps); + void mark_caps_clean(Inode *in); int mark_caps_flushing(Inode *in, ceph_tid_t *ptid); void adjust_session_flushing_caps(Inode *in, MetaSession *old_s, MetaSession *new_s); void flush_caps_sync(); diff --git a/src/client/Inode.cc b/src/client/Inode.cc index 60689db06c43..d877757faa1e 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -14,7 +14,8 @@ Inode::~Inode() { - cap_item.remove_myself(); + delay_cap_item.remove_myself(); + dirty_cap_item.remove_myself(); snaprealm_item.remove_myself(); if (snapdir_parent) { diff --git a/src/client/Inode.h b/src/client/Inode.h index 5242630d5d1a..9c9ebe0c3770 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -177,7 +177,7 @@ struct Inode { int shared_gen, cache_gen; int snap_caps, snap_cap_refs; utime_t hold_caps_until; - xlist::item cap_item, flushing_cap_item; + xlist::item delay_cap_item, dirty_cap_item, flushing_cap_item; SnapRealm *snaprealm; xlist::item snaprealm_item; @@ -247,7 +247,7 @@ struct Inode { cap_dirtier_uid(-1), cap_dirtier_gid(-1), dirty_caps(0), flushing_caps(0), shared_gen(0), cache_gen(0), snap_caps(0), snap_cap_refs(0), - cap_item(this), flushing_cap_item(this), + delay_cap_item(this), dirty_cap_item(this), flushing_cap_item(this), snaprealm(0), snaprealm_item(this), oset((void *)this, newlayout->pool_id, this->ino), reported_size(0), wanted_max_size(0), requested_max_size(0),