mirror of
https://github.com/ceph/ceph
synced 2025-01-18 09:02:08 +00:00
mds: fix fast create + rm failure
The inode projected_version() needs to be accurate or we run into problems later. So, change the way the inode creation version is initialized by moving the hack to right before mark_dirty() is called (to keep the v < pv assertion in place).
This commit is contained in:
parent
7eeca0bbdf
commit
461cb1a643
@ -79,6 +79,8 @@ ostream& operator<<(ostream& out, CInode& in)
|
||||
out << " " << in.dirfragtree;
|
||||
|
||||
out << " v" << in.get_version();
|
||||
if (in.get_projected_version() > in.get_version())
|
||||
out << " pv" << in.get_projected_version();
|
||||
|
||||
if (in.is_auth_pinned()) {
|
||||
out << " ap=" << in.get_num_auth_pins();
|
||||
@ -493,11 +495,7 @@ void CInode::name_stray_dentry(string& dname)
|
||||
version_t CInode::pre_dirty()
|
||||
{
|
||||
assert(parent || projected_parent.size());
|
||||
version_t pv;
|
||||
if (projected_parent.size())
|
||||
pv = projected_parent.front()->pre_dirty(get_projected_version());
|
||||
else
|
||||
pv = parent->pre_dirty();
|
||||
version_t pv = get_projected_parent_dn()->pre_dirty(get_projected_version());
|
||||
dout(10) << "pre_dirty " << pv << " (current v " << inode.version << ")" << dendl;
|
||||
return pv;
|
||||
}
|
||||
|
@ -2303,7 +2303,10 @@ public:
|
||||
// link the inode
|
||||
dn->pop_projected_linkage();
|
||||
|
||||
// dirty inode, dn, dir
|
||||
// be a bit hacky with the inode version, here.. we decrement it
|
||||
// just to keep mark_dirty() happen. (we didn't bother projecting
|
||||
// a new version of hte inode since it's just been created)
|
||||
newi->inode.version--;
|
||||
newi->mark_dirty(newi->inode.version + 1, mdr->ls);
|
||||
|
||||
// mkdir?
|
||||
@ -2347,7 +2350,7 @@ void Server::handle_client_mknod(MDRequest *mdr)
|
||||
newi->inode.mode = req->head.args.mknod.mode;
|
||||
if ((newi->inode.mode & S_IFMT) == 0)
|
||||
newi->inode.mode |= S_IFREG;
|
||||
newi->inode.version = dn->pre_dirty() - 1;
|
||||
newi->inode.version = dn->pre_dirty();
|
||||
newi->inode.rstat.rfiles = 1;
|
||||
|
||||
dn->first = newi->first = follows+1;
|
||||
@ -2398,7 +2401,7 @@ void Server::handle_client_mkdir(MDRequest *mdr)
|
||||
newi->inode.mode &= ~S_IFMT;
|
||||
newi->inode.mode |= S_IFDIR;
|
||||
newi->inode.layout = g_default_mds_dir_layout;
|
||||
newi->inode.version = dn->pre_dirty() - 1;
|
||||
newi->inode.version = dn->pre_dirty();
|
||||
newi->inode.rstat.rsubdirs = 1;
|
||||
|
||||
dn->first = newi->first = follows+1;
|
||||
@ -2467,7 +2470,7 @@ void Server::handle_client_symlink(MDRequest *mdr)
|
||||
newi->inode.size = newi->symlink.length();
|
||||
newi->inode.rstat.rbytes = newi->inode.size;
|
||||
newi->inode.rstat.rfiles = 1;
|
||||
newi->inode.version = dn->pre_dirty() - 1;
|
||||
newi->inode.version = dn->pre_dirty();
|
||||
|
||||
dn->first = newi->first = follows+1;
|
||||
|
||||
@ -3233,8 +3236,10 @@ void Server::_unlink_local(MDRequest *mdr, CDentry *dn, CDentry *straydn)
|
||||
EUpdate *le = new EUpdate(mdlog, "unlink_local");
|
||||
le->metablob.add_client_req(mdr->reqid);
|
||||
|
||||
if (dnl->is_primary())
|
||||
if (straydn) {
|
||||
assert(dnl->is_primary());
|
||||
straydn->push_projected_linkage(dnl->get_inode());
|
||||
}
|
||||
|
||||
// the unlinked dentry
|
||||
dn->pre_dirty();
|
||||
|
Loading…
Reference in New Issue
Block a user