- 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
}
-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();
}
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();
}
inode_t *oi = &inode;
inode_t *pi = get_projected_inode();
- map<string, bufferptr> *pxattrs = &xattrs;
+ map<string, bufferptr> *pxattrs = 0;
if (snapid && is_multiversion()) {
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;
// 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;
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() {
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) { }
// 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);
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)
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
// 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();
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;
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;