]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
allow leases on snapped metadata
authorSage Weil <sage@newdream.net>
Wed, 23 Jul 2008 22:52:28 +0000 (15:52 -0700)
committerSage Weil <sage@newdream.net>
Wed, 23 Jul 2008 23:51:37 +0000 (16:51 -0700)
src/TODO
src/client/Client.cc
src/include/ceph_fs.h
src/mds/Locker.cc
src/mds/MDCache.cc
src/messages/MClientLease.h

index 9df7010e36e375bd5eadfbe674b442bf0d313f31..acf83955aab34e8242283ff42b3a25d6fb654af9 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -249,7 +249,6 @@ todo
 
 - for simplicity, don't replicate any snapshot data.
 
-- need rsnaprealms in fraginfo_t
 - rename() needs to create a new realm if src/dst realms differ and (rrealms, or open_children, or not subtree leaf) (similar logic to the anchor update)
 
 - will snapshots and CAS play nice?
index fe86aa642a069fdd08c47e9c1b9675d1042c7746..a2211c81da53222cf16e4c58797e5d6c0d058736 100644 (file)
@@ -1294,7 +1294,7 @@ void Client::handle_lease(MClientLease *m)
   
  revoke:
   messenger->send_message(new MClientLease(CEPH_MDS_LEASE_RELEASE,
-                                          m->get_mask(), m->get_ino(), m->dname),
+                                          m->get_mask(), m->get_ino(), m->get_first(), m->get_last(), m->dname),
                          m->get_source_inst());
   delete m;
 }
@@ -1323,7 +1323,7 @@ void Client::release_lease(Inode *in, Dentry *dn, int mask)
   if (mds >= 0 && mdsmap->is_up(mds)) {
     dout(10) << "release_lease mds" << mds << " mask " << mask
             << " on " << in->ino() << " " << dname << dendl;
-    messenger->send_message(new MClientLease(CEPH_MDS_LEASE_RELEASE, mask, in->ino(), dname),
+    messenger->send_message(new MClientLease(CEPH_MDS_LEASE_RELEASE, mask, in->ino(), in->snapid, in->snapid, dname),
                            mdsmap->get_inst(mds));
   }
 }
index f89645f73570a86e9aa62515dbb5fb7b873ea397..3249fe4aaa7537d96ba002eba1047cd847b10cfb 100644 (file)
@@ -826,6 +826,7 @@ struct ceph_mds_lease {
        __u8 action;
        __le16 mask;
        __le64 ino;
+       __le64 first, last;
 } __attribute__ ((packed));
 /* followed by a __le32+string for dname */
 
index 34a17fd76aa3b1a8a26068af879f0dfce159d644..67903d58b4aab70bb73fb7a26e99cb1bc3522589 100644 (file)
@@ -1163,9 +1163,9 @@ void Locker::handle_client_lease(MClientLease *m)
   assert(m->get_source().is_client());
   int client = m->get_source().num();
 
-  CInode *in = mdcache->get_inode(m->get_ino());
+  CInode *in = mdcache->get_inode(m->get_ino(), m->get_last());
   if (!in) {
-    dout(7) << "handle_client_lease don't have ino " << m->get_ino() << dendl;
+    dout(7) << "handle_client_lease don't have ino " << m->get_ino() << "." << m->get_last() << dendl;
     delete m;
     return;
   }
@@ -1298,13 +1298,13 @@ void Locker::revoke_client_leases(SimpleLock *lock)
       mds->send_message_client(new MClientLease(CEPH_MDS_LEASE_REVOKE,
                                                mask,
                                                dn->get_dir()->ino(),
+                                               dn->get_dir()->get_inode()->first, CEPH_NOSNAP,
                                                dn->get_name()),
                               l->client);
     } else {
       CInode *in = (CInode*)lock->get_parent();
       mds->send_message_client(new MClientLease(CEPH_MDS_LEASE_REVOKE,
-                                               lock->get_type(),
-                                               in->ino()),
+                                               lock->get_type(), in->ino(), in->first, in->last),
                               l->client);
     }
   }
index 1871cb5151e4f2c1f61275262a8ce51df04aa350..d5f91f804e4d8197542876db90337fa9c88d5d5b 100644 (file)
@@ -1008,6 +1008,21 @@ CInode *MDCache::cow_inode(CInode *in, snapid_t last)
   else
     oldin->inode.max_size = 0;
 
+  // clone leases?
+  if (in->last != CEPH_NOSNAP) {
+    // only if we are not the head, and our lease may cover an
+    // instance in either the old or new inodes valid interval.
+    for (hash_map<int,ClientLease*>::iterator p = in->client_lease_map.begin();
+        p != in->client_lease_map.end();
+        p++) {
+      dout(10) << " cloning client" << p->first << " lease on " << p->second->mask << " to cloned inode" << dendl;
+      ClientLease *l = oldin->add_client_lease(p->first, p->second->mask);
+      l->ttl = p->second->ttl;
+      p->second->session_lease_item.get_xlist()->push_back(&l->session_lease_item);
+      p->second->lease_item.get_xlist()->push_back(&l->lease_item);
+    }
+  }
+
   return oldin;
 }
 
@@ -1295,6 +1310,7 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
   // build list of inodes to wrlock, dirty, and update
   list<CInode*> lsi;
   CInode *cur = in;
+  CDentry *parentdn = cur->get_projected_parent_dn();
   while (parent) {
     //assert(cur->is_auth() || !primary_dn);  // this breaks the rename auth twiddle hack
     assert(parent->is_auth());
@@ -1337,26 +1353,38 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
 
     
     // rstat
-    SnapRealm *prealm = parent->inode->find_snaprealm();
-    snapid_t latest = prealm->get_latest_snap();
-
-    snapid_t follows = cfollows;
-    if (follows == CEPH_NOSNAP || follows == 0)
-      follows = latest;
-
-    snapid_t first = follows+1;
-    if (cur->first > first)
-      first = cur->first;
     if (primary_dn) { 
+      SnapRealm *prealm = parent->inode->find_snaprealm();
+      snapid_t latest = prealm->get_latest_snap();
+      
+      snapid_t follows = cfollows;
+      if (follows == CEPH_NOSNAP || follows == 0)
+       follows = latest;
+      
+      snapid_t first = follows+1;
+      if (cur->first > first)
+       first = cur->first;
+
       dout(10) << "    frag head is [" << parent->first << ",head] " << dendl;
       dout(10) << " inode update is [" << first << "," << cur->last << "]" << dendl;
-      project_rstat_inode_to_frag(*curi, first, cur->last, parent, linkunlink);
+
+      /*
+       * FIXME.  this incompletely propagates rstats to _old_ parents
+       * (i.e. shortly after a directory rename).  but we need full
+       * blow hard link backpointers to make this work properly...
+       */
+      snapid_t floor = parentdn->first;
+      dout(10) << " floor of " << floor << " from parent dn " << *parentdn << dendl;
+
+      if (cur->last >= floor)
+       project_rstat_inode_to_frag(*curi, MAX(first, floor), cur->last, parent, linkunlink);
       
       for (set<snapid_t>::iterator p = cur->dirty_old_rstats.begin();
           p != cur->dirty_old_rstats.end();
           p++) {
        old_inode_t& old = cur->old_inodes[*p];
-       project_rstat_inode_to_frag(old.inode, old.first, *p, parent);
+       if (*p >= floor)
+         project_rstat_inode_to_frag(old.inode, MAX(old.first, floor), *p, parent);
       }
       cur->dirty_old_rstats.clear();
     }
@@ -1398,7 +1426,7 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
     mut->add_projected_inode(pin);
     lsi.push_front(pin);
 
-    pin->pre_cow_old_inode();  // avoid cow mayhem
+    pin->pre_cow_old_inode();  // avoid cow mayhem!
 
     inode_t *pi = pin->project_inode();
     pi->version = pin->pre_dirty();
@@ -1415,24 +1443,32 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
       dout(15) << "predirty_journal_parents     gives " << pi->dirstat << " on " << *pin << dendl;
     }
 
-    // parent dn [first,last]?
-    CDentry *parentdn = cur->get_projected_parent_dn();
-    dout(10) << "predirty_journal_parents parentdn is " << *parentdn << dendl;
+    /* 
+     * the rule here is to follow the _oldest_ parent with dirty rstat
+     * data.  if we don't propagate all data, we add ourselves to the
+     * nudge list.  that way all rstat data will (eventually) get
+     * pushed up the tree.
+     *
+     * actually, no.  for now, silently drop rstats for old parents.  we need 
+     * hard link backpointers to do the above properly.
+     */
+    parentdn = pin->get_projected_parent_dn();
 
     // rstat
     if (primary_dn) {
-      project_rstat_frag_to_inode(*pf, first, CEPH_NOSNAP, pin, false);
       for (map<snapid_t,old_fnode_t>::iterator p = parent->dirty_old_fnodes.begin();
           p != parent->dirty_old_fnodes.end();
           p++)
        project_rstat_frag_to_inode(p->second.fnode, p->second.first, p->first, pin, false);
       parent->dirty_old_fnodes.clear();
+      
+      project_rstat_frag_to_inode(*pf, pin->first, CEPH_NOSNAP, pin, false);
     }
 
     // next parent!
     cur = pin;
     curi = pi;
-    parent = cur->get_projected_parent_dn()->get_dir();
+    parent = parentdn->get_dir();
     linkunlink = 0;
     do_parent_mtime = false;
     primary_dn = true;
@@ -1442,15 +1478,10 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
   assert(parent->is_auth());
   blob->add_dir_context(parent);
   blob->add_dir(parent, true);
-  SnapRealm *realm = 0;
   for (list<CInode*>::iterator p = lsi.begin();
        p != lsi.end();
        p++) {
     CInode *cur = *p;
-    if (!realm)
-      realm = cur->find_snaprealm();
-    else if (cur->snaprealm)
-      realm = cur->snaprealm;
     journal_dirty_inode(blob, cur);
   }
  
index 0e12803dd751280db07890f55666f59fbcf5885c..2beef88efb099089b07721277b7a82c86fafa7d6 100644 (file)
@@ -36,20 +36,26 @@ struct MClientLease : public Message {
   int get_action() { return h.action; }
   int get_mask() { return h.mask; }
   inodeno_t get_ino() { return inodeno_t(h.ino); }
+  snapid_t get_first() { return snapid_t(h.first); }
+  snapid_t get_last() { return snapid_t(h.last); }
 
   MClientLease() : Message(CEPH_MSG_CLIENT_LEASE) {}
-  MClientLease(int ac, int m, __u64 i) :
+  MClientLease(int ac, int m, __u64 i, __u64 sf, __u64 sl) :
     Message(CEPH_MSG_CLIENT_LEASE) {
     h.action = ac;
     h.mask = m;
     h.ino = i;
+    h.first = sf;
+    h.last = sl;
   }
-  MClientLease(int ac, int m, __u64 i, const nstring& d) :
+  MClientLease(int ac, int m, __u64 i, __u64 sf, __u64 sl, const nstring& d) :
     Message(CEPH_MSG_CLIENT_LEASE),
     dname(d) {
     h.action = ac;
     h.mask = m;
     h.ino = i;
+    h.first = sf;
+    h.last = sl;
   }
 
   const char *get_type_name() { return "client_lease"; }
@@ -57,6 +63,8 @@ struct MClientLease : public Message {
     out << "client_lease(a=" << get_lease_action_name(get_action())
        << " mask " << get_mask();
     out << " " << get_ino();
+    if (h.last != CEPH_NOSNAP)
+      out << " [" << snapid_t(h.first) << "," << snapid_t(h.last) << "]";
     if (dname.length())
       out << "/" << dname;
     out << ")";