bool rdlock_path = (flags & MDS_TRAVERSE_RDLOCK_PATH);
bool xlock_dentry = (flags & MDS_TRAVERSE_XLOCK_DENTRY);
bool rdlock_authlock = (flags & MDS_TRAVERSE_RDLOCK_AUTHLOCK);
+ bool forimport = (flags & MDS_TRAVERSE_IMPORT);
if (forward)
ceph_assert(mdr); // forward requires a request
curdir = cur->get_or_open_dirfrag(this, fg);
} else {
// discover?
- dout(10) << "traverse: need dirfrag " << fg << ", doing discover from " << *cur << dendl;
- discover_path(cur, snapid, path.postfixpath(depth), cf.build(),
- path_locked);
- if (mds->logger) mds->logger->inc(l_mds_traverse_discover);
- return 1;
+ if (forimport && cur->is_quiesced()) {
+ /* block discover for import */
+ dout(5) << __func__ << ": blocking discover due to quiesced parent: " << *cur << dendl;
+ return -CEPHFS_EAGAIN;
+ } else {
+ dout(10) << "traverse: need dirfrag " << fg << ", doing discover from " << *cur << dendl;
+ discover_path(cur, snapid, path.postfixpath(depth), cf.build(),
+ path_locked);
+ if (mds->logger) mds->logger->inc(l_mds_traverse_discover);
+ return 1;
+ }
}
}
ceph_assert(curdir);
}
if (discover) {
- dout(7) << "traverse: discover from " << path[depth] << " from " << *curdir << dendl;
- discover_path(curdir, snapid, path.postfixpath(depth), cf.build(),
- path_locked);
- if (mds->logger) mds->logger->inc(l_mds_traverse_discover);
- return 1;
- }
+ if (forimport && cur->is_quiesced()) {
+ /* block discover for import */
+ dout(5) << __func__ << ": blocking discover due to quiesced parent: " << *cur << dendl;
+ return -CEPHFS_EAGAIN;
+ } else {
+ dout(7) << "traverse: discover from " << path[depth] << " from " << *curdir << dendl;
+ discover_path(curdir, snapid, path.postfixpath(depth), cf.build(),
+ path_locked);
+ if (mds->logger) mds->logger->inc(l_mds_traverse_discover);
+ return 1;
+ }
+ }
if (forward) {
// forward
dout(7) << "traverse: not auth for " << path << " in " << *curdir << dendl;
ceph_assert(g_conf()->mds_kill_export_at != 3);
} else {
- dout(7) << "peer failed to discover (not active?), canceling" << dendl;
+ dout(7) << "peer failed to discover (not active or quiesced), canceling" << dendl;
export_try_cancel(dir, false);
}
}
filepath fpath(m->get_path());
vector<CDentry*> trace;
MDRequestRef null_ref;
- int r = mdcache->path_traverse(null_ref, cf, fpath,
- MDS_TRAVERSE_DISCOVER | MDS_TRAVERSE_PATH_LOCKED,
- &trace);
+ static constexpr int flags = 0
+ | MDS_TRAVERSE_DISCOVER
+ | MDS_TRAVERSE_PATH_LOCKED
+ | MDS_TRAVERSE_IMPORT;
+ int r = mdcache->path_traverse(null_ref, cf, fpath, flags, &trace);
if (r > 0) return;
if (r < 0) {
- dout(7) << "failed to discover or not dir " << m->get_path() << ", NAK" << dendl;
- ceph_abort(); // this shouldn't happen if the auth pins its path properly!!!!
+ if (r == -CEPHFS_EAGAIN) {
+ dout(5) << "blocking import during quiesce" << dendl;
+ import_reverse_discovering(df);
+ mds->send_message_mds(make_message<MExportDirDiscoverAck>(df, m->get_tid(), false), from);
+ return;
+ } else {
+ dout(7) << "failed to discover or not dir " << m->get_path() << ", NAK" << dendl;
+ ceph_abort(); // this shouldn't happen if the auth pins its path properly!!!!
+ }
}
ceph_abort(); // this shouldn't happen; the get_inode above would have succeeded.