From 3ef32bc6b68c19858e68c73b5df746dd8d316fdf Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 24 Aug 2011 16:51:15 -0700 Subject: [PATCH] client: be careful about replacing dentries during readdir assimilation When we are assimilate readdir results into our cache, we need to be more careful about replacing existing dentries. We were calling insert_dentry_inode(), which would replace a name if it already exists, which might include pd->first, an active iterator. Move the dentry link/relink into the caller (where we already have an iterator pointing to the existing item, if any). Then update the dentry lease information separately. Fixes: #1391 Signed-off-by: Sage Weil --- src/client/Client.cc | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 4c0cd2549f89c..bc7ed03669105 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -808,9 +808,27 @@ Inode* Client::insert_trace(MetaRequest *request, utime_t from, int mds) ::decode(dname, p); ::decode(dlease, p); InodeStat ist(p, features); - + Inode *in = add_update_inode(&ist, from, mds); - Dentry *dn = insert_dentry_inode(dir, dname, &dlease, in, from, mds, false); + Dentry *dn; + if (pd != dir->dentry_map.end() && + pd->first == dname) { + Dentry *olddn = pd->second; + if (pd->second->inode != in) { + // replace incorrect dentry + pd++; + unlink(olddn, true); + dn = link(dir, dname, in, NULL); + } else { + // keep existing dn + dn = olddn; + touch_dn(dn); + } + } else { + // new dn + dn = link(dir, dname, in, NULL); + } + update_dentry_lease(dn, &dlease, from, mds); dn->offset = dir_result_t::make_fpos(request->readdir_frag, i + request->readdir_offset); // remove any extra names -- 2.39.5