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: v15.2.9~122^2~32^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=03a4d18c1b5a16e6bcd79bc44aa9a1a0eb643c35;p=ceph.git mds: explicitly track files with client writeable ranges Signed-off-by: "Yan, Zheng" (cherry picked from commit 44f67be02b8e8aa8fc69283bf12107c2df3f8277) Conflicts: src/mds/CInode.cc src/mds/Locker.cc src/mds/MDCache.cc src/mds/Server.cc src/mds/StrayManager.cc --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 7055e0e49d21..78263f7fb515 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -3281,17 +3281,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) { @@ -3573,6 +3562,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); + } +} // ============================================= @@ -3690,10 +3711,8 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session, // max_size is min of projected, actual uint64_t max_size = - std::min(oi->client_ranges.count(client) ? - oi->client_ranges[client].range.last : 0, - pi->client_ranges.count(client) ? - pi->client_ranges[client].range.last : 0); + std::min(oi->get_client_range(client), + pi->get_client_range(client)); // inline data version_t inline_version = 0; @@ -4045,8 +4064,8 @@ void CInode::encode_cap_message(const ref_t &m, Capability *cap) } // max_size is min of projected, actual. - uint64_t oldms = oi->client_ranges.count(client) ? oi->client_ranges[client].range.last : 0; - uint64_t newms = pi->client_ranges.count(client) ? pi->client_ranges[client].range.last : 0; + 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; diff --git a/src/mds/CInode.h b/src/mds/CInode.h index a416a9060a38..4bf81fd248b5 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -323,6 +323,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; } @@ -3725,7 +3731,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 = latest->client_ranges.count(client) ? latest->client_ranges[client].range.last : 0; + uint64_t old_max = latest->get_client_range(client); uint64_t new_max = old_max; if (in->is_file()) { @@ -3842,10 +3848,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 869cde4bf4e2..788d7e8c02c1 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)) @@ -6378,16 +6380,18 @@ void MDCache::identify_files_to_recover() } bool recover = false; - for (map::iterator p = in->inode.client_ranges.begin(); - p != in->inode.client_ranges.end(); - ++p) { - 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 1efb72d5f11e..875e6baf3823 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->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 8c24a195d6be..e9dfa58c9b26 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -4391,6 +4391,7 @@ void Server::handle_client_openc(MDRequestRef& mdr) in->inode.client_ranges[client].range.first = 0; in->inode.client_ranges[client].range.last = in->inode.layout.stripe_unit; in->inode.client_ranges[client].follows = follows; + in->mark_clientwriteable(); cap->mark_clientwriteable(); } @@ -5055,6 +5056,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(); } @@ -6055,6 +6057,7 @@ void Server::handle_client_mknod(MDRequestRef& mdr) newi->inode.client_ranges[client].range.first = 0; newi->inode.client_ranges[client].range.last = newi->inode.layout.stripe_unit; newi->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 a093dd73fb00..6f821c0a1f6e 100644 --- a/src/mds/StrayManager.cc +++ b/src/mds/StrayManager.cc @@ -185,10 +185,11 @@ void StrayManager::_purge_stray_purged( auto &pi = in->project_inode(); pi.inode.size = 0; pi.inode.max_size_ever = 0; - pi.inode.client_ranges.clear(); pi.inode.truncate_size = 0; pi.inode.truncate_from = 0; pi.inode.version = in->pre_dirty(); + pi.inode.client_ranges.clear(); + in->clear_clientwriteable(); le->metablob.add_dir_context(dn->dir); le->metablob.add_primary_dentry(dn, in, true); diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index cd829b86698f..3f0b05a09528 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -482,6 +482,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();