int flags = req->head.args.open.flags;
int cmode = ceph_flags_to_mode(flags);
- bool need_auth = !file_mode_is_readonly(cmode) || (flags & CEPH_O_TRUNC);
+ bool need_auth = !file_mode_is_readonly(cmode) ||
+ (flags & (CEPH_O_TRUNC | CEPH_O_DIRECTORY));
dout(7) << "open on " << req->get_filepath() << dendl;
dout(7) << "handle_client_link link " << dn->get_name() << " in " << *dir << dendl;
dout(7) << "target is " << *targeti << dendl;
if (targeti->is_dir()) {
- dout(7) << "target is a dir, failing..." << dendl;
- respond_to_request(mdr, -EINVAL);
- return;
+ // if srcdn is replica, need to make sure its linkage is correct
+ vector<CDentry*>& trace = mdr->dn[1];
+ if (trace.empty() ||
+ trace.back()->is_auth() ||
+ trace.back()->lock.can_read(mdr->get_client())) {
+ dout(7) << "target is a dir, failing..." << dendl;
+ respond_to_request(mdr, -EINVAL);
+ return;
+ }
}
xlocks.insert(&targeti->linklock);
oldin = mdcache->get_dentry_inode(destdn, mdr, true);
if (!oldin) return;
dout(10) << " oldin " << *oldin << dendl;
-
- // mv /some/thing /to/some/existing_other_thing
- if (oldin->is_dir() && !srci->is_dir()) {
- respond_to_request(mdr, -EISDIR);
- return;
- }
- if (!oldin->is_dir() && srci->is_dir()) {
- respond_to_request(mdr, -ENOTDIR);
- return;
- }
// non-empty dir?
if (oldin->is_dir() && _dir_is_nonempty_unlocked(mdr, oldin)) {
respond_to_request(mdr, -ENOTEMPTY);
return;
}
- if (srci == oldin && !srcdn->get_dir()->inode->is_stray()) {
- respond_to_request(mdr, 0); // no-op. POSIX makes no sense.
- return;
+
+ // if srcdn is replica, need to make sure its linkage is correct
+ if (srcdn->is_auth() ||
+ srcdn->lock.can_read(mdr->get_client()) ||
+ (srcdn->lock.is_xlocked() && srcdn->lock.get_xlock_by() == mdr)) {
+ // mv /some/thing /to/some/existing_other_thing
+ if (oldin->is_dir() && !srci->is_dir()) {
+ respond_to_request(mdr, -EISDIR);
+ return;
+ }
+ if (!oldin->is_dir() && srci->is_dir()) {
+ respond_to_request(mdr, -ENOTDIR);
+ return;
+ }
+ if (srci == oldin && !srcdn->get_dir()->inode->is_stray()) {
+ respond_to_request(mdr, 0); // no-op. POSIX makes no sense.
+ return;
+ }
}
}