// can we conclude ENOENT?
if (dnl && dnl->is_null()) {
- if (mds->locker->rdlock_try(&dn->lock, client, NULL)) {
+ if (dn->lock.can_read(client) ||
+ (dn->lock.is_xlocked() && dn->lock.get_xlock_by() == mdr)) {
dout(10) << "traverse: miss on null+readable dentry " << path[depth] << " " << *dn << dendl;
return -ENOENT;
- } else {
+ } else if (curdir->is_auth()) {
dout(10) << "miss on dentry " << *dn << ", can't read due to lock" << dendl;
dn->lock.add_waiter(SimpleLock::WAIT_RD, _get_waiter(mdr, req, fin));
return 1;
+ } else {
+ // non-auth and can not read, treat this as no dentry
+ dn = NULL;
+ dnl = NULL;
}
}
return;
}
+ if (!(req->head.args.open.flags & O_EXCL)) {
+ int r = mdcache->path_traverse(mdr, NULL, NULL, req->get_filepath(),
+ &mdr->dn[0], NULL, MDS_TRAVERSE_FORWARD);
+ if (r > 0) return;
+ if (r == 0) {
+ // it existed.
+ handle_client_open(mdr);
+ return;
+ }
+ if (r < 0 && r != -ENOENT) {
+ if (r == -ESTALE) {
+ dout(10) << "FAIL on ESTALE but attempting recovery" << dendl;
+ Context *c = new C_MDS_TryFindInode(this, mdr);
+ mdcache->find_ino_peers(req->get_filepath().get_ino(), c);
+ } else {
+ dout(10) << "FAIL on error " << r << dendl;
+ reply_request(mdr, r);
+ }
+ return;
+ }
+ // r == -ENOENT
+ }
+
bool excl = (req->head.args.open.flags & O_EXCL);
set<SimpleLock*> rdlocks, wrlocks, xlocks;
ceph_file_layout *dir_layout = NULL;
if (!dnl->is_null()) {
// it existed.
- if (req->head.args.open.flags & O_EXCL) {
- dout(10) << "O_EXCL, target exists, failing with -EEXIST" << dendl;
- reply_request(mdr, -EEXIST, dnl->get_inode(), dn);
- return;
- }
-
- handle_client_open(mdr);
+ assert(req->head.args.open.flags & O_EXCL);
+ dout(10) << "O_EXCL, target exists, failing with -EEXIST" << dendl;
+ reply_request(mdr, -EEXIST, dnl->get_inode(), dn);
return;
}