From: John Spray Date: Tue, 25 Mar 2014 13:30:53 +0000 (+0000) Subject: mds: Add get_paths method to EMetaBlob X-Git-Tag: v0.82~48^2~44 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=74ac6e4e1bdff6637b6a43882bbfcef15be4b922;p=ceph.git mds: Add get_paths method to EMetaBlob Used by cephfs-journal-tool to filter events by path fragment. Signed-off-by: John Spray --- diff --git a/src/mds/events/EMetaBlob.h b/src/mds/events/EMetaBlob.h index 4d52b7fb73a7..52ad9008408c 100644 --- a/src/mds/events/EMetaBlob.h +++ b/src/mds/events/EMetaBlob.h @@ -312,6 +312,7 @@ private: public: void encode(bufferlist& bl) const; void decode(bufferlist::iterator& bl); + int get_paths(std::vector &paths); void dump(Formatter *f) const; static void generate_test_instances(list& ls); // soft stateadd diff --git a/src/mds/journal.cc b/src/mds/journal.cc index 9e256e6ab973..54115090445b 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -814,6 +814,123 @@ void EMetaBlob::decode(bufferlist::iterator &bl) DECODE_FINISH(bl); } + +/** + * + * This is not const because the contained dirlump and 'bit' objects + * are modified by being decoded. + */ +int EMetaBlob::get_paths( + std::vector &paths) +{ + // Each dentry has a 'location' which is a 2-tuple of parent inode and dentry name + typedef std::pair Location; + + // Whenever we see a dentry within a dirlump, we remember it as a child of + // the dirlump's inode + std::map > children; + + // Whenever we see a location for an inode, remember it: this allows us to + // build a path given an inode + std::map ino_locations; + + // Special case: operations on root inode populate roots but not dirlumps + if (lump_map.empty() && !roots.empty()) { + paths.push_back("/"); + return 0; + } + + // First pass + // ========== + // Build a tiny local metadata cache for the path structure in this metablob + for (std::map::iterator i = lump_map.begin(); i != lump_map.end(); ++i) { + inodeno_t const dir_ino = i->first.ino; + dirlump &dl = i->second; + dl._decode_bits(); + + list > &fb_list = dl.get_dfull(); + list &nb_list = dl.get_dnull(); + list &rb_list = dl.get_dremote(); + + for (list >::const_iterator + iter = fb_list.begin(); iter != fb_list.end(); ++iter) { + std::string const &dentry = (*iter)->dn; + children[dir_ino].push_back(dentry); + ino_locations[(*iter)->inode.ino] = Location(dir_ino, dentry); + } + + for (list::const_iterator + iter = nb_list.begin(); iter != nb_list.end(); ++iter) { + std::string const &dentry = iter->dn; + children[dir_ino].push_back(dentry); + } + + for (list::const_iterator + iter = rb_list.begin(); iter != rb_list.end(); ++iter) { + std::string const &dentry = iter->dn; + children[dir_ino].push_back(dentry); + } + } + + std::vector leaf_locations; + + // Second pass + // =========== + // Output paths for all childless nodes in the metablob + for (std::map::iterator i = lump_map.begin(); i != lump_map.end(); ++i) { + inodeno_t const dir_ino = i->first.ino; + dirlump &dl = i->second; + dl._decode_bits(); + + list > &fb_list = dl.get_dfull(); + for (list >::const_iterator + iter = fb_list.begin(); iter != fb_list.end(); ++iter) { + std::string const &dentry = (*iter)->dn; + children[dir_ino].push_back(dentry); + ino_locations[(*iter)->inode.ino] = Location(dir_ino, dentry); + if (children.find((*iter)->inode.ino) == children.end()) { + leaf_locations.push_back(Location(dir_ino, dentry)); + + } + } + + list &nb_list = dl.get_dnull(); + for (list::const_iterator + iter = nb_list.begin(); iter != nb_list.end(); ++iter) { + std::string const &dentry = iter->dn; + leaf_locations.push_back(Location(dir_ino, dentry)); + } + + list &rb_list = dl.get_dremote(); + for (list::const_iterator + iter = rb_list.begin(); iter != rb_list.end(); ++iter) { + std::string const &dentry = iter->dn; + leaf_locations.push_back(Location(dir_ino, dentry)); + } + } + + // For all the leaf locations identified, generate paths + for (std::vector::iterator i = leaf_locations.begin(); i != leaf_locations.end(); ++i) { + Location const &loc = *i; + std::string path = loc.second; + inodeno_t ino = loc.first; + while(ino_locations.find(ino) != ino_locations.end()) { + Location const &loc = ino_locations[ino]; + if (!path.empty()) { + path = loc.second + "/" + path; + } else { + path = loc.second + path; + } + ino = loc.first; + } + + paths.push_back(path); + } + + return 0; +} + + void EMetaBlob::dump(Formatter *f) const { f->open_array_section("lumps");