]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix xattr projection
authorSage Weil <sage@newdream.net>
Thu, 22 Jan 2009 00:44:21 +0000 (16:44 -0800)
committerSage Weil <sage@newdream.net>
Thu, 22 Jan 2009 00:44:21 +0000 (16:44 -0800)
src/TODO
src/mds/CInode.cc
src/mds/CInode.h
src/mds/Server.cc
src/mds/events/EMetaBlob.h

index d9b0755c2a1f2775d74f6adca9ace9fffca019cc..fc6d06a96beb35661eb6fac1a87f3ffe10528905 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -107,7 +107,6 @@ userspace client
 - fix readdir vs fragment race by keeping a separate frag pos, and ignoring dentries below it
 
 mds
-- fix xattr projection
 - linkage vs cdentry replicas and remote rename....
 - move root inode into stray dir
 - make recovery work with early replies
index 34aebd7aa79a18b561471b4898deaffc9a60d3ea..4922e81f2ba536afc2f8170030c246a61758f2f7 100644 (file)
@@ -164,13 +164,18 @@ void CInode::print(ostream& out)
 }
 
 
-inode_t *CInode::project_inode() 
+inode_t *CInode::project_inode(map<string,bufferptr> *px
 {
   if (projected_inode.empty()) {
     projected_inode.push_back(new inode_t(inode));
+    if (px)
+      *px = xattrs;
   } else {
     projected_inode.push_back(new inode_t(*projected_inode.back()));
+    if (px)
+      *px = *get_projected_xattrs();
   }
+  projected_xattrs.push_back(px);
   dout(15) << "project_inode " << projected_inode.back() << dendl;
   return projected_inode.back();
 }
@@ -183,7 +188,15 @@ void CInode::pop_and_dirty_projected_inode(LogSegment *ls)
   mark_dirty(projected_inode.front()->version, ls);
   inode = *projected_inode.front();
   delete projected_inode.front();
+
+  map<string,bufferptr> *px = projected_xattrs.front();
+  if (px) {
+    xattrs = *px;
+    delete px;
+  }
+
   projected_inode.pop_front();
+  projected_xattrs.pop_front();
 }
 
 
@@ -1340,7 +1353,7 @@ bool CInode::encode_inodestat(bufferlist& bl, Session *session,
   inode_t *oi = &inode;
   inode_t *pi = get_projected_inode();
 
-  map<string, bufferptr> *pxattrs = &xattrs;
+  map<string, bufferptr> *pxattrs = 0;
 
   if (snapid && is_multiversion()) {
 
@@ -1475,6 +1488,10 @@ bool CInode::encode_inodestat(bufferlist& bl, Session *session,
   if (!had_latest_xattrs &&
       cap &&
       (cap->pending() & CEPH_CAP_XATTR_RDCACHE)) {
+    
+    if (!pxattrs)
+      pxattrs = pxattr ? get_projected_xattrs() : &xattrs;
+
     ::encode(*pxattrs, xbl);
     if (cap)
       cap->client_xattr_version = i->xattr_version;
index 8161d01775b71ffd86acfb452da91480b3c23557..9f7edef839fcbe53b52d014c3349ba857c7da6d6 100644 (file)
@@ -162,6 +162,9 @@ class CInode : public MDSCacheObject {
   // projected values (only defined while dirty)
   list<inode_t*>   projected_inode;
 
+  // if xattr* is null, it is defined to be the same as the previous version
+  list<map<string,bufferptr>*>   projected_xattrs;
+  
   version_t get_projected_version() {
     if (projected_inode.empty())
       return inode.version;
@@ -178,7 +181,17 @@ class CInode : public MDSCacheObject {
     else
       return projected_inode.back();
   }
-  inode_t *project_inode();
+  map<string,bufferptr> *get_projected_xattrs() {
+    if (!projected_xattrs.empty())
+      for (list<map<string,bufferptr>*>::reverse_iterator p = projected_xattrs.rbegin();
+          p != projected_xattrs.rend();
+          p++)
+       if (*p)
+         return *p;
+    return &xattrs;
+  }
+
+  inode_t *project_inode(map<string,bufferptr> *px=0);
   void pop_and_dirty_projected_inode(LogSegment *ls);
 
   inode_t *get_previous_projected_inode() {
index cdc94a9ed664c34bd97fede0536bbc6b7b0ab7d8..0639859eec4f4126182bd0468ea5209e90362f62 100644 (file)
@@ -2001,7 +2001,6 @@ class C_MDS_inode_xattr_update_finish : public Context {
   MDRequest *mdr;
   CInode *in;
 public:
-  map<string, bufferptr> xattrs;
 
   C_MDS_inode_xattr_update_finish(MDS *m, MDRequest *r, CInode *i) :
     mds(m), mdr(r), in(i) { }
@@ -2011,8 +2010,6 @@ public:
     // apply
     in->pop_and_dirty_projected_inode(mdr->ls);
     
-    in->xattrs.swap(xattrs);
-
     mdr->apply();
 
     mds->balancer->hit_inode(mdr->now, in, META_POP_IWR);   
@@ -2060,36 +2057,25 @@ void Server::handle_client_setxattr(MDRequest *mdr)
   dout(10) << "setxattr '" << name << "' len " << len << " on " << *cur << dendl;
 
   // project update
-  inode_t *pi = cur->project_inode();
+  map<string,bufferptr> *px = new map<string,bufferptr>;
+  inode_t *pi = cur->project_inode(px);
   pi->version = cur->pre_dirty();
   pi->ctime = g_clock.real_now();
   pi->xattr_version++;
+  px->erase(name);
+  (*px)[name] = buffer::create(len);
+  if (len)
+    req->get_data().copy(0, len, (*px)[name].c_str());
 
   // log + wait
   mdr->ls = mdlog->get_current_segment();
   EUpdate *le = new EUpdate(mdlog, "setxattr");
   le->metablob.add_client_req(req->get_reqid());
   mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
-
   mdcache->journal_cow_inode(mdr, &le->metablob, cur);
+  le->metablob.add_primary_dentry(cur->get_projected_parent_dn(), true, cur, pi, 0, 0, px);
 
-  C_MDS_inode_xattr_update_finish *fin = new C_MDS_inode_xattr_update_finish(mds, mdr, cur);
-  fin->xattrs = cur->xattrs;
-
-  cur->xattrs.erase(name);
-  cur->xattrs[name] = buffer::create(len);
-  if (len)
-    req->get_data().copy(0, len, cur->xattrs[name].c_str());
-  le->metablob.add_primary_dentry(cur->get_projected_parent_dn(), true, cur, pi);
-
-  early_reply(mdr, cur, 0);
-
-  fin->xattrs.swap(cur->xattrs);
-
-  mdlog->submit_entry(le, fin);
-
-  if (mdr->did_early_reply)
-    mds->locker->drop_rdlocks(mdr);
+  journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(mds, mdr, cur));
 }
 
 void Server::handle_client_removexattr(MDRequest *mdr)
@@ -2123,37 +2109,25 @@ void Server::handle_client_removexattr(MDRequest *mdr)
   dout(10) << "removexattr '" << name << "' on " << *cur << dendl;
 
   // project update
-  inode_t *pi = cur->project_inode();
+  map<string,bufferptr> *px = new map<string,bufferptr>;
+  inode_t *pi = cur->project_inode(px);
   pi->version = cur->pre_dirty();
   pi->ctime = g_clock.real_now();
   pi->xattr_version++;
+  px->erase(name);
 
   // log + wait
   mdr->ls = mdlog->get_current_segment();
   EUpdate *le = new EUpdate(mdlog, "removexattr");
   le->metablob.add_client_req(req->get_reqid());
   mdcache->predirty_journal_parents(mdr, &le->metablob, cur, 0, PREDIRTY_PRIMARY, false);
-
   mdcache->journal_cow_inode(mdr, &le->metablob, cur);
+  le->metablob.add_primary_dentry(cur->get_projected_parent_dn(), true, cur, pi, 0, 0, px);
 
-  C_MDS_inode_xattr_update_finish *fin = new C_MDS_inode_xattr_update_finish(mds, mdr, cur);
-  fin->xattrs = cur->xattrs;
-
-  cur->xattrs.erase(name);
-  le->metablob.add_primary_dentry(cur->get_projected_parent_dn(), true, cur, pi);
-
-  early_reply(mdr, cur, 0);
-
-  fin->xattrs.swap(cur->xattrs);
-
-  mdlog->submit_entry(le, fin);
-
-  if (mdr->did_early_reply)
-    mds->locker->drop_rdlocks(mdr);
+  journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(mds, mdr, cur));
 }
 
 
-
 // =================================================================
 // DIRECTORY and NAMESPACE OPS
 
index 65c6ff5cf96c1b4148e7cc13d60b5e2e29750adb..24890f3b242ac23da7a8d0ced293ea312b4f9e5b 100644 (file)
@@ -419,12 +419,14 @@ private:
 
   // return remote pointer to to-be-journaled inode
   inode_t *add_primary_dentry(CDentry *dn, bool dirty, 
-                             CInode *in=0, inode_t *pi=0, fragtree_t *pdft=0, bufferlist *psnapbl=0) {
+                             CInode *in=0, inode_t *pi=0, fragtree_t *pdft=0, bufferlist *psnapbl=0,
+                             map<string,bufferptr> *px=0) {
     return add_primary_dentry(add_dir(dn->get_dir(), false),
-                             dn, dirty, in, pi, pdft, psnapbl);
+                             dn, dirty, in, pi, pdft, psnapbl, px);
   }
   inode_t *add_primary_dentry(dirlump& lump, CDentry *dn, bool dirty, 
-                             CInode *in=0, inode_t *pi=0, fragtree_t *pdft=0, bufferlist *psnapbl=0) {
+                             CInode *in=0, inode_t *pi=0, fragtree_t *pdft=0, bufferlist *psnapbl=0,
+                             map<string,bufferptr> *px=0) {
     if (!in) 
       in = dn->get_projected_linkage()->get_inode();
 
@@ -443,7 +445,9 @@ private:
       lump.get_dfull().push_front(fullbit(dn->get_name(), 
                                          dn->first, dn->last,
                                          dn->get_projected_version(), 
-                                         in->inode, in->dirfragtree, in->xattrs, in->symlink, snapbl,
+                                         in->inode, in->dirfragtree,
+                                         px ? *px : in->xattrs,
+                                         in->symlink, snapbl,
                                          dirty));
       if (pi) lump.get_dfull().front().inode = *pi;
       return &lump.get_dfull().front().inode;
@@ -451,7 +455,9 @@ private:
       lump.get_dfull().push_back(fullbit(dn->get_name(), 
                                         dn->first, dn->last,
                                         dn->get_projected_version(),
-                                        in->inode, in->dirfragtree, in->xattrs, in->symlink, snapbl,
+                                        in->inode, in->dirfragtree,
+                                        px ? *px : in->xattrs,
+                                        in->symlink, snapbl,
                                         dirty));
       if (pi) lump.get_dfull().back().inode = *pi;
       return &lump.get_dfull().back().inode;