]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
openc hack, works for now
authorsageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Sat, 17 Feb 2007 19:03:06 +0000 (19:03 +0000)
committersageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Sat, 17 Feb 2007 19:03:06 +0000 (19:03 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1104 29311d96-e01e-0410-9327-a35deaab8ce9

branches/sage/cephmds2/mds/Server.cc
branches/sage/cephmds2/mds/Server.h
branches/sage/cephmds2/mds/events/EString.h
branches/sage/cephmds2/mds/journal.cc

index 5ea354d76e041e705cc4f375e8dd1c8c3d22d171..e9e41414ac2bf58b7ecddc540c78e1f4eb1f8d20 100644 (file)
@@ -1164,10 +1164,15 @@ CDir *Server::validate_new_dentry_dir(MClientRequest *req, CInode *diri, string&
  * create the inode and dentry, but do not link them.
  * pre_dirty the dentry+dir.
  * xlock the dentry.
+ *
+ * return val
+ *  0 - wait for something
+ *  1 - created
+ *  2 - already exists (only if okexist=true)
  */
-bool Server::prepare_mknod(MClientRequest *req, CInode *diri, 
-                          CInode **pin, CDentry **pdn, 
-                          bool okexist) 
+int Server::prepare_mknod(MClientRequest *req, CInode *diri, 
+                         CInode **pin, CDentry **pdn, 
+                         bool okexist) 
 {
   dout(10) << "prepare_mknod " << req->get_filepath() << " in " << *diri << endl;
   
@@ -1176,7 +1181,7 @@ bool Server::prepare_mknod(MClientRequest *req, CInode *diri,
   string name = req->get_filepath().last_bit();
   
   CDir *dir = validate_new_dentry_dir(req, diri, name);
-  if (!dir) return false;
+  if (!dir) return 0;
 
   // make sure name doesn't already exist
   *pdn = dir->lookup(name);
@@ -1184,7 +1189,7 @@ bool Server::prepare_mknod(MClientRequest *req, CInode *diri,
     if (!(*pdn)->can_read(req)) {
       dout(10) << "waiting on (existing!) dentry " << **pdn << endl;
       dir->add_waiter(CDIR_WAIT_DNREAD, name, new C_MDS_RetryRequest(mds, req, diri));
-      return false;
+      return 0;
     }
 
     if (!(*pdn)->is_null()) {
@@ -1192,11 +1197,11 @@ bool Server::prepare_mknod(MClientRequest *req, CInode *diri,
       if (okexist) {
         dout(10) << "dentry " << name << " exists in " << *dir << endl;
        *pin = (*pdn)->inode;
-        return true;
+        return 2;
       } else {
         dout(10) << "dentry " << name << " exists in " << *dir << endl;
         reply_request(req, -EEXIST);
-        return false;
+        return 0;
       }
     }
   }
@@ -1205,7 +1210,7 @@ bool Server::prepare_mknod(MClientRequest *req, CInode *diri,
   if (!dir->is_complete()) {
     dout(7) << " incomplete dir contents for " << *dir << ", fetching" << endl;
     mds->mdstore->fetch_dir(dir, new C_MDS_RetryRequest(mds, req, diri));
-    return false;
+    return 0;
   }
 
   // make sure dir is pinnable
@@ -1231,7 +1236,7 @@ bool Server::prepare_mknod(MClientRequest *req, CInode *diri,
   // bump modify pop
   mds->balancer->hit_dir(dir, META_POP_DWR);
 
-  return true;
+  return 1;
 }
 
 
@@ -2234,7 +2239,7 @@ void Server::handle_client_truncate(MClientRequest *req, CInode *cur)
 // open, openc, close
 
 void Server::handle_client_open(MClientRequest *req,
-                             CInode *cur)
+                               CInode *cur)
 {
   int flags = req->get_iarg();
   int mode = req->get_iarg2();
@@ -2282,19 +2287,77 @@ void Server::handle_client_open(MClientRequest *req,
 }
 
 
+class C_MDS_openc_finish : public Context {
+  MDS *mds;
+  MClientRequest *req;
+  CDentry *dn;
+  CInode *newi;
+  version_t pv;
+public:
+  C_MDS_openc_finish(MDS *m, MClientRequest *r, CDentry *d, CInode *ni) :
+    mds(m), req(r), dn(d), newi(ni),
+    pv(d->get_projected_version()) {}
+  void finish(int r) {
+    assert(r == 0);
+
+    // link the inode
+    dn->get_dir()->link_inode(dn, newi);
+
+    // dirty inode, dn, dir
+    newi->mark_dirty(pv);
+
+    // unlock
+    mds->locker->dentry_xlock_finish(dn);
+
+    // hit pop
+    mds->balancer->hit_inode(newi, META_POP_IWR);
+
+    // ok, do the open.
+    mds->server->handle_client_open(req, newi);
+  }
+};
+
 
-void Server::handle_client_openc(MClientRequest *req, CInode *ref)
+void Server::handle_client_openc(MClientRequest *req, CInode *diri)
 {
   dout(7) << "open w/ O_CREAT on " << req->get_filepath() << endl;
 
-  assert(0);
-  CInode *in = 0;//mknod(req, ref, true);   // FIXME FIXME
-  if (!in) return;
+  CInode *in = 0;
+  CDentry *dn = 0;
+  
+  // make dentry and inode, xlock dentry.
+  int r = prepare_mknod(req, diri, &in, &dn);
+  if (!r) 
+    return; // wait on something
+  assert(in);
+  assert(dn);
 
-  in->inode.mode = 0644;              // wtf FIXME
-  in->inode.mode |= INODE_MODE_FILE;
+  if (r == 1) {
+    // created.
+    // it's a file.
+    in->inode.mode = 0644;              // FIXME req should have a umask
+    in->inode.mode |= INODE_MODE_FILE;
+
+    // prepare finisher
+    C_MDS_openc_finish *fin = new C_MDS_openc_finish(mds, req, dn, in);
+    EUpdate *le = new EUpdate("openc");
+    le->metablob.add_dir_context(diri->dir);
+    inode_t *pi = le->metablob.add_dentry(dn, true, in);
+    pi->version = dn->get_projected_version();
+    
+    // log + wait
+    mdlog->submit_entry(le);
+    mdlog->wait_for_sync(fin);
 
-  handle_client_open(req, in);
+    /*
+      FIXME. this needs to be rewritten when the write capability stuff starts
+      getting journaled.  
+    */
+  } else {
+    // exists!
+    // FIXME: do i need to repin path based existant inode? hmm.
+    handle_client_open(req, in);
+  }
 }
 
 
index 59382370ee0f9ba9a929cd70445cd5ed8fa8726c..d4509f1418e07a59f0baa42e1cc4cc67f3c7eec1 100644 (file)
@@ -127,9 +127,9 @@ public:
   CInode *mknod(MClientRequest *req, CInode *ref, bool okexist=false);  // used by mknod, symlink, mkdir, openc
 
   CDir *validate_new_dentry_dir(MClientRequest *req, CInode *diri, string& dname);
-  bool prepare_mknod(MClientRequest *req, CInode *diri, 
-                    CInode **pin, CDentry **pdn, 
-                    bool okexist=false);
+  int prepare_mknod(MClientRequest *req, CInode *diri, 
+                   CInode **pin, CDentry **pdn, 
+                   bool okexist=false);
 
 
 
index 6bd10030549bab5d7c95599031e7d911d6906bb8..0ef75774064544109ea179d64f6802d85e26f447 100644 (file)
@@ -39,7 +39,6 @@ class EString : public LogEvent {
     event = bl.c_str() + off;
     off += event.length() + 1;
   }
-  
   void encode_payload(bufferlist& bl) {
     bl.append(event.c_str(), event.length()+1);
   }
@@ -48,6 +47,10 @@ class EString : public LogEvent {
     out << '"' << event << '"';
   }
 
+  bool has_expired(MDS *mds);
+  void expire(MDS *mds, Context *c);
+  void replay(MDS *mds);
+
 };
 
 #endif
index 49af089fec4664cd1d88406902c5cbb107178b15..2182d33ffc878eabb9ccdbe103b9d3526cf3f9c9 100644 (file)
@@ -11,6 +11,8 @@
  * 
  */
 
+#include "events/EString.h"
+
 #include "events/EMetaBlob.h"
 #include "events/EAlloc.h"
 #include "events/EUpdate.h"
 #define  derr(l)    if (l<=g_conf.debug_mds || l <= g_conf.debug_mds_log) cout << g_clock.now() << " mds" << mds->get_nodeid() << ".journal "
 
 
+// -----------------------
+// EString
+
+bool EString::has_expired(MDS *mds) {
+  dout(10) << "EString.has_expired " << event << endl; 
+  return true;
+}
+void EString::expire(MDS *mds, Context *c)
+{
+  dout(10) << "EString.expire " << event << endl; 
+}
+void EString::replay(MDS *mds)
+{
+  dout(10) << "EString.replay " << event << endl; 
+}
+
+
+
 // -----------------------
 // EMetaBlob