using client_range_map = std::map<client_t,client_writeable_range_t,std::less<client_t>,Allocator<std::pair<const client_t,client_writeable_range_t>>>;
static const uint8_t F_EPHEMERAL_DISTRIBUTED_PIN = (1<<0);
+ static const uint8_t F_QUIESCE_BLOCK = (1<<1);
inode_t()
{
bool get_ephemeral_distributed_pin() const {
return get_flag(F_EPHEMERAL_DISTRIBUTED_PIN);
}
+ void set_quiesce_block(bool v) {
+ set_flag(v, F_QUIESCE_BLOCK);
+ }
+ bool get_quiesce_block() const {
+ return get_flag(F_QUIESCE_BLOCK);
+ }
void encode(ceph::buffer::list &bl, uint64_t features) const;
void decode(ceph::buffer::list::const_iterator& bl);
f->dump_int("export_pin", export_pin);
f->dump_int("export_ephemeral_random_pin", export_ephemeral_random_pin);
f->dump_bool("export_ephemeral_distributed_pin", get_ephemeral_distributed_pin());
+ f->dump_bool("quiesce_block", get_quiesce_block());
f->open_array_section("client_ranges");
for (const auto &p : client_ranges) {
if (in.state_test(CInode::STATE_RANDEPHEMERALPIN)) {
out << " randepin";
}
+ if (in.get_inode()->get_quiesce_block()) {
+ out << " qblock";
+ }
out << " " << ∈
out << "]";
return;
}
+ if (in->get_projected_inode()->get_quiesce_block()) {
+ dout(10) << __func__ << " quiesce is blocked for this inode; dropping locks!" << dendl;
+ mdr->mark_event("quiesce blocked");
+ mds->locker->drop_locks(mdr.get());
+ /* keep authpins! */
+ qs.inc_inodes_blocked();
+ mdr->internal_op_finish->complete(0);
+ mdr->internal_op_finish = nullptr;
+ return;
+ }
+
if (in->is_dir()) {
for (auto& dir : in->get_dirfrags()) {
if (!dir->is_auth() && !splitauth) {
uint64_t inc_heartbeat_count() {
return ++heartbeat_count;
}
+ void inc_inodes_blocked() {
+ inodes_blocked++;
+ }
uint64_t get_inodes() const {
return inodes;
}
uint64_t get_inodes_quiesced() const {
return inodes_quiesced;
}
+ uint64_t get_inodes_blocked() const {
+ return inodes_blocked;
+ }
void add_failed(const MDRequestRef& mdr, int rc) {
failed[mdr] = rc;
}
void dump(Formatter* f) const {
f->dump_unsigned("inodes", inodes);
f->dump_unsigned("inodes_quiesced", inodes_quiesced);
+ f->dump_unsigned("inodes_blocked", inodes_blocked);
f->open_array_section("failed");
for (auto& [mdr, rc] : failed) {
f->open_object_section("failure");
uint64_t heartbeat_count = 0;
uint64_t inodes = 0;
uint64_t inodes_quiesced = 0;
+ uint64_t inodes_blocked = 0;
std::map<MDRequestRef, int> failed;
};
class C_MDS_QuiescePath : public MDSInternalContext {
client_t exclude_ct = mdr->get_client();
mdcache->broadcast_quota_to_client(cur, exclude_ct, true);
+ } else if (name == "ceph.quiesce.block"sv) {
+ bool val;
+ try {
+ val = boost::lexical_cast<bool>(value);
+ } catch (boost::bad_lexical_cast const&) {
+ dout(10) << "bad vxattr value, unable to parse bool for " << name << dendl;
+ respond_to_request(mdr, -CEPHFS_EINVAL);
+ return;
+ }
+
+ /* Verify it's not already marked with lighter weight
+ * rdlock.
+ */
+ if (!mdr->more()->rdonly_checks) {
+ if (!(mdr->locking_state & MutationImpl::ALL_LOCKED)) {
+ lov.add_rdlock(&cur->policylock);
+ if (!mds->locker->acquire_locks(mdr, lov))
+ return;
+ mdr->locking_state |= MutationImpl::ALL_LOCKED;
+ }
+ bool is_blocked = cur->get_projected_inode()->get_quiesce_block();
+ if (is_blocked == val) {
+ dout(20) << "already F_QUIESCE_BLOCK set" << dendl;
+ respond_to_request(mdr, 0);
+ return;
+ }
+ mdr->more()->rdonly_checks = true;
+ }
+
+ if ((mdr->locking_state & MutationImpl::ALL_LOCKED) && !mdr->is_xlocked(&cur->policylock)) {
+ /* drop the rdlock and acquire xlocks */
+ dout(20) << "dropping rdlocks" << dendl;
+ mds->locker->drop_locks(mdr.get());
+ if (!xlock_policylock(mdr, cur, false, true))
+ return;
+ }
+
+ /* repeat rdonly checks in case changed between rdlock -> xlock */
+ bool is_blocked = cur->get_projected_inode()->get_quiesce_block();
+ if (is_blocked == val) {
+ dout(20) << "already F_QUIESCE_BLOCK set" << dendl;
+ respond_to_request(mdr, 0);
+ return;
+ }
+
+ auto pi = cur->project_inode(mdr);
+ pi.inode->set_quiesce_block(val);
+ dout(20) << (val ? "setting" : "unsetting") << " F_QUIESCE_BLOCK on ino: " << cur->ino() << dendl;
+
+ mdr->no_early_reply = true;
+ pip = pi.inode.get();
} else if (name == "ceph.dir.subvolume"sv) {
if (!cur->is_dir()) {
respond_to_request(mdr, -CEPHFS_EINVAL);
} else {
r = -CEPHFS_ENODATA; // no such attribute
}
+ } else if (xattr_name == "ceph.quiesce.block"sv) {
+ *css << cur->get_projected_inode()->get_quiesce_block();
} else if (xattr_name.substr(0, 12) == "ceph.dir.pin"sv) {
if (xattr_name == "ceph.dir.pin"sv) {
*css << cur->get_projected_inode()->export_pin;
#include <string_view>
+using namespace std::literals::string_view_literals;
+
#include <common/DecayCounter.h>
#include "include/common_fwd.h"
return xattr_name.rfind("ceph.dir.layout", 0) == 0 ||
xattr_name.rfind("ceph.file.layout", 0) == 0 ||
xattr_name.rfind("ceph.quota", 0) == 0 ||
+ xattr_name == "ceph.quiesce.block"sv ||
xattr_name == "ceph.dir.subvolume" ||
xattr_name == "ceph.dir.pin" ||
xattr_name == "ceph.dir.pin.random" ||