]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: SnapRealm
authorSage Weil <sage@newdream.net>
Wed, 2 Jul 2008 20:30:24 +0000 (13:30 -0700)
committerSage Weil <sage@newdream.net>
Wed, 2 Jul 2008 20:30:24 +0000 (13:30 -0700)
src/Makefile.am
src/TODO
src/include/ceph_fs.h
src/mds/CInode.h
src/mds/Capability.h
src/mds/SnapTable.cc
src/mds/journal.cc
src/mds/snap.cc [new file with mode: 0644]
src/mds/snap.h

index d616484463be9737a11bf05c0c1194dc3ead403c..d05cf1b2fa9b326dec3422589916bba9273d5b19 100644 (file)
@@ -206,6 +206,7 @@ libmds_a_SOURCES = \
        mds/MDSTable.cc \
        mds/IdAllocator.cc \
        mds/SnapTable.cc \
+       mds/snap.cc \
        mds/SessionMap.cc \
        mds/MDLog.cc
 
index ea9570e0314250cc92686adeff5f1fedd62f03cc..0f370a97f3706461ad6d7cfcded2f42b207d3ee0 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -229,6 +229,8 @@ todo
 - client capgroups
 - mds snapid allocation
 - snap creation
+  - async SnapClient for the (possibly remote) SnapTable
+    - hmm, can we generalize any of AnchorClient?
 - mds metadata versioning
 - mds server ops
 
@@ -281,7 +283,7 @@ in SnapRealm,
 
 - when we create a snapshot,
   - xlock snaplock
-  - create realm, if necesarry
+  - create realm, if necessary
   - add it to the realm snaps list.
   - build list of current children
     - send client a capgroup update for each affected realm
index 4c547631c4068d64268d58467689dbe9f9c1b2d8..71ae52da3ac43c0849d6a3c4510565eaa1eda727 100644 (file)
@@ -780,6 +780,7 @@ struct ceph_mds_file_caps {
        __le32 seq;
        __le32 caps, wanted;
        __le64 ino;
+       __le64 realm;
        __le64 size, max_size;
        __le32 migrate_seq;
        struct ceph_timespec mtime, atime, ctime;
index 8a6008bce9b560a39004dafb6018e7d0de595465..528a282ad5dcd7aa95d493f964b856e77db3e7b2 100644 (file)
@@ -47,6 +47,7 @@ class CInode;
 class CInodeDiscover;
 class MDCache;
 class LogSegment;
+class SnapRealm;
 
 ostream& operator<<(ostream& out, CInode& in);
 
@@ -132,6 +133,7 @@ class CInode : public MDSCacheObject {
   string           symlink;      // symlink dest, if symlink
   map<string, bufferptr> xattrs;
   fragtree_t       dirfragtree;  // dir frag tree, if any.  always consistent with our dirfrag map.
+  SnapRealm        *snaprealm;
 
   off_t last_journaled;       // log offset for the last time i was journaled
   off_t last_open_journaled;  // log offset for the last journaled EOpen
@@ -211,7 +213,7 @@ public:
   // -- distributed state --
 protected:
   // file capabilities
-  map<int, Capability*>  client_caps;         // client -> caps
+  map<int, Capability*> client_caps;         // client -> caps
   map<int, int>         mds_caps_wanted;     // [auth] mds -> caps wanted
   int                   replica_caps_wanted; // [replica] what i've requested from auth
   utime_t               replica_caps_wanted_keep_until;
@@ -220,6 +222,7 @@ protected:
   // LogSegment xlists i (may) belong to
   xlist<CInode*>::item xlist_dirty;
 public:
+  xlist<CInode*>::item xlist_caps;
   xlist<CInode*>::item xlist_open_file;
   xlist<CInode*>::item xlist_dirty_dirfrag_dir;
   xlist<CInode*>::item xlist_dirty_dirfrag_dirfragtree;
@@ -254,13 +257,14 @@ private:
   // ---------------------------
   CInode(MDCache *c, bool auth=true) : 
     mdcache(c),
+    snaprealm(0),
     last_journaled(0), last_open_journaled(0), 
     //hack_accessed(true),
     stickydir_ref(0),
     parent(0), projected_parent(0),
     inode_auth(CDIR_AUTH_DEFAULT),
     replica_caps_wanted(0),
-    xlist_dirty(this), xlist_open_file(this), 
+    xlist_dirty(this), xlist_caps(this), xlist_open_file(this), 
     xlist_dirty_dirfrag_dir(this), 
     xlist_dirty_dirfrag_dirfragtree(this), 
     xlist_purging_inode(this),
index 6fb52ca2bee228776274b4abe1f0c80f3630b86e..911a9d7c2525244f169e322b46bac333148c1dd8 100644 (file)
@@ -73,8 +73,9 @@ public:
 
 private:
   CInode *inode;
+  xlist<Capability*>::item cap_group_item;
   __u32 wanted_caps;     // what the client wants (ideally)
-  
+
   map<capseq_t, __u32>  cap_history;  // seq -> cap, [last_recv,last_sent]
   capseq_t last_sent, last_recv;
   capseq_t last_open;
@@ -86,7 +87,7 @@ public:
   xlist<Capability*>::item session_caps_item;
 
   Capability(CInode *i=0, int want=0, capseq_t s=0) :
-    inode(i),
+    inode(i), cap_group_item(this),
     wanted_caps(want),
     last_sent(s),
     last_recv(s),
index 5481ca8efbe15d068fd978b9e7d3d0561b519696..547f262e63c23100a524b3b8c6e8f261859aa37d 100644 (file)
@@ -40,7 +40,7 @@ snapid_t SnapTable::create(inodeno_t base, const string& name, utime_t stamp)
   
   snapid_t sn = ++last_snap;
   snaps[sn].snapid = sn;
-  snaps[sn].base = base;
+  snaps[sn].dirino = base;
   snaps[sn].name = name;
   snaps[sn].stamp = stamp;
   version++;
index 62c0ce037ac94b1e5fa6533d2aa5df5a2456691a..cfddab0820a86389f9b5fd5b20b2b851e56de275 100644 (file)
@@ -639,7 +639,7 @@ void ESnap::replay(MDS *mds)
   assert(version-1 == mds->snaptable->get_version());
 
   if (create) {
-    snapid_t s = mds->snaptable->create(snap.base, snap.name, snap.stamp);
+    snapid_t s = mds->snaptable->create(snap.dirino, snap.name, snap.stamp);
     assert(s == snap.snapid);
   } else {
     mds->snaptable->remove(snap.snapid);
diff --git a/src/mds/snap.cc b/src/mds/snap.cc
new file mode 100644 (file)
index 0000000..3479d20
--- /dev/null
@@ -0,0 +1,72 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004- Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software 
+ * Foundation.  See file COPYING.
+ * 
+ */
+
+#include "snap.h"
+#include "MDCache.h"
+#include "MDS.h"
+
+
+/*
+ * SnapRealm
+ */
+
+#define dout(x) if (x < g_conf.debug_mds) *_dout << dbeginl << g_clock.now() \
+                                                << " mds" << mdcache->mds->get_nodeid() \
+                                                << ".snaprealm(" << dirino << ") "
+
+bool SnapRealm::open_parents(MDRequest *mdr)
+{
+  dout(10) << "open_parents" << dendl;
+  for (multimap<snapid_t, snaplink_t>::iterator p = parents.begin();
+       p != parents.end();
+       p++) {
+    CInode *parent = mdcache->get_inode(p->second.dirino);
+    if (parent)
+      continue;
+    mdcache->open_remote_ino(p->second.dirino, mdr, 
+                            new C_MDS_RetryRequest(mdcache, mdr));
+    return false;
+  }
+  return true;
+}
+
+/*
+ * get list of snaps for this realm.  we must include parents' snaps
+ * for the intervals during which they were our parent.
+ */
+void SnapRealm::get_snap_list(set<snapid_t> &s)
+{
+  // start with my snaps
+  for (map<snapid_t, SnapInfo>::iterator p = snaps.begin();
+       p != snaps.end();
+       p++)
+    s.insert(p->first);
+
+  // include parent snaps
+  for (multimap<snapid_t, snaplink_t>::iterator p = parents.begin();
+       p != parents.end();
+       p++) {
+    CInode *parent = mdcache->get_inode(p->second.dirino);
+    assert(parent);  // call open_parents first!
+    assert(parent->snaprealm);
+
+    for (map<snapid_t, SnapInfo>::iterator q = parent->snaprealm->snaps.begin();
+        q != parent->snaprealm->snaps.end();
+        q++)
+      if (q->first <= p->first && 
+         q->first >= p->second.first)
+       s.insert(q->first);
+  }
+  dout(10) << "build_snap_list " << s << dendl;
+}
index cf446d14bc3ea4955fd1d14bdc87a16d4bc9688b..999e37b2154a0073f40657fe31db15c1c20fe320 100644 (file)
 #ifndef __CEPH_MDS_SNAP_H
 #define __CEPH_MDS_SNAP_H
 
+#include "mdstypes.h"
+#include "include/xlist.h"
+
+/*
+ * generic snap descriptor.
+ */
 struct SnapInfo {
   snapid_t snapid;
-  inodeno_t base;
+  inodeno_t dirino;
   utime_t stamp;
   string name;
   
   void encode(bufferlist& bl) const {
     ::encode(snapid, bl);
-    ::encode(base, bl);
+    ::encode(dirino, bl);
     ::encode(stamp, bl);
     ::encode(name, bl);
   }
   void decode(bufferlist::iterator& bl) {
     ::decode(snapid, bl);
-    ::decode(base, bl);
+    ::decode(dirino, bl);
     ::decode(stamp, bl);
     ::decode(name, bl);
   }
@@ -37,7 +43,64 @@ struct SnapInfo {
 WRITE_CLASS_ENCODER(SnapInfo)
 
 inline ostream& operator<<(ostream& out, const SnapInfo &sn) {
-  return out << "snap(" << sn.snapid << " " << sn.base << " '" << sn.name << "' " << sn.stamp << ")";
+  return out << "snap(" << sn.snapid
+            << " " << sn.dirino
+            << " '" << sn.name
+            << "' " << sn.stamp << ")";
 }
 
+
+
+/*
+ * SnapRealm - a subtree that shares the same set of snapshots.
+ */
+struct SnapRealm;
+struct CapabilityGroup;
+class CInode;
+class MDCache;
+class MDRequest;
+
+struct snaplink_t {
+  inodeno_t dirino;
+  snapid_t first;
+};
+
+struct SnapRealm {
+  // realm state
+  inodeno_t dirino;
+  map<snapid_t, SnapInfo> snaps;
+  multimap<snapid_t, snaplink_t> parents, children;  // key is "last" (or NOSNAP)
+
+  // in-memory state
+  MDCache *mdcache;
+  CInode *inode;
+
+  // caches?
+  //set<snapid_t> cached_snaps;
+  //set<SnapRealm*> cached_active_children;    // active children that are currently open
+
+  xlist<CInode*> inodes_with_caps;               // for efficient realm splits
+  map<int, CapabilityGroup*> client_cap_groups;  // to identify clients who need snap notifications
+
+  SnapRealm(inodeno_t i, MDCache *c, CInode *in) : dirino(i), mdcache(c), inode(in) {}
+
+  bool open_parents(MDRequest *mdr);
+  void get_snap_list(set<snapid_t>& s);
+};
+
+
+
+/*
+ * CapabilityGroup - group per-realm, per-client caps for efficient
+ * client snap notifications.
+ */
+struct Capability;
+
+struct CapabilityGroup {
+  int client;
+  xlist<Capability*> caps;
+  SnapRealm *realm;
+};
+
+
 #endif