When looking up a file, the ENOENT error code is supposed to be used
if we know that the target filename does not exist. That is, the
situation is a user or application error; they specified a filename
that was not previously created.
Currently, though, we use ENOENT for a variety of different
situations, such as:
- After successfully looking up a directory entry, we fail to
afs_GetDCache or afs_GetVCache on the FID for that entry.
- We encounter an invalid mount point, in certain code paths.
In each of these situations, an ENOENT error code is incorrect, since
the target filename does indeed exist and these situations may be
caused by network or administrative errors. An ENOENT error implies
that the user may be able to then create the target filename, which is
not true most of the time in the above situations.
In addition, on LINUX we return a negative dcache entry when we
encounter an ENOENT error on lookup. This means that if any of the
above scenarios occur, Linux would cache the fact that that directory
entry did not exist, and return ENOENT for future lookups. This was
worked around in one of the changes in commit
652f3bd9cb7a5d7833a760ba50ef7c2c67214bba to always invalidate such
negative dentries, but at the cost of performance (since this caused
negative lookups to never be cached).
To avoid all of these issues, just don't use ENOENT in these
situations. For simple non-disconnected afs_GetDCache or afs_GetVCache
errors, return EIO, since we have encountered an error that is
internal to AFS (either the underlying data is inconsistent, or we
have a network error, or something else). In disconnected operation,
return ENETDOWN like in other disconnected code paths, since often the
root cause is due to us not having network access. When a bad
mountpoint is encountered, return ENODEV, since that is what we use
elsewhere in the code when encountering a bad mountpoint.
It is also noteworthy that this changes removes the translation of
VNOVNODE into ENOENT, since a nonexistent vnode is not the same as a
nonexistent filename, as described above. Some code paths have special
behavior for this situation (ignoring the error in some cases where it
does not matter). These code paths should be okay with this change,
since all of them examine error codes that have not been translated
through afs_CheckCode.
Some useless references to ENOENT were also removed in
src/afs/LINUX*/osi_misc.c. These did not result in incorrect behavior,
but removing them makes searching for bad ENOENT references easier.
Change-Id: Ib01e4309e44b532f843d53c8de2eae613e397bf6
Reviewed-on: http://gerrit.openafs.org/11788
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
if (tvp) {
afs_globalVp = tvp;
} else
- code = ENOENT;
+ code = EIO;
}
crfree(credp);
}
needref=1;
}
} else
- error = ENOENT;
+ error = EIO;
}
}
if (tvp) {
}
}
} else
- error = ENOENT;
+ error = EIO;
}
}
if (tvp) {
if (tvp) {
afs_globalVp = tvp;
} else
- code = ENOENT;
+ code = EIO;
}
}
if (tvp) {
if (tvp) {
afs_globalVp = tvp;
} else
- code = ENOENT;
+ code = EIO;
}
}
if (tvp) {
/* It's a checkpoint restart fid. */
tcell = afs_GetCellByIndex(afid2->af_cell, READ_LOCK);
if (!tcell) {
- code = ENOENT;
+ code = EIO;
goto out;
}
vfid.Cell = tcell->cellNum;
*avcp =
(vnode_t *) afs_GetVCache(&vfid, &treq, NULL, (struct vcache *)0);
if (!*avcp) {
- code = ENOENT;
+ code = EIO;
}
goto out;
}
avc->mapcnt -= mapcnt;
code = afs_StoreOnLastReference(avc, &treq);
/* The following behavior mimics the behavior in afs_close. */
- if (code == VNOVNODE || code == ENOENT)
+ if (code == VNOVNODE)
code = 0;
if (code) {
if (mapcnt) {
afs_linux_path_t path_data;
#endif
int flags = LOOKUP_POSITIVE;
- code = ENOENT;
if (followlink)
flags |= LOOKUP_FOLLOW;
int code;
char *name;
- code = ENOENT;
if (seg == AFS_UIOUSER) {
name = afs_getname(aname);
if (IS_ERR(name))
char *name, *path;
int code;
- code = ENOENT;
name = afs_getname(aname);
if (IS_ERR(name))
return -PTR_ERR(name);
afs_DestroyAttr(vattr);
}
} else
- code = ENOENT;
+ code = EIO;
}
crfree(credp);
afs_DestroyReq(treq);
tdc = afs_GetDCache(avc, (afs_size_t) 0, treq, &origOffset, &tlen, 1);
len = tlen;
if (!tdc) {
- code = -ENOENT;
+ code = -EIO;
goto out;
}
ObtainWriteLock(&avc->lock, 811);
UpgradeSToWLock(&avc->lock, 814);
avc->f.states |= CCorrupt;
}
- code = -ENOENT;
+ code = -EIO;
goto unlock_out;
}
}
afs_globalVp = tvp;
} else
- code = ENOENT;
+ code = EIO;
}
}
if (tvp) {
afs_globalVFS = mp;
*vpp = AFSTOV(tvp);
} else
- code = ENOENT;
+ code = EIO;
}
AFS_GUNLOCK();
}
afs_globalVp = tvp;
} else
- code = ENOENT;
+ code = EIO;
}
}
if (tvp) {
afs_size_t toff, tlen;
dcp = afs_GetDCache(avc, fileBase, &treq, &toff, &tlen, 2);
if (!dcp) {
- code = ENOENT;
+ code = EIO;
break;
}
}
if (tvp) {
afs_globalVp = tvp;
} else
- code = ENOENT;
+ code = EIO;
}
}
if (tvp) {
}
}
*avcp = tvc;
- } else
- code = ENOENT; /* shouldn't get here */
+
+ } else {
+ /* Directory entry already exists, but we cannot fetch the
+ * fid it points to. */
+ code = EIO;
+ }
/* make sure vrefCount bumped only if code == 0 */
goto done;
}
ReleaseWriteLock(&tvc->lock);
*avcp = tvc;
code = 0;
- } else
- code = ENOENT;
+
+ } else {
+ /* Cannot create a new vcache. */
+ code = EIO;
+ }
} else {
/* otherwise cache entry already exists, someone else must
* have created it. Comments used to say: "don't need write
if (tvc) {
*avcp = tvc;
} else {
- code = ENOENT;
+ code = EIO;
goto done;
}
new_dc = afs_GetDCache(tvc, (afs_size_t) 0, treq, &offset, &len, 1);
if (!new_dc) {
/* printf("afs_mkdir: can't get new dcache for dir.\n"); */
- code = ENOENT;
+ code = EIO;
goto done;
}
if (tvc) {
code = 0;
*avcp = tvc;
- } else
- code = ENOENT;
+
+ } else {
+ /* For some reason, we cannot fetch the vcache for our
+ * newly-created dir. */
+ code = EIO;
+ }
} /* if (AFS_DISCON_RW) */
done:
root_vp = afs_GetVCache(tvc->mvid.target_root, areq, NULL, NULL);
}
if (!root_vp) {
- code = canblock ? ENOENT : 0;
+ code = canblock ? EIO : 0;
goto done;
}
#ifdef AFS_DARWIN80_ENV
*avcp = root_vp;
code = 0;
} else {
- code = canblock ? ENOENT : 0;
+ code = canblock ? EIO : 0;
}
done:
dcp = afs_GetDCache(adp, (afs_size_t) 0, areqp, &temp, &temp, 1);
if (!dcp) {
- code = ENOENT;
+ code = EIO;
goto done2;
}
/*printf("Code is %d\n", code);*/
if (tryEvalOnly && adp->mvstat == AFS_MVSTAT_MTPT)
- code = ENOENT;
+ code = ENODEV;
if (code)
goto done;
afs_Trace3(afs_iclSetp, CM_TRACE_GETVCDOTDOT, ICL_TYPE_FID, adp->mvid.parent,
ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, code);
*avcp = tvc;
- code = (tvc ? 0 : ENOENT);
+ code = (tvc ? 0 : EIO);
hit = 1;
if (tvc && !VREFCOUNT_GT(tvc, 0)) {
osi_Panic("TT1");
tfid.Fid.Unique = volid;
}
*avcp = tvc = afs_GetVCache(&tfid, treq, NULL, NULL);
- code = (tvc ? 0 : ENOENT);
+ code = (tvc ? 0 : EIO);
hit = 1;
goto done;
}
afs_PutVCache(uvc); /* we're done with it */
if (!tvc) {
- code = ENOENT;
+ code = EIO;
if (tvolp) {
afs_PutVolume(tvolp, WRITE_LOCK);
}
}
} else {
afs_PutVCache(tvc);
- code = ENOENT;
+ code = ENODEV;
if (tvolp)
afs_PutVolume(tvolp, WRITE_LOCK);
goto done;
afs_PutVolume(tv, READ_LOCK);
}
}
- code = ENOENT;
+ code = EIO;
} else {
code = ENETDOWN;
}
/* get a reference to the entire directory */
tdc = afs_GetDCache(avc, (afs_size_t) 0, treq, &origOffset, &tlen, 1);
if (!tdc) {
- code = ENOENT;
+ code = EIO;
goto done;
}
ObtainReadLock(&avc->lock);
goto done;
}
if (afs_IsDynrootMount(adp)) {
- code = ENOENT;
+ code = EROFS;
goto done;
}
ObtainWriteLock(&andp->lock, 147);
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
if (!tdc1) {
- code = ENOENT;
+ code = EIO;
} else {
ObtainWriteLock(&tdc1->lock, 643);
}
if (tdc1)
ObtainWriteLock(&tdc1->lock, 645);
else
- code = ENOENT;
+ code = EIO;
} else {
ObtainWriteLock(&aodp->lock, 150); /* lock smaller one first */
ObtainWriteLock(&andp->lock, 557);
if (tdc1)
ObtainWriteLock(&tdc1->lock, 646);
else
- code = ENOENT;
+ code = EIO;
tdc2 = afs_FindDCache(andp, (afs_size_t) 0);
if (tdc2)
ObtainWriteLock(&tdc2->lock, 647);
ReleaseWriteLock(&tvc->lock);
afs_PutVCache(tvc);
} else {
- code = ENOENT;
+ code = ENETDOWN;
} /* if (tvc) */
} /* if !(AFS_IS_DISCON_RW)*/
returnCode = code; /* remember for later */
tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 0);
if (!tdc) {
/* printf("afs_DisconCreateSymlink: can't get new dcache for symlink.\n"); */
- return ENOENT;
+ return ENETDOWN;
}
len = strlen(aname);
ReleaseReadLock(&tdc->lock);
afs_PutDCache(tdc);
osi_FreeLargeSpace(rbuf);
- return ENOENT;
+ return EIO;
}
code = afs_osi_Read(tfile, -1, rbuf, tlen);
osi_UFSClose(tfile);
/* VNOVNODE is "acceptable" error code from close, since
* may happen when deleting a file on another machine while
- * it is open here. We do the same for ENOENT since in afs_CheckCode we map VNOVNODE -> ENOENT */
- if (code == VNOVNODE || code == ENOENT)
+ * it is open here. */
+ if (code == VNOVNODE)
code = 0;
/* Ensure last closer gets the error. If another thread caused
parent_vc = afs_FindVCache(&parent_fid, 0, 1);
ReleaseSharedLock(&afs_xvcache);
if (!parent_vc) {
- return ENOENT;
+ return ENETDOWN;
}
shadow_fid.Cell = parent_vc->f.fid.Cell;
code = ENOENT;
} else {
/* printf("Directory dcache not found!\n"); */
- code = ENOENT;
+ code = ENETDOWN;
}
return code;
if (afs_GetParentDirFid(avc, afid)) {
/* printf("afs_GetParentVCache: Couldn't find parent dir's FID.\n"); */
- return ENOENT;
+ return ENETDOWN;
}
code = afs_GetVnodeName(avc, afid, aname, deleted);
ReleaseSharedLock(&afs_xvcache);
if (!*adp) {
/* printf("afs_GetParentVCache: Couldn't find parent dir's vcache\n"); */
- code = ENOENT;
+ code = ENETDOWN;
goto end;
}
/* Get parent dir's FID.*/
if (afs_GetParentDirFid(avc, &new_pdir_fid)) {
/* printf("afs_ProcessOpRename: Couldn't find new parent dir FID.\n"); */
- code = ENOENT;
+ code = ENETDOWN;
goto done;
}
}
tdc = afs_GetDCache(avc, 0, areq, &offset, &tlen, 0);
if (!tdc) {
- code = ENOENT;
+ code = ENETDOWN;
goto end;
}
if (areq->volumeError == VOLBUSY)
return EWOULDBLOCK;
if (acode == VNOVNODE)
- return ENOENT;
+ return EIO;
if (acode == VDISKFULL)
return ENOSPC;
if (acode == VOVERQUOTA)
}
tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
if (!tdc)
- return ENOENT;
+ return EIO;
Check_AtSys(avc, name, &sysState, areq);
ObtainReadLock(&tdc->lock);
do {
tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
}
if (!tvc) {
- code = ENOENT;
+ code = EIO;
goto out;
}
if (tvc->mvstat != AFS_MVSTAT_MTPT) {
tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
if (!tdc)
- return ENOENT;
+ return EIO;
Check_AtSys(avc, name, &sysState, areq);
ObtainReadLock(&tdc->lock);
do {
tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
}
if (!tvc) {
- code = ENOENT;
+ code = EIO;
afs_PutDCache(tdc);
goto out;
}
}
tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
if (!tdc)
- return ENOENT;
+ return EIO;
Check_AtSys(avc, mount, &sysState, areq);
ObtainReadLock(&tdc->lock);
do {
tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
}
if (!tvc) {
- code = ENOENT;
+ code = EIO;
goto out;
}
if (tvc->mvstat != AFS_MVSTAT_MTPT) {
/* fetch the status info */
tvc = afs_GetVCache(&avc->f.fid, areq, NULL, avc);
if (!tvc)
- return ENOENT;
+ return EIO;
/* Put it back; caller has already incremented vrefCount */
afs_PutVCache(tvc);
return 0;