]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: add inode on IMPORT
authorSage Weil <sage@newdream.net>
Wed, 7 Sep 2011 16:48:35 +0000 (09:48 -0700)
committerSage Weil <sage@newdream.net>
Wed, 7 Sep 2011 16:48:35 +0000 (09:48 -0700)
If we get an IMPORT and don't have the inode, add it.  This fixes a race
like:

 mds0 -> client .. mknod reply (or similar)
 mds0 -> mds1 .. migrate cap
 mds1 -> client .. send IMPORT
 client <- mds1 .. rx IMPORT, but don't have inode
 client <- mds0 .. rx mknod reply, add it.

With this fix, we add the inode and set up the cap on IMPORT, and when we
get the mknod reply we update the inode immutable fields that aren't
present in the cap message (rdev, symlink target).

Fixes: #1513
Signed-off-by: Sage Weil <sage@newdream.net>
src/client/Client.cc

index 7e3a0b7c06fc406ba3c5249937f0b5045814e5c5..1a63320c39b9483ad9f0fcb5561ccbb2d0ea006e 100644 (file)
@@ -459,6 +459,7 @@ void Client::update_inode_file_bits(Inode *in,
 Inode * Client::add_update_inode(InodeStat *st, utime_t from, int mds)
 {
   Inode *in;
+  bool was_new = false;
   if (inode_map.count(st->vino)) {
     in = inode_map[st->vino];
     ldout(cct, 12) << "add_update_inode had " << *in << " caps " << ccap_string(st->cap.caps) << dendl;
@@ -476,14 +477,16 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, int mds)
     // immutable bits
     in->ino = st->vino.ino;
     in->snapid = st->vino.snapid;
-    in->rdev = st->rdev;
     in->mode = st->mode & S_IFMT;
-    if (new_root) ldout(cct, 10) << "setting this inode as root! " << *in << "; ino: " << root->ino << "; snapid" << root->snapid << dendl;
-    if (in->is_symlink())
-      in->symlink = st->symlink;
+    was_new = true;
+  }
+
+  in->rdev = st->rdev;
+  if (in->is_symlink())
+    in->symlink = st->symlink;
 
+  if (was_new)
     ldout(cct, 12) << "add_update_inode adding " << *in << " caps " << ccap_string(st->cap.caps) << dendl;
-  }
 
   if (!st->cap.caps)
     return in;   // as with readdir returning indoes in different snaprealms (no caps!)
@@ -2909,9 +2912,21 @@ void Client::handle_caps(MClientCaps *m)
   if (inode_map.count(vino))
     in = inode_map[vino];
   if (!in) {
-    ldout(cct, 5) << "handle_caps don't have vino " << vino << dendl;
-    m->put();
-    return;
+    if (m->get_op() == CEPH_CAP_OP_IMPORT) {
+      ldout(cct, 5) << "handle_caps adding ino " << vino << " on IMPORT" << dendl;
+      in = new Inode(cct, vino, &m->get_layout());
+      inode_map[vino] = in;
+      in->ino = vino.ino;
+      in->snapid = vino.snapid;
+      in->mode = m->head.mode;
+    } else {
+      ldout(cct, 5) << "handle_caps don't have vino " << vino << ", dropping" << dendl;
+      m->put();
+
+      // in case the mds is waiting on e.g. a revocation
+      flush_cap_releases();
+      return;
+    }
   }
 
   switch (m->get_op()) {