]> 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)
committerPatrick Donnelly <pdonnell@redhat.com>
Sat, 12 Dec 2020 21:58:00 +0000 (13:58 -0800)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit 8d531680cdf48ba43d93becd5a19072844e92c19)

Conflicts: resolutions similar to nautilus backport
src/mds/Server.cc
src/mds/SnapRealm.h
src/mds/snap.h

src/mds/Server.cc
src/mds/SnapRealm.cc
src/mds/SnapRealm.h
src/mds/snap.h

index e1d9f1172fbc7b1605025d5e71a21694cc5666da..946c24e19deca0c7c5cde4382be326916e191881 100644 (file)
@@ -4679,15 +4679,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
     in->pop_and_dirty_projected_inode(mdr->ls);
     mdr->apply();
@@ -4700,10 +4702,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);
@@ -5498,7 +5499,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);
@@ -5565,26 +5566,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(false, new_realm);
+    auto &pi = cur->project_inode(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;
 
     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(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;
+    adjust_realm = true;
   } else if (name == "ceph.dir.pin"sv) {
     if (!cur->is_dir() || cur->is_root()) {
       respond_to_request(mdr, -EINVAL);
@@ -5680,7 +5727,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 6e62e3898bcb4b4f27c2b709710afeef036f8d8c..8e749f09f741fb62f26568fda1c44011ffdc638b 100644 (file)
@@ -102,6 +102,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);
@@ -156,6 +161,7 @@ private:
   mutable set<snapid_t> cached_snaps;
   mutable SnapContext cached_snap_context;
   mutable bufferlist cached_snap_trace;
+  mutable inodeno_t cached_subvolume_ino = 0;
 };
 
 ostream& operator<<(ostream& out, const SnapRealm &realm);
index 9ebadb1255bb380d0810c3bbf47b91dc135521ef..8081316d4df35affbc7a066b590ba01e423f10b7 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(bufferlist &bl) const;
   void decode(bufferlist::const_iterator &bl);
   void dump(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)