}
}
-int MDCache::path_traverse(MDRequestRef& mdr, MDSContextFactory& cf, // who
- const filepath& path, // what
- vector<CDentry*> *pdnvec, // result
- CInode **pin,
- int onfail)
+int MDCache::path_traverse(MDRequestRef& mdr, MDSContextFactory& cf,
+ const filepath& path, int flags,
+ vector<CDentry*> *pdnvec, CInode **pin)
{
- bool discover = (onfail == MDS_TRAVERSE_DISCOVER);
- bool null_okay = (onfail == MDS_TRAVERSE_DISCOVERXLOCK);
- bool forward = (onfail == MDS_TRAVERSE_FORWARD);
+ bool discover = (flags & MDS_TRAVERSE_DISCOVER);
+ bool forward = !discover;
+ bool last_xlocked = (flags & MDS_TRAVERSE_LAST_XLOCKED);
- ceph_assert(!forward || mdr); // forward requires a request
+ if (forward)
+ ceph_assert(mdr); // forward requires a request
snapid_t snapid = CEPH_NOSNAP;
if (mdr)
// discover?
dout(10) << "traverse: need dirfrag " << fg << ", doing discover from " << *cur << dendl;
discover_path(cur, snapid, path.postfixpath(depth), cf.build(),
- null_okay);
+ last_xlocked);
if (mds->logger) mds->logger->inc(l_mds_traverse_discover);
return 1;
}
CDentry::linkage_t *dnl = dn ? dn->get_projected_linkage() : 0;
// null and last_bit and xlocked by me?
- if (dnl && dnl->is_null() && null_okay) {
+ if (dnl && dnl->is_null() && last_xlocked) {
dout(10) << "traverse: hit null dentry at tail of traverse, succeeding" << dendl;
if (pdnvec)
pdnvec->push_back(dn);
return -EIO;
}
open_remote_dentry(dn, true, cf.build(),
- (null_okay && depth == path.depth() - 1));
+ (last_xlocked && depth == path.depth() - 1));
if (mds->logger) mds->logger->inc(l_mds_traverse_remote_ino);
return 1;
}
discover = true;
}
- if ((discover || null_okay)) {
+ if ((discover)) {
dout(7) << "traverse: discover from " << path[depth] << " from " << *curdir << dendl;
discover_path(curdir, snapid, path.postfixpath(depth), cf.build(),
- null_okay);
+ last_xlocked);
if (mds->logger) mds->logger->inc(l_mds_traverse_discover);
return 1;
}
vector<CDentry*> trace;
CF_MDS_RetryMessageFactory cf(mds, m);
MDRequestRef null_ref;
- int r = path_traverse(null_ref, cf, m->path, &trace, NULL, MDS_TRAVERSE_DISCOVER);
+ int r = path_traverse(null_ref, cf, m->path, MDS_TRAVERSE_DISCOVER, &trace);
if (r > 0)
return;
dout(0) << "handle_find_ino_reply failed with " << r << " on " << m->path
dout(5) << "trying discover on dir_update for " << path << dendl;
CF_MDS_RetryMessageFactory cf(mds, m);
MDRequestRef null_ref;
- int r = path_traverse(null_ref, cf, path, &trace, &in, MDS_TRAVERSE_DISCOVER);
+ int r = path_traverse(null_ref, cf, path, MDS_TRAVERSE_DISCOVER, &trace, &in);
if (r > 0)
return;
if (r == 0 &&
l_mdc_last,
};
+// flags for path_traverse();
+static const int MDS_TRAVERSE_DISCOVER = (1 << 0);
+static const int MDS_TRAVERSE_LAST_XLOCKED = (1 << 1);
// flags for predirty_journal_parents()
static const int PREDIRTY_PRIMARY = 1; // primary dn, adjust nested accounting
* @param mdr The MDRequest associated with the path. Can be null.
* @param cf A MDSContextFactory for waiter building.
* @param path The path to traverse to.
+ *
+ * @param flags Specifies different lookup behaviors.
+ * By default, path_traverse() forwards the request to the auth MDS if that
+ * is appropriate (ie, if it doesn't know the contents of a directory).
+ * MDS_TRAVERSE_DISCOVER: Instead of forwarding request, path_traverse()
+ * attempts to look up the path from a different MDS (and bring them into
+ * its cache as replicas).
+ * MDS_TRAVERSE_LAST_XLOCKED: path_traverse() will succeed on xlocked tail
+ * dentry (return 0 even it's null).
+ *
* @param pdnvec Data return parameter -- on success, contains a
* vector of dentries. On failure, is either empty or contains the
* full trace of traversable dentries.
* @param pin Data return parameter -- if successful, points to the inode
* associated with filepath. If unsuccessful, is null.
- * @param onfail Specifies different lookup failure behaviors. If set to
- * MDS_TRAVERSE_DISCOVERXLOCK, path_traverse will succeed on null
- * dentries (instead of returning -ENOENT). If set to
- * MDS_TRAVERSE_FORWARD, it will forward the request to the auth
- * MDS if that becomes appropriate (ie, if it doesn't know the contents
- * of a directory). If set to MDS_TRAVERSE_DISCOVER, it
- * will attempt to look up the path from a different MDS (and bring them
- * into its cache as replicas).
*
* @returns 0 on success, 1 on "not done yet", 2 on "forwarding", -errno otherwise.
* If it returns 1, the requester associated with this call has been placed
* If it returns 2 the request has been forwarded, and again the requester
* should unwind itself and back out.
*/
- int path_traverse(MDRequestRef& mdr, MDSContextFactory& cf, const filepath& path,
- vector<CDentry*> *pdnvec, CInode **pin, int onfail);
+ int path_traverse(MDRequestRef& mdr, MDSContextFactory& cf,
+ const filepath& path, int flags,
+ vector<CDentry*> *pdnvec, CInode **pin=nullptr);
CInode *cache_traverse(const filepath& path);
filepath fpath(m->get_path());
vector<CDentry*> trace;
MDRequestRef null_ref;
- int r = cache->path_traverse(null_ref, cf, fpath, &trace, NULL, MDS_TRAVERSE_DISCOVER);
+ int r = cache->path_traverse(null_ref, cf, fpath, MDS_TRAVERSE_DISCOVER, &trace);
if (r > 0) return;
if (r < 0) {
dout(7) << "handle_export_discover failed to discover or not dir " << m->get_path() << ", NAK" << dendl;
// traverse to parent dir
CInode *diri;
CF_MDS_MDRContextFactory cf(mdcache, mdr);
- int r = mdcache->path_traverse(mdr, cf, refpath, &trace, &diri, MDS_TRAVERSE_FORWARD);
+ int r = mdcache->path_traverse(mdr, cf, refpath, 0, &trace, &diri);
if (r > 0) return 0; // delayed
if (r < 0) {
if (r == -ESTALE) {
// traverse
CF_MDS_MDRContextFactory cf(mdcache, mdr);
- int r = mdcache->path_traverse(mdr, cf, refpath, &mdr->dn[n], &mdr->in[n], MDS_TRAVERSE_FORWARD);
+ int r = mdcache->path_traverse(mdr, cf, refpath, 0, &mdr->dn[n], &mdr->in[n]);
if (r > 0)
return NULL; // delayed
if (r < 0) { // error
if (!excl) {
CF_MDS_MDRContextFactory cf(mdcache, mdr);
- int r = mdcache->path_traverse(mdr, cf, req->get_filepath(),
- &mdr->dn[0], NULL, MDS_TRAVERSE_FORWARD);
+ int r = mdcache->path_traverse(mdr, cf, req->get_filepath(), 0, &mdr->dn[0]);
if (r > 0) return;
if (r == 0) {
// it existed.
vector<CDentry*> trace;
CInode *in;
CF_MDS_MDRContextFactory cf(mdcache, mdr);
- int r = mdcache->path_traverse(mdr, cf, refpath, &trace, &in, MDS_TRAVERSE_FORWARD);
+ int r = mdcache->path_traverse(mdr, cf, refpath, 0, &trace, &in);
if (r > 0) return;
if (r < 0) {
if (r == -ESTALE) {
dout(10) << " src " << srcpath << dendl;
CInode *in;
CF_MDS_MDRContextFactory cf(mdcache, mdr);
- int r = mdcache->path_traverse(mdr, cf, srcpath, &trace, &in, MDS_TRAVERSE_DISCOVERXLOCK);
+ int r = mdcache->path_traverse(mdr, cf, srcpath,
+ MDS_TRAVERSE_DISCOVER | MDS_TRAVERSE_LAST_XLOCKED,
+ &trace, &in);
if (r > 0) return;
if (r == -ESTALE) {
mdcache->find_ino_peers(srcpath.get_ino(), new C_MDS_RetryRequest(mdcache, mdr),
ceph_assert(destdir->is_auth());
CF_MDS_MDRContextFactory cf(mdcache, mdr);
- int r = mdcache->path_traverse(mdr, cf, srcpath, &srctrace, NULL, MDS_TRAVERSE_DISCOVER);
+ int r = mdcache->path_traverse(mdr, cf, srcpath, MDS_TRAVERSE_DISCOVER, &srctrace);
if (r > 0)
return; // delayed
if (r < 0) {
dout(10) << " dest " << destpath << dendl;
vector<CDentry*> trace;
CF_MDS_MDRContextFactory cf(mdcache, mdr);
- int r = mdcache->path_traverse(mdr, cf, destpath, &trace, NULL, MDS_TRAVERSE_DISCOVERXLOCK);
+ int r = mdcache->path_traverse(mdr, cf, destpath,
+ MDS_TRAVERSE_DISCOVER | MDS_TRAVERSE_LAST_XLOCKED,
+ &trace);
if (r > 0) return;
if (r == -ESTALE) {
mdcache->find_ino_peers(destpath.get_ino(), new C_MDS_RetryRequest(mdcache, mdr),
filepath srcpath(mdr->slave_request->srcdnpath);
dout(10) << " src " << srcpath << dendl;
CInode *srci = nullptr;
- r = mdcache->path_traverse(mdr, cf, srcpath, &trace, &srci, MDS_TRAVERSE_DISCOVERXLOCK);
+ r = mdcache->path_traverse(mdr, cf, srcpath,
+ MDS_TRAVERSE_DISCOVER | MDS_TRAVERSE_LAST_XLOCKED,
+ &trace, &srci);
if (r > 0) return;
ceph_assert(r == 0);
#define MDS_INO_STRAY_OWNER(i) (signed (((unsigned (i)) - MDS_INO_STRAY_OFFSET) / NUM_STRAY))
#define MDS_INO_STRAY_INDEX(i) (((unsigned (i)) - MDS_INO_STRAY_OFFSET) % NUM_STRAY)
-#define MDS_TRAVERSE_FORWARD 1
-#define MDS_TRAVERSE_DISCOVER 2 // skips permissions checks etc.
-#define MDS_TRAVERSE_DISCOVERXLOCK 3 // succeeds on (foreign?) null, xlocked dentries.
-
-
typedef int32_t mds_rank_t;
constexpr mds_rank_t MDS_RANK_NONE = -1;