From 4c75e0a8b704c81819582fb1e32671c36990ef3a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 21 Jan 2009 16:44:21 -0800 Subject: [PATCH] mds: fix xattr projection --- src/TODO | 1 - src/mds/CInode.cc | 21 +++++++++++++-- src/mds/CInode.h | 15 ++++++++++- src/mds/Server.cc | 52 ++++++++++---------------------------- src/mds/events/EMetaBlob.h | 16 ++++++++---- 5 files changed, 57 insertions(+), 48 deletions(-) diff --git a/src/TODO b/src/TODO index d9b0755c2a1f2..fc6d06a96beb3 100644 --- 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 diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 34aebd7aa79a1..4922e81f2ba53 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -164,13 +164,18 @@ void CInode::print(ostream& out) } -inode_t *CInode::project_inode() +inode_t *CInode::project_inode(map *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 *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 *pxattrs = &xattrs; + map *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; diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 8161d01775b71..9f7edef839fcb 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -162,6 +162,9 @@ class CInode : public MDSCacheObject { // projected values (only defined while dirty) list projected_inode; + // if xattr* is null, it is defined to be the same as the previous version + list*> 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 *get_projected_xattrs() { + if (!projected_xattrs.empty()) + for (list*>::reverse_iterator p = projected_xattrs.rbegin(); + p != projected_xattrs.rend(); + p++) + if (*p) + return *p; + return &xattrs; + } + + inode_t *project_inode(map *px=0); void pop_and_dirty_projected_inode(LogSegment *ls); inode_t *get_previous_projected_inode() { diff --git a/src/mds/Server.cc b/src/mds/Server.cc index cdc94a9ed664c..0639859eec4f4 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -2001,7 +2001,6 @@ class C_MDS_inode_xattr_update_finish : public Context { MDRequest *mdr; CInode *in; public: - map 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 *px = new map; + 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 *px = new map; + 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 diff --git a/src/mds/events/EMetaBlob.h b/src/mds/events/EMetaBlob.h index 65c6ff5cf96c1..24890f3b242ac 100644 --- a/src/mds/events/EMetaBlob.h +++ b/src/mds/events/EMetaBlob.h @@ -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 *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 *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; -- 2.39.5