]> 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>
Wed, 26 Aug 2020 06:32:26 +0000 (14:32 +0800)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit 8d531680cdf48ba43d93becd5a19072844e92c19)

 Conflicts:
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 ba99b52a63df406d6ba697862d0399e2a0337a8a..4d9e65349ec3a9f20badd65a3e474c894503419d 100644 (file)
@@ -4512,15 +4512,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();
@@ -4533,10 +4535,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);
@@ -5298,7 +5299,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);
@@ -5367,28 +5368,76 @@ void Server::handle_set_vxattr(MDRequestRef& mdr, CInode *cur,
     lov.add_xlock(&cur->policylock);
     if (quota.is_enable() && !cur->get_projected_srnode()) {
       lov.add_xlock(&cur->snaplock);
-      new_realm = true;
+      adjust_realm = true;
     }
 
     if (!mds->locker->acquire_locks(mdr, lov))
       return;
 
-    auto &pi = cur->project_inode(false, new_realm);
+    if (cur->get_projected_inode()->quota == quota) {
+      respond_to_request(mdr, 0);
+      return;
+    }
+
+    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.find("ceph.dir.pin") == 0) {
+  } 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;
+    }
+
+    lov.add_xlock(&cur->policylock);
+    lov.add_xlock(&cur->snaplock);
+    if (!mds->locker->acquire_locks(mdr, lov))
+      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);
       return;
@@ -5434,7 +5483,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 ee906a3a48d357da423491c1bc2b5dcb3c3c2dc4..4ef775dc697116607bee41d3f2e6a09a5871790f 100644 (file)
@@ -333,6 +333,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 17849e4f926f667c8097321769a5cc2238f6e670..582daa2d2e047f018842cb02d3b1134d611801d0 100644 (file)
@@ -33,6 +33,7 @@ protected:
   mutable set<snapid_t> cached_snaps;
   mutable SnapContext cached_snap_context;
   mutable bufferlist cached_snap_trace;
+  mutable inodeno_t cached_subvolume_ino = 0;
 
   void check_cache() const;
 
@@ -133,6 +134,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);
index b3c00ddf78ad232e0139c88f27f3eeb0e26b7c87..41f48d8031e95818187d761f453c24475c76d6e2 100644 (file)
@@ -87,13 +87,18 @@ struct sr_t {
 
   __u32 flags;
   enum {
-    PARENT_GLOBAL = 1 << 0,
+    PARENT_GLOBAL      = 1 << 0,
+    SUBVOLUME          = 1 << 1,
   };
 
   void mark_parent_global() { flags |= PARENT_GLOBAL; }
   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; }
+
   sr_t()
     : seq(0), created(0),
       last_created(0), last_destroyed(0),