From: Yan, Zheng Date: Tue, 4 Aug 2020 13:26:26 +0000 (+0800) Subject: mds: add vxattr that marks/clears subvolume flag X-Git-Tag: wip-pdonnell-testing-20200918.022351~305^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8d531680cdf48ba43d93becd5a19072844e92c19;p=ceph-ci.git mds: add vxattr that marks/clears subvolume flag Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 77f2b561436..10ff327119c 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -4699,15 +4699,17 @@ void Server::handle_client_readdir(MDRequestRef& mdr) */ class C_MDS_inode_update_finish : public ServerLogContext { CInode *in; - bool truncating_smaller, changed_ranges, new_realm; + bool truncating_smaller, changed_ranges, adjust_realm; public: C_MDS_inode_update_finish(Server *s, MDRequestRef& r, CInode *i, - bool sm=false, bool cr=false, bool nr=false) : + bool sm=false, bool cr=false, bool ar=false) : ServerLogContext(s, r), in(i), - truncating_smaller(sm), changed_ranges(cr), new_realm(nr) { } + truncating_smaller(sm), changed_ranges(cr), adjust_realm(ar) { } void finish(int r) override { ceph_assert(r == 0); + int snap_op = (in->snaprealm ? CEPH_SNAP_OP_UPDATE : CEPH_SNAP_OP_SPLIT); + // apply mdr->apply(); @@ -4719,10 +4721,9 @@ public: mds->mdcache->truncate_inode(in, mdr->ls); } - if (new_realm) { - int op = CEPH_SNAP_OP_SPLIT; - mds->mdcache->send_snap_update(in, 0, op); - mds->mdcache->do_realm_invalidate_and_update_notify(in, op); + if (adjust_realm) { + mds->mdcache->send_snap_update(in, 0, snap_op); + mds->mdcache->do_realm_invalidate_and_update_notify(in, snap_op); } get_mds()->balancer->hit_inode(in, META_POP_IWR); @@ -5508,7 +5509,7 @@ void Server::handle_set_vxattr(MDRequestRef& mdr, CInode *cur) return; } - bool new_realm = false; + bool adjust_realm = false; if (name.compare(0, 15, "ceph.dir.layout") == 0) { if (!cur->is_dir()) { respond_to_request(mdr, -EINVAL); @@ -5575,26 +5576,72 @@ void Server::handle_set_vxattr(MDRequestRef& mdr, CInode *cur) } if (quota.is_enable() && !cur->get_projected_srnode()) - new_realm = true; + adjust_realm = true; + + if (!xlock_policylock(mdr, cur, false, adjust_realm)) + return; - if (!xlock_policylock(mdr, cur, false, new_realm)) + if (cur->get_projected_inode()->quota == quota) { + respond_to_request(mdr, 0); return; + } - auto pi = cur->project_inode(mdr, false, new_realm); + auto pi = cur->project_inode(mdr, false, adjust_realm); pi.inode->quota = quota; - if (new_realm) { - SnapRealm *realm = cur->find_snaprealm(); - auto seq = realm->get_newest_seq(); - auto &newsnap = *pi.snapnode; - newsnap.created = seq; - newsnap.seq = seq; - } + if (adjust_realm) + pi.snapnode->created = pi.snapnode->seq = cur->find_snaprealm()->get_newest_seq(); + mdr->no_early_reply = true; pip = pi.inode.get(); client_t exclude_ct = mdr->get_client(); mdcache->broadcast_quota_to_client(cur, exclude_ct, true); + } else if (name == "ceph.dir.subvolume"sv) { + if (!cur->is_dir()) { + respond_to_request(mdr, -EINVAL); + return; + } + + bool val; + try { + val = boost::lexical_cast(value); + } catch (boost::bad_lexical_cast const&) { + dout(10) << "bad vxattr value, unable to parse bool for " << name << dendl; + respond_to_request(mdr, -EINVAL); + return; + } + + if (!xlock_policylock(mdr, cur, false, true)) + return; + + SnapRealm *realm = cur->find_snaprealm(); + if (val) { + inodeno_t subvol_ino = realm->get_subvolume_ino(); + // can't create subvolume inside another subvolume + if (subvol_ino && subvol_ino != cur->ino()) { + respond_to_request(mdr, -EINVAL); + return; + } + } + + const auto srnode = cur->get_projected_srnode(); + if (val == (srnode && srnode->is_subvolume())) { + respond_to_request(mdr, 0); + return; + } + + auto pi = cur->project_inode(mdr, false, true); + if (!srnode) + pi.snapnode->created = pi.snapnode->seq = realm->get_newest_seq(); + if (val) + pi.snapnode->mark_subvolume(); + else + pi.snapnode->clear_subvolume(); + + mdr->no_early_reply = true; + pip = pi.inode.get(); + adjust_realm = true; } else if (name == "ceph.dir.pin"sv) { if (!cur->is_dir() || cur->is_root()) { respond_to_request(mdr, -EINVAL); @@ -5690,7 +5737,7 @@ void Server::handle_set_vxattr(MDRequestRef& mdr, CInode *cur) mdcache->journal_dirty_inode(mdr.get(), &le->metablob, cur); journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(this, mdr, cur, - false, false, new_realm)); + false, false, adjust_realm)); return; } diff --git a/src/mds/SnapRealm.cc b/src/mds/SnapRealm.cc index bfdf013102b..7c89ba019d5 100644 --- a/src/mds/SnapRealm.cc +++ b/src/mds/SnapRealm.cc @@ -332,6 +332,13 @@ void SnapRealm::check_cache() const cached_seq = seq; cached_last_created = last_created; cached_last_destroyed = last_destroyed; + + cached_subvolume_ino = 0; + if (parent) + cached_subvolume_ino = parent->get_subvolume_ino(); + if (!cached_subvolume_ino && srnode.is_subvolume()) + cached_subvolume_ino = inode->ino(); + build_snap_set(); build_snap_trace(); diff --git a/src/mds/SnapRealm.h b/src/mds/SnapRealm.h index 805b16bf3f7..8c7a48ef0fb 100644 --- a/src/mds/SnapRealm.h +++ b/src/mds/SnapRealm.h @@ -100,6 +100,11 @@ public: return (p != s.end() && *p <= last); } + inodeno_t get_subvolume_ino() { + check_cache(); + return cached_subvolume_ino; + } + void adjust_parent(); void split_at(SnapRealm *child); @@ -154,6 +159,7 @@ private: mutable std::set cached_snaps; mutable SnapContext cached_snap_context; mutable ceph::buffer::list cached_snap_trace; + mutable inodeno_t cached_subvolume_ino = 0; }; std::ostream& operator<<(std::ostream& out, const SnapRealm &realm); diff --git a/src/mds/snap.h b/src/mds/snap.h index 227f84fccc2..346f787e37c 100644 --- a/src/mds/snap.h +++ b/src/mds/snap.h @@ -74,6 +74,10 @@ struct sr_t { void clear_parent_global() { flags &= ~PARENT_GLOBAL; } bool is_parent_global() const { return flags & PARENT_GLOBAL; } + void mark_subvolume() { flags |= SUBVOLUME; } + void clear_subvolume() { flags &= ~SUBVOLUME; } + bool is_subvolume() const { return flags & SUBVOLUME; } + void encode(ceph::buffer::list &bl) const; void decode(ceph::buffer::list::const_iterator &bl); void dump(ceph::Formatter *f) const; @@ -90,7 +94,8 @@ struct sr_t { __u32 flags = 0; enum { - PARENT_GLOBAL = 1 << 0, + PARENT_GLOBAL = 1 << 0, + SUBVOLUME = 1 << 1, }; }; WRITE_CLASS_ENCODER(sr_t)