From: Yan, Zheng Date: Fri, 10 Jul 2020 09:56:19 +0000 (+0800) Subject: mds: explicitly track files with client writeable ranges X-Git-Tag: v16.1.0~1258^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=44f67be02b8e8aa8fc69283bf12107c2df3f8277;p=ceph.git mds: explicitly track files with client writeable ranges Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 5fa858b6af7..02213a70173 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -3364,17 +3364,6 @@ void CInode::set_mds_caps_wanted(mds_rank_t mds, int32_t wanted) } } -void CInode::adjust_num_caps_notable(int d) -{ - if (!num_caps_notable && d > 0) - mdcache->open_file_table.add_inode(this); - else if (num_caps_notable > 0 && num_caps_notable == -d) - mdcache->open_file_table.remove_inode(this); - - num_caps_notable +=d; - ceph_assert(num_caps_notable >= 0); -} - Capability *CInode::add_client_cap(client_t client, Session *session, SnapRealm *conrealm, bool new_inode) { @@ -3656,6 +3645,38 @@ bool CInode::issued_caps_need_gather(SimpleLock *lock) return false; } +void CInode::adjust_num_caps_notable(int d) +{ + if (!is_clientwriteable()) { + if (!num_caps_notable && d > 0) + mdcache->open_file_table.add_inode(this); + else if (num_caps_notable > 0 && num_caps_notable == -d) + mdcache->open_file_table.remove_inode(this); + } + + num_caps_notable +=d; + ceph_assert(num_caps_notable >= 0); +} + +void CInode::mark_clientwriteable() +{ + if (last != CEPH_NOSNAP) + return; + if (!state_test(STATE_CLIENTWRITEABLE)) { + if (num_caps_notable == 0) + mdcache->open_file_table.add_inode(this); + state_set(STATE_CLIENTWRITEABLE); + } +} + +void CInode::clear_clientwriteable() +{ + if (state_test(STATE_CLIENTWRITEABLE)) { + if (num_caps_notable == 0) + mdcache->open_file_table.remove_inode(this); + state_clear(STATE_CLIENTWRITEABLE); + } +} // ============================================= @@ -3771,23 +3792,9 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session, } // max_size is min of projected, actual - uint64_t max_size; - { - auto it = oi->client_ranges.find(client); - if (it == oi->client_ranges.end()) { - max_size = 0; - } else { - max_size = it->second.range.last; - if (oi != pi) { - it = pi->client_ranges.find(client); - if (it == pi->client_ranges.end()) { - max_size = 0; - } else { - max_size = std::min(max_size, it->second.range.last); - } - } - } - } + uint64_t max_size = + std::min(oi->get_client_range(client), + pi->get_client_range(client)); // inline data version_t inline_version = 0; @@ -4139,24 +4146,9 @@ void CInode::encode_cap_message(const ref_t &m, Capability *cap) } // max_size is min of projected, actual. - { - uint64_t max_size; - auto it = oi->client_ranges.find(client); - if (it == oi->client_ranges.end()) { - max_size = 0; - } else { - max_size = it->second.range.last; - if (oi != pi) { - it = pi->client_ranges.find(client); - if (it == pi->client_ranges.end()) { - max_size = 0; - } else { - max_size = std::min(max_size, it->second.range.last); - } - } - } - m->max_size = max_size; - } + uint64_t oldms = oi->get_client_range(client); + uint64_t newms = pi->get_client_range(client); + m->max_size = std::min(oldms, newms); i = pauth ? pi:oi; m->head.mode = i->mode; diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 781bcf7f726..600307b5724 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -358,6 +358,8 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counterclient_ranges.erase(it); updated = true; } + if (updated) { + if (pi->client_ranges.empty()) + in->clear_clientwriteable(); + else + in->mark_clientwriteable(); + } return updated; } @@ -3733,11 +3739,7 @@ bool Locker::_do_cap_update(CInode *in, Capability *cap, // increase or zero max_size? uint64_t size = m->get_size(); bool change_max = false; - uint64_t old_max; - { - auto it = latest->client_ranges.find(client); - old_max = it != latest->client_ranges.end() ? it->second.range.last: 0; - } + uint64_t old_max = latest->get_client_range(client); uint64_t new_max = old_max; if (in->is_file()) { @@ -3854,10 +3856,13 @@ bool Locker::_do_cap_update(CInode *in, Capability *cap, cr.range.first = 0; cr.range.last = new_max; cr.follows = in->first - 1; + in->mark_clientwriteable(); if (cap) cap->mark_clientwriteable(); } else { pi.inode->client_ranges.erase(client); + if (pi.inode->client_ranges.empty()) + in->clear_clientwriteable(); if (cap) cap->clear_clientwriteable(); } diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index f8833756227..920e141f9a4 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -353,6 +353,8 @@ void MDCache::remove_inode(CInode *o) o->clear_scatter_dirty(); + o->clear_clientwriteable(); + o->item_open_file.remove_myself(); if (o->state_test(CInode::STATE_QUEUEDEXPORTPIN)) @@ -6399,14 +6401,18 @@ void MDCache::identify_files_to_recover() } bool recover = false; - for (auto& p : in->get_inode()->client_ranges) { - Capability *cap = in->get_client_cap(p.first); - if (cap) { - cap->mark_clientwriteable(); - } else { - dout(10) << " client." << p.first << " has range " << p.second << " but no cap on " << *in << dendl; - recover = true; - break; + const auto& client_ranges = in->get_projected_inode()->client_ranges; + if (!client_ranges.empty()) { + in->mark_clientwriteable(); + for (auto& p : client_ranges) { + Capability *cap = in->get_client_cap(p.first); + if (cap) { + cap->mark_clientwriteable(); + } else { + dout(10) << " client." << p.first << " has range " << p.second << " but no cap on " << *in << dendl; + recover = true; + break; + } } } diff --git a/src/mds/Migrator.cc b/src/mds/Migrator.cc index 6703cba1b18..9a6d90bf9bd 100644 --- a/src/mds/Migrator.cc +++ b/src/mds/Migrator.cc @@ -1726,6 +1726,8 @@ void Migrator::finish_export_inode(CInode *in, mds_rank_t peer, in->clear_dirty_parent(); + in->clear_clientwriteable(); + in->clear_file_locks(); // waiters @@ -2868,6 +2870,7 @@ void Migrator::import_reverse(CDir *dir) in->clear_dirty_parent(); + in->clear_clientwriteable(); in->state_clear(CInode::STATE_NEEDSRECOVER); in->authlock.clear_gather(); @@ -3228,6 +3231,9 @@ void Migrator::decode_import_inode(CDentry *dn, bufferlist::const_iterator& blp, if (in->get_inode()->is_dirty_rstat()) in->mark_dirty_rstat(); + + if (!in->get_inode()->client_ranges.empty()) + in->mark_clientwriteable(); // clear if dirtyscattered, since we're going to journal this // but not until we _actually_ finish the import... diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 4eb759afd0f..7c5d7db52d5 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -4395,6 +4395,7 @@ void Server::handle_client_openc(MDRequestRef& mdr) _inode->client_ranges[client].range.first = 0; _inode->client_ranges[client].range.last = _inode->layout.stripe_unit; _inode->client_ranges[client].follows = follows; + newi->mark_clientwriteable(); cap->mark_clientwriteable(); } @@ -5058,6 +5059,7 @@ void Server::do_open_truncate(MDRequestRef& mdr, int cmode) pi.inode->client_ranges[client].range.last = pi.inode->get_layout_size_increment(); pi.inode->client_ranges[client].follows = realm->get_newest_seq(); changed_ranges = true; + in->mark_clientwriteable(); cap->mark_clientwriteable(); } @@ -6030,6 +6032,7 @@ void Server::handle_client_mknod(MDRequestRef& mdr) _inode->client_ranges[client].range.first = 0; _inode->client_ranges[client].range.last = _inode->layout.stripe_unit; _inode->client_ranges[client].follows = follows; + newi->mark_clientwriteable(); cap->mark_clientwriteable(); } } diff --git a/src/mds/StrayManager.cc b/src/mds/StrayManager.cc index ee2a99e3063..2ff639e18d2 100644 --- a/src/mds/StrayManager.cc +++ b/src/mds/StrayManager.cc @@ -188,6 +188,8 @@ void StrayManager::_purge_stray_purged( pi.inode->truncate_size = 0; pi.inode->truncate_from = 0; pi.inode->version = in->pre_dirty(); + pi.inode->client_ranges.clear(); + in->clear_clientwriteable(); CDir *dir = dn->get_dir(); auto pf = dir->project_fnode(mut); diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index 78d8405ac9d..de38ef79de8 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -494,6 +494,11 @@ struct inode_t { bool is_dirty_rstat() const { return !(rstat == accounted_rstat); } + uint64_t get_client_range(client_t client) const { + auto it = client_ranges.find(client); + return it != client_ranges.end() ? it->second.range.last : 0; + } + uint64_t get_max_size() const { uint64_t max = 0; for (std::map::const_iterator p = client_ranges.begin();