From ba6a56b77be74ef13640a761d8a9fafc17c79abc Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 10 Jul 2020 09:42:34 +0800 Subject: [PATCH] mds: in-place update projected inode's client ranges Signed-off-by: "Yan, Zheng" (cherry picked from commit 994017b6155af7fbb5a53f76f6a4525b363ba07f) Conflicts: src/mds/Locker.cc src/mds/Server.cc --- src/mds/Locker.cc | 135 ++++++++++++++++++++++++++++------------------ src/mds/Locker.h | 6 +-- src/mds/Server.cc | 9 ++-- 3 files changed, 88 insertions(+), 62 deletions(-) diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 9a249555da4e7..5ce696864e569 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -2687,9 +2687,7 @@ uint64_t Locker::calc_new_max_size(CInode::mempool_inode *pi, uint64_t size) return round_up_to(new_max, pi->get_layout_size_increment()); } -void Locker::calc_new_client_ranges(CInode *in, uint64_t size, bool update, - CInode::mempool_inode::client_range_map *new_ranges, - bool *max_increased) +bool Locker::check_client_ranges(CInode *in, uint64_t size) { auto latest = in->get_projected_inode(); uint64_t ms; @@ -2700,30 +2698,72 @@ void Locker::calc_new_client_ranges(CInode *in, uint64_t size, bool update, ms = 0; } + auto it = latest->client_ranges.begin(); + for (auto &p : in->client_caps) { + if ((p.second.issued() | p.second.wanted()) & CEPH_CAP_ANY_FILE_WR) { + if (it == latest->client_ranges.end()) + return true; + if (it->first != p.first) + return true; + if (ms > it->second.range.last) + return true; + ++it; + } + } + return it != latest->client_ranges.end(); +} + +bool Locker::calc_new_client_ranges(CInode *in, uint64_t size, bool *max_increased) +{ + auto pi = in->get_projected_inode(); + uint64_t ms; + if (pi->has_layout()) { + ms = calc_new_max_size(pi, size); + } else { + // Layout-less directories like ~mds0/, have zero size + ms = 0; + } + + bool updated = false; + // increase ranges as appropriate. // shrink to 0 if no WR|BUFFER caps issued. + auto it = pi->client_ranges.begin(); for (auto &p : in->client_caps) { if ((p.second.issued() | p.second.wanted()) & CEPH_CAP_ANY_FILE_WR) { - client_writeable_range_t& nr = (*new_ranges)[p.first]; - nr.range.first = 0; - if (latest->client_ranges.count(p.first)) { - client_writeable_range_t& oldr = latest->client_ranges[p.first]; - if (ms > oldr.range.last) - *max_increased = true; - nr.range.last = std::max(ms, oldr.range.last); - nr.follows = oldr.follows; + while (it != pi->client_ranges.end() && it->first < p.first) { + it = pi->client_ranges.erase(it); + updated = true; + } + + if (it != pi->client_ranges.end() && it->first == p.first) { + if (ms > it->second.range.last) { + it->second.range.last = ms; + updated = true; + if (max_increased) + *max_increased = true; + } } else { - *max_increased = true; - nr.range.last = ms; - nr.follows = in->first - 1; + it = pi->client_ranges.emplace_hint(it, std::piecewise_construct, + std::forward_as_tuple(p.first), + std::forward_as_tuple()); + it->second.range.last = ms; + it->second.follows = in->first - 1; + updated = true; + if (max_increased) + *max_increased = true; } - if (update) - p.second.mark_clientwriteable(); + p.second.mark_clientwriteable(); + ++it; } else { - if (update) - p.second.clear_clientwriteable(); + p.second.clear_clientwriteable(); } } + while (it != pi->client_ranges.end()) { + it = pi->client_ranges.erase(it); + updated = true; + } + return updated; } bool Locker::check_inode_max_size(CInode *in, bool force_wrlock, @@ -2734,11 +2774,8 @@ bool Locker::check_inode_max_size(CInode *in, bool force_wrlock, ceph_assert(in->is_file()); CInode::mempool_inode *latest = in->get_projected_inode(); - CInode::mempool_inode::client_range_map new_ranges; uint64_t size = latest->size; bool update_size = new_size > 0; - bool update_max = false; - bool max_increased = false; if (update_size) { new_size = size = std::max(size, new_size); @@ -2747,9 +2784,21 @@ bool Locker::check_inode_max_size(CInode *in, bool force_wrlock, update_size = false; } - int can_update = 1; + bool new_ranges = check_client_ranges(in, std::max(new_max_size, size)); + if (!update_size && !new_ranges) { + dout(20) << "check_inode_max_size no-op on " << *in << dendl; + return false; + } + + dout(10) << "check_inode_max_size new_ranges " << new_ranges + << " update_size " << update_size + << " on " << *in << dendl; + if (in->is_frozen()) { - can_update = -1; + dout(10) << "check_inode_max_size frozen, waiting on " << *in << dendl; + in->add_waiter(CInode::WAIT_UNFREEZE, + new C_MDL_CheckMaxSize(this, in, new_max_size, new_size, new_mtime)); + return false; } else if (!force_wrlock && !in->filelock.can_wrlock(in->get_loner())) { // lock? if (in->filelock.is_stable()) { @@ -2758,35 +2807,12 @@ bool Locker::check_inode_max_size(CInode *in, bool force_wrlock, else simple_lock(&in->filelock); } - if (!in->filelock.can_wrlock(in->get_loner())) - can_update = -2; - } - - calc_new_client_ranges(in, std::max(new_max_size, size), can_update > 0, - &new_ranges, &max_increased); - - if (max_increased || latest->client_ranges != new_ranges) - update_max = true; - - if (!update_size && !update_max) { - dout(20) << "check_inode_max_size no-op on " << *in << dendl; - return false; - } - - dout(10) << "check_inode_max_size new_ranges " << new_ranges - << " update_size " << update_size - << " on " << *in << dendl; - - if (can_update < 0) { - auto cms = new C_MDL_CheckMaxSize(this, in, new_max_size, new_size, new_mtime); - if (can_update == -1) { - dout(10) << "check_inode_max_size frozen, waiting on " << *in << dendl; - in->add_waiter(CInode::WAIT_UNFREEZE, cms); - } else { - in->filelock.add_waiter(SimpleLock::WAIT_STABLE, cms); + if (!in->filelock.can_wrlock(in->get_loner())) { dout(10) << "check_inode_max_size can't wrlock, waiting on " << *in << dendl; + in->filelock.add_waiter(SimpleLock::WAIT_STABLE, + new C_MDL_CheckMaxSize(this, in, new_max_size, new_size, new_mtime)); + return false; } - return false; } MutationRef mut(new MutationImpl()); @@ -2795,9 +2821,12 @@ bool Locker::check_inode_max_size(CInode *in, bool force_wrlock, auto &pi = in->project_inode(); pi.inode.version = in->pre_dirty(); - if (update_max) { - dout(10) << "check_inode_max_size client_ranges " << pi.inode.client_ranges << " -> " << new_ranges << dendl; - pi.inode.client_ranges = new_ranges; + bool max_increased = false; + if (new_ranges && + calc_new_client_ranges(in, std::max(new_max_size, size), &max_increased)) { + dout(10) << "check_inode_max_size client_ranges " + << in->get_previous_projected_inode()->client_ranges + << " -> " << pi.inode.client_ranges << dendl; } if (update_size) { diff --git a/src/mds/Locker.h b/src/mds/Locker.h index a3d3ec6a6ec5d..bcd6e74592b3a 100644 --- a/src/mds/Locker.h +++ b/src/mds/Locker.h @@ -174,9 +174,9 @@ public: void request_inode_file_caps(CInode *in); - void calc_new_client_ranges(CInode *in, uint64_t size, bool update, - CInode::mempool_inode::client_range_map* new_ranges, - bool *max_increased); + bool check_client_ranges(CInode *in, uint64_t size); + bool calc_new_client_ranges(CInode *in, uint64_t size, + bool *max_increased=nullptr); bool check_inode_max_size(CInode *in, bool force_wrlock=false, uint64_t newmax=0, uint64_t newsize=0, utime_t mtime=utime_t()); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index d636646807d85..8c24a195d6be9 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -4992,12 +4992,9 @@ void Server::handle_client_setattr(MDRequestRef& mdr) pi.inode.mtime = mdr->get_op_stamp(); // adjust client's max_size? - CInode::mempool_inode::client_range_map new_ranges; - bool max_increased = false; - mds->locker->calc_new_client_ranges(cur, pi.inode.size, true, &new_ranges, &max_increased); - if (pi.inode.client_ranges != new_ranges) { - dout(10) << " client_ranges " << pi.inode.client_ranges << " -> " << new_ranges << dendl; - pi.inode.client_ranges = new_ranges; + if (mds->locker->calc_new_client_ranges(cur, pi.inode.size)) { + dout(10) << " client_ranges " << cur->get_previous_projected_inode()->client_ranges + << " -> " << pi.inode.client_ranges << dendl; changed_ranges = true; } } -- 2.39.5