return 0;
}
sp->caseFold = casefold;
+ }
- /* see if we can find it using the directory hash tables.
- we can only do exact matches, since the hash is case
- sensitive. */
- {
- cm_dirOp_t dirop;
+ /*
+ * see if we can find it using the directory hash tables.
+ * we can only do exact matches, since the hash is case
+ * sensitive.
+ */
+ if (funcp != (cm_DirFuncp_t)cm_BPlusDirFoo)
+ {
+ cm_dirOp_t dirop;
#ifdef USE_BPLUS
- int usedBplus = 0;
+ int usedBplus = 0;
#endif
- code = ENOENT;
+ code = ENOENT;
- code = cm_BeginDirOp(scp, userp, reqp, CM_DIRLOCK_READ, &dirop);
- if (code == 0) {
+ code = cm_BeginDirOp(scp, userp, reqp, CM_DIRLOCK_READ, &dirop);
+ if (code == 0) {
#ifdef USE_BPLUS
- code = cm_BPlusDirLookup(&dirop, sp->nsearchNamep, &sp->fid);
- if (code != EINVAL)
- usedBplus = 1;
- else
+ code = cm_BPlusDirLookup(&dirop, sp->nsearchNamep, &sp->fid);
+ if (code != EINVAL)
+ usedBplus = 1;
+ else
#endif
- code = cm_DirLookup(&dirop, sp->searchNamep, &sp->fid);
+ code = cm_DirLookup(&dirop, sp->searchNamep, &sp->fid);
- cm_EndDirOp(&dirop);
- }
+ cm_EndDirOp(&dirop);
+ }
- if (code == 0) {
+ if (code == 0) {
+ /* found it */
+ sp->found = TRUE;
+ sp->ExactFound = TRUE;
+ *retscp = NULL; /* force caller to call cm_GetSCache() */
+ return 0;
+ }
+#ifdef USE_BPLUS
+ if (usedBplus) {
+ if (sp->caseFold && code == CM_ERROR_INEXACT_MATCH) {
/* found it */
sp->found = TRUE;
- sp->ExactFound = TRUE;
+ sp->ExactFound = FALSE;
*retscp = NULL; /* force caller to call cm_GetSCache() */
return 0;
}
-#ifdef USE_BPLUS
- if (usedBplus) {
- if (sp->caseFold && code == CM_ERROR_INEXACT_MATCH) {
- /* found it */
- sp->found = TRUE;
- sp->ExactFound = FALSE;
- *retscp = NULL; /* force caller to call cm_GetSCache() */
- return 0;
- }
-
- return CM_ERROR_BPLUS_NOMATCH;
- }
-#endif
+
+ return CM_ERROR_BPLUS_NOMATCH;
}
+#endif
}
}
{
fschar_t *cellNamep = NULL;
fschar_t *volNamep = NULL;
- int tlen;
afs_uint32 code;
fschar_t *cp;
fschar_t *mpNamep;
mpNamep = scp->mountPointStringp;
if (!mpNamep[0])
return CM_ERROR_NOSUCHPATH;
- tlen = cm_FsStrLen(scp->mountPointStringp);
mtType = *scp->mountPointStringp;
cp = cm_FsStrChr(mpNamep, _FS(':'));
cm_scache_t *scp = NULL;
int free_fnamep = FALSE;
+ memset(&volSync, 0, sizeof(volSync));
+
if (fnamep == NULL) {
code = -1;
#ifdef USE_BPLUS
struct rx_connection * rxconnp;
int inlinebulk = 0; /* Did we use InlineBulkStatus RPC or not? */
+ memset(&volSync, 0, sizeof(volSync));
+
/* otherwise, we may have one or more bulk stat's worth of stuff in bb;
* make the calls to create the entries. Handle AFSCBMAX files at a
* time.
} while (cm_Analyze(connp, userp, reqp, &dscp->fid,
&volSync, NULL, &cbReq, code));
code = cm_MapRPCError(code, reqp);
- if (code)
- osi_Log2(afsd_logp, "CALL %sBulkStatus FAILURE code 0x%x",
- inlinebulk ? "Inline" : "", code);
- else
- osi_Log1(afsd_logp, "CALL %sBulkStatus SUCCESS", inlinebulk ? "Inline" : "");
/* may as well quit on an error, since we're not going to do
* much better on the next immediate call, either.
*/
if (code) {
- cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
+ osi_Log2(afsd_logp, "CALL %sBulkStatus FAILURE code 0x%x",
+ inlinebulk ? "Inline" : "", code);
+ cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
break;
+ } else {
+ osi_Log1(afsd_logp, "CALL %sBulkStatus SUCCESS", inlinebulk ? "Inline" : "");
}
/* otherwise, we should do the merges */
*
* Right now, be pretty conservative: if there's a
* callback or a pending call, skip it.
+ * However, if the prior attempt to obtain status
+ * was refused access or the volume is .readonly,
+ * take the data in any case since we have nothing
+ * better for the in flight directory enumeration that
+ * resulted in this function being called.
*/
- if ((scp->cbServerp == NULL || (scp->flags & CM_SCACHEFLAG_EACCESS))
- && !(scp->flags &
- (CM_SCACHEFLAG_FETCHING
- | CM_SCACHEFLAG_STORING
- | CM_SCACHEFLAG_SIZESTORING))) {
+ if ((scp->cbServerp == NULL &&
+ !(scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING | CM_SCACHEFLAG_SIZESTORING))) ||
+ (scp->flags & CM_SCACHEFLAG_PURERO) ||
+ (scp->flags & CM_SCACHEFLAG_EACCESS)) {
cm_EndCallbackGrantingCall(scp, &cbReq,
&bbp->callbacks[j],
+ &volSync,
CM_CALLBACK_MAINTAINCOUNT);
cm_MergeStatus(dscp, scp, &bbp->stats[j], &volSync, userp, reqp, 0);
}
} /* all files in the response */
/* now tell it to drop the count,
* after doing the vnode processing above */
- cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
+ cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
} /* while there are still more files to process */
/* If we did the InlineBulk RPC pull out the return code and log it */
AFSStoreStatus afsInStatus;
struct rx_connection * rxconnp;
+ memset(&volSync, 0, sizeof(volSync));
+
/* handle file length setting */
if (attrp->mask & CM_ATTRMASK_LENGTH)
return cm_SetLength(scp, &attrp->length, userp, reqp);
cm_dirOp_t dirop;
fschar_t * fnamep = NULL;
+ memset(&volSync, 0, sizeof(volSync));
+
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
lock_ObtainWrite(&scp->rw);
scp->creator = userp; /* remember who created it */
if (!cm_HaveCallback(scp)) {
+ cm_EndCallbackGrantingCall(scp, &cbReq,
+ &newFileCallback, &volSync, 0);
cm_MergeStatus(dscp, scp, &newFileStatus, &volSync,
userp, reqp, 0);
- cm_EndCallbackGrantingCall(scp, &cbReq,
- &newFileCallback, 0);
didEnd = 1;
}
lock_ReleaseWrite(&scp->rw);
/* make sure we end things properly */
if (!didEnd)
- cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
+ cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
if (scp && cm_CheckDirOpForSingleChange(&dirop)) {
cm_DirCreateEntry(&dirop, fnamep, &newFid);
return code;
}
-long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
+/*
+ * locked if TRUE means write-locked
+ * else the cm_scache_t rw must not be held
+ */
+long cm_FSync(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 locked)
{
long code;
+ if (locked)
+ lock_ReleaseWrite(&scp->rw);
code = buf_CleanVnode(scp, userp, reqp);
if (code == 0) {
lock_ObtainWrite(&scp->rw);
scp->flags &= ~(CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE);
}
- lock_ReleaseWrite(&scp->rw);
+ if (!locked)
+ lock_ReleaseWrite(&scp->rw);
+ } else if (locked) {
+ lock_ObtainWrite(&scp->rw);
}
return code;
}
cm_dirOp_t dirop;
fschar_t * fnamep = NULL;
+ memset(&volSync, 0, sizeof(volSync));
+
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
if (code == 0) {
lock_ObtainWrite(&scp->rw);
if (!cm_HaveCallback(scp)) {
+ cm_EndCallbackGrantingCall(scp, &cbReq,
+ &newDirCallback, &volSync, 0);
cm_MergeStatus(dscp, scp, &newDirStatus, &volSync,
userp, reqp, 0);
- cm_EndCallbackGrantingCall(scp, &cbReq,
- &newDirCallback, 0);
didEnd = 1;
}
lock_ReleaseWrite(&scp->rw);
/* make sure we end things properly */
if (!didEnd)
- cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
+ cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
if (scp && cm_CheckDirOpForSingleChange(&dirop)) {
cm_DirCreateEntry(&dirop, fnamep, &newFid);
cm_dirOp_t dirop;
fschar_t * fnamep = NULL;
+ memset(&volSync, 0, sizeof(volSync));
+
if (dscp->fid.cell != sscp->fid.cell ||
dscp->fid.volume != sscp->fid.volume) {
return CM_ERROR_CROSSDEVLINK;
cm_dirOp_t dirop;
fschar_t *fnamep = NULL;
+ memset(&volSync, 0, sizeof(volSync));
+
/* before starting the RPC, mark that we're changing the directory data,
* so that someone who does a chmod on the dir will wait until our
* call completes.
cm_scache_t *scp = NULL;
int free_fnamep = FALSE;
+ memset(&volSync, 0, sizeof(volSync));
+
if (fnamep == NULL) {
code = -1;
#ifdef USE_BPLUS
int free_oldNamep = FALSE;
cm_scache_t *oldScp = NULL, *newScp = NULL;
+ memset(&volSync, 0, sizeof(volSync));
+
if (cOldNamep == NULL || cNewNamep == NULL ||
cm_ClientStrLen(cOldNamep) == 0 ||
cm_ClientStrLen(cNewNamep) == 0)
AFSVolSync volSync;
afs_uint32 reqflags = reqp->flags;
+ memset(&volSync, 0, sizeof(volSync));
+
tfid.Volume = scp->fid.volume;
tfid.Vnode = scp->fid.vnode;
tfid.Unique = scp->fid.unique;
struct rx_connection * rxconnp;
AFSVolSync volSync;
+ memset(&volSync, 0, sizeof(volSync));
+
tfid.Volume = scp->fid.volume;
tfid.Vnode = scp->fid.vnode;
tfid.Unique = scp->fid.unique;
if (scp->serverLock == LockWrite &&
scp->exclusiveLocks == 0 &&
scp->sharedLocks > 0) {
-
/* The serverLock should be downgraded to LockRead */
osi_Log0(afsd_logp, " DOWNGRADE lock from LockWrite to LockRead");
+ /* Make sure there are no dirty buffers left. */
+ code = cm_FSync(scp, userp, reqp, TRUE);
+
/* since scp->serverLock looked sane, we are going to assume
that we have a valid server lock. */
scp->lockDataVersion = scp->dataVersion;
scp->sharedLocks == 0) {
/* The serverLock should be released entirely */
+ if (scp->serverLock == LockWrite) {
+ /* Make sure there are no dirty buffers left. */
+ code = cm_FSync(scp, userp, reqp, TRUE);
+ }
+
code = cm_IntReleaseLock(scp, userp, reqp);
if (code == 0)
/* The serverLock should be downgraded to LockRead */
osi_Log0(afsd_logp, " DOWNGRADE lock from LockWrite to LockRead");
+ /* Make sure there are no dirty buffers left. */
+ code = cm_FSync(scp, userp, reqp, TRUE);
+
/* Since we already had a lock, we assume that there is a
valid server lock. */
scp->lockDataVersion = scp->dataVersion;
scp->sharedLocks == 0) {
/* The serverLock should be released entirely */
+ if (scp->serverLock == LockWrite) {
+ /* Make sure there are no dirty buffers left. */
+ code = cm_FSync(scp, userp, reqp, TRUE);
+ }
+
code = cm_IntReleaseLock(scp, userp, reqp);
if (code == 0) {
struct rx_connection * rxconnp;
cm_scache_t * scp;
+ memset(&volSync, 0, sizeof(volSync));
+
cm_InitReq(&req);
lock_ObtainWrite(&cm_scacheLock);