From: Sage Weil Date: Thu, 17 Sep 2009 18:58:06 +0000 (-0700) Subject: mds: make parallel_fetch work with hard/remote links X-Git-Tag: v0.15~58 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f11918b1dbf1cb7d18e50cea91b575a5e10eb9da;p=ceph.git mds: make parallel_fetch work with hard/remote links We need to open remote ino's, and possibly add to gather (like a fetch). Required some refactoring. Killed/renamed otherwise unused traverse_to_dir. --- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 2e4cbc2ae7e..c6e2b9ce87c 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -3228,51 +3228,44 @@ void MDCache::handle_cache_rejoin_weak(MMDSCacheRejoin *weak) * @pathmap - map of inodeno to full pathnames. we remove items from this map * as we discover we have them. * - * returns a C_Gather* is there is work to do. caller is responsible for setting + * returns a C_Gather* if there is work to do. caller is responsible for setting * the C_Gather completer. */ + C_Gather *MDCache::parallel_fetch(map& pathmap, set& missing) { dout(10) << "parallel_fetch on " << pathmap.size() << " paths" << dendl; + C_Gather *gather = new C_Gather; + // scan list set fetch_queue; map::iterator p = pathmap.begin(); while (p != pathmap.end()) { - CInode *in = get_inode(p->first); - if (in) { - dout(15) << " have " << *in << dendl; + // do we have the target already? + CInode *cur = get_inode(p->first); + if (cur) { + dout(15) << " have " << *cur << dendl; pathmap.erase(p++); continue; } // traverse dout(17) << " missing " << p->first << " at " << p->second << dendl; - CDir *dir = path_traverse_to_dir(p->second); - if (!dir) { - dout(5) << " path not found " << p->first << " at " << p->second << dendl; - missing.insert(p->first); + if (parallel_fetch_traverse_dir(p->first, p->second, fetch_queue, missing, gather)) pathmap.erase(p++); - } else if (!dir->is_complete()) { - fetch_queue.insert(dir); + else p++; - } else { - // probably because the client created it and held a cap but it never committed - // to the journal, and the op hasn't replayed yet. - dout(5) << " dne (not created yet?) " << p->first << " at " << p->second << dendl; - missing.insert(p->first); - pathmap.erase(p++); - } } - if (pathmap.empty()) { + if (pathmap.empty() && gather->empty()) { dout(10) << "parallel_fetch done" << dendl; assert(fetch_queue.empty()); + delete gather; return false; } // do a parallel fetch - C_Gather *gather = new C_Gather; for (set::iterator p = fetch_queue.begin(); p != fetch_queue.end(); ++p) { @@ -3283,6 +3276,63 @@ C_Gather *MDCache::parallel_fetch(map& pathmap, set& fetch_queue, set& missing, C_Gather *gather) +{ + CInode *cur = get_inode(path.get_ino()); + if (!cur) { + dout(5) << " missing " << path << " base ino " << path.get_ino() << dendl; + missing.insert(ino); + return true; + } + + for (unsigned i=0; iis_dir()) { + dout(5) << " bad path " << path << " ENOTDIR at " << path[i] << dendl; + missing.insert(ino); + return true; + } + + frag_t fg = cur->pick_dirfrag(path[i]); + CDir *dir = cur->get_or_open_dirfrag(this, fg); + CDentry *dn = dir->lookup(path[i]); + if (!dn) { + if (!dir->is_complete()) { + // fetch dir + fetch_queue.insert(dir); + return false; + } else { + // probably because the client created it and held a cap but it never committed + // to the journal, and the op hasn't replayed yet. + dout(5) << " dne (not created yet?) " << ino << " at " << path << dendl; + missing.insert(ino); + return true; + } + } + CDentry::linkage_t *dnl = dn->get_linkage(); + cur = dnl->get_inode(); + if (!cur) { + assert(dnl->is_remote()); + cur = get_inode(dnl->get_remote_ino()); + if (cur) { + dn->link_remote(dnl, cur); + } else { + // open remote ino + open_remote_ino(dnl->get_remote_ino(), gather->new_sub()); + return false; + } + } + } + + dout(5) << " ino not found " << ino << " at " << path << dendl; + missing.insert(ino); + return true; +} + + /* @@ -5950,38 +6000,6 @@ bool MDCache::path_is_mine(filepath& path) -/** - * path_traverse_to_dir -- traverse to deepest dir we have - * - * @path - path to traverse (as far as we can) - * - * usually we _don't_ have the full path. (if we do, we return NULL.) - * also, if path calls a file a dir, we return NULL. - */ -CDir *MDCache::path_traverse_to_dir(filepath& path) -{ - CInode *cur = get_inode(path.get_ino()); - if (!cur) - return 0; // useless! - - for (unsigned i=0; iis_dir()) - return 0; - frag_t fg = cur->pick_dirfrag(path[i]); - CDir *dir = cur->get_or_open_dirfrag(this, fg); - CDentry *dn = dir->lookup(path[i]); - if (!dn) return dir; - CDentry::linkage_t *dnl = dn->get_linkage(); - assert(dnl->is_primary()); - cur = dnl->get_inode(); - } - - // hmm, we DO have the full path. - return NULL; -} - - /** * open_remote_dir -- open up a remote dirfrag * diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 89f2d263f6a..9aaa9468def 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -941,7 +941,6 @@ public: filepath path(p, 1); return path_is_mine(path); } - CDir *path_traverse_to_dir(filepath& path); void open_remote_dirfrag(CInode *diri, frag_t fg, Context *fin); CInode *get_dentry_inode(CDentry *dn, MDRequest *mdr, bool projected=false); @@ -954,6 +953,9 @@ public: void _open_remote_dentry_finish(int r, CDentry *dn, bool projected, Context *fin); C_Gather *parallel_fetch(map& pathmap, set& missing); + bool parallel_fetch_traverse_dir(inodeno_t ino, filepath& path, + set& fetch_queue, set& missing, C_Gather *gather); + void make_trace(vector& trace, CInode *in);