]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: add vxattr that marks/clears subvolume flag
authorYan, Zheng <zyan@redhat.com>
Tue, 4 Aug 2020 13:26:26 +0000 (21:26 +0800)
committerYan, Zheng <zyan@redhat.com>
Thu, 20 Aug 2020 03:10:08 +0000 (11:10 +0800)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/Server.cc
src/mds/SnapRealm.cc
src/mds/SnapRealm.h
src/mds/snap.h

index 77f2b561436bb14610a32a72a5f758c0176226aa..10ff327119c922896de927df82d2ae33762f505d 100644 (file)
@@ -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<bool>(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;
 }
 
index bfdf013102b3089073702de24260f9b5961cebc3..7c89ba019d5874d063551d72d30b5372f76267d0 100644 (file)
@@ -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();
index 805b16bf3f7f05e9f5e3ec9537f1e1ef7dd36c17..8c7a48ef0fbf551032f977c85d384a609d6ba6fb 100644 (file)
@@ -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<snapid_t> 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);
index 227f84fccc2ce0998bfc6e478fbe6ae6d3b07eb8..346f787e37c4a5743b34a7e0c215e5acd8ab7234 100644 (file)
@@ -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)