code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, reqp, NULL);
if (code == 0) {
- cm_Unlock(scp, sLockType, LOffset, LLength, key, userp, reqp);
+ cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, reqp);
} else {
/* In this case, we allow the file open to go through even
though we can't enforce mandatory locking on the
(*ldpp) = (cm_lock_data_t *)malloc(sizeof(cm_lock_data_t));
if (!*ldpp) {
code = ENOMEM;
- goto _syncopdone;
+ goto _done;
}
(*ldpp)->key = key;
goto _done;
}
- _syncopdone:
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
-
_done:
lock_ReleaseWrite(&scp->rw);
cm_lock_data_t ** ldpp)
{
osi_Log2(afsd_logp,"cm_CheckNTOpenDone scp 0x%p ldp 0x%p", scp, *ldpp);
+ lock_ObtainWrite(&scp->rw);
if (*ldpp) {
- lock_ObtainWrite(&scp->rw);
cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength,
- (*ldpp)->key, userp, reqp);
- lock_ReleaseWrite(&scp->rw);
+ (*ldpp)->key, 0, userp, reqp);
free(*ldpp);
*ldpp = NULL;
}
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
+ lock_ReleaseWrite(&scp->rw);
return 0;
}
/*
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, reqp, PRSFS_DELETE,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (!code)
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ReleaseWrite(&scp->rw);
if (code)
return code;
return code;
thyper.HighPart = 0; thyper.LowPart = 0;
- code = buf_Get(scp, &thyper, &bufferp);
+ code = buf_Get(scp, &thyper, reqp, &bufferp);
if (code)
return code;
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
}
}
bufferp = NULL;
}
- code = buf_Get(scp, &thyper, &bufferp);
+ code = buf_Get(scp, &thyper, reqp, &bufferp);
if (code) {
/* if buf_Get() fails we do not have a buffer object to lock */
bufferp = NULL;
sp = (cm_lookupSearch_t *) rockp;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ /* Can't normalize FS string. */
+ return 0;
+ }
+
if (sp->caseFold)
match = cm_NormStrCmpI(matchName, sp->nsearchNamep);
else
long cm_ReadMountPoint(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
{
long code;
- cm_buf_t *bufp;
+ cm_buf_t *bufp = NULL;
osi_hyper_t thyper;
int tlen;
if (scp->mountPointStringp[0])
return 0;
- /* otherwise, we have to read it in */
- lock_ReleaseWrite(&scp->rw);
-
- thyper.LowPart = thyper.HighPart = 0;
- code = buf_Get(scp, &thyper, &bufp);
+#ifdef AFS_FREELANCE_CLIENT
+ /* File servers do not have data for freelance entries */
+ if (cm_freelanceEnabled &&
+ scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ scp->fid.volume==AFS_FAKE_ROOT_VOL_ID )
+ {
+ code = cm_FreelanceFetchMountPointString(scp);
+ } else
+#endif /* AFS_FREELANCE_CLIENT */
+ {
+ /* otherwise, we have to read it in */
+ lock_ReleaseWrite(&scp->rw);
- lock_ObtainWrite(&scp->rw);
- if (code)
- return code;
+ thyper.LowPart = thyper.HighPart = 0;
+ code = buf_Get(scp, &thyper, reqp, &bufp);
- while (1) {
- code = cm_SyncOp(scp, bufp, userp, reqp, 0,
- CM_SCACHESYNC_READ | CM_SCACHESYNC_NEEDCALLBACK);
+ lock_ObtainWrite(&scp->rw);
if (code)
- goto done;
+ return code;
- cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+ while (1) {
+ code = cm_SyncOp(scp, bufp, userp, reqp, 0,
+ CM_SCACHESYNC_READ | CM_SCACHESYNC_NEEDCALLBACK);
+ if (code)
+ goto done;
- if (cm_HaveBuffer(scp, bufp, 0))
- break;
+ cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
- /* otherwise load buffer */
- code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
- if (code)
+ if (cm_HaveBuffer(scp, bufp, 0))
+ break;
+
+ /* otherwise load buffer */
+ code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
+ if (code)
+ goto done;
+ }
+ /* locked, has callback, has valid data in buffer */
+ if ((tlen = scp->length.LowPart) > MOUNTPOINTLEN - 1)
+ return CM_ERROR_TOOBIG;
+ if (tlen <= 0) {
+ code = CM_ERROR_INVAL;
goto done;
- }
- /* locked, has callback, has valid data in buffer */
- if ((tlen = scp->length.LowPart) > MOUNTPOINTLEN - 1)
- return CM_ERROR_TOOBIG;
- if (tlen <= 0) {
- code = CM_ERROR_INVAL;
- goto done;
- }
+ }
- /* someone else did the work while we were out */
- if (scp->mountPointStringp[0]) {
- code = 0;
- goto done;
- }
+ /* someone else did the work while we were out */
+ if (scp->mountPointStringp[0]) {
+ code = 0;
+ goto done;
+ }
- /* otherwise, copy out the link */
- memcpy(scp->mountPointStringp, bufp->datap, tlen);
+ /* otherwise, copy out the link */
+ memcpy(scp->mountPointStringp, bufp->datap, tlen);
- /* now make it null-terminated. Note that the original contents of a
- * link that is a mount point is "#volname." where "." is there just to
- * be turned into a null. That is, we can trash the last char of the
- * link without damaging the vol name. This is a stupid convention,
- * but that's the protocol.
- */
- scp->mountPointStringp[tlen-1] = 0;
- code = 0;
+ /* now make it null-terminated. Note that the original contents of a
+ * link that is a mount point is "#volname." where "." is there just to
+ * be turned into a null. That is, we can trash the last char of the
+ * link without damaging the vol name. This is a stupid convention,
+ * but that's the protocol.
+ */
+ scp->mountPointStringp[tlen-1] = 0;
+ code = 0;
- done:
- if (bufp)
- buf_Release(bufp);
+ done:
+ if (bufp)
+ buf_Release(bufp);
+ }
return code;
}
{
fschar_t *cellNamep = NULL;
fschar_t *volNamep = NULL;
- int tlen;
afs_uint32 code;
fschar_t *cp;
fschar_t *mpNamep;
size_t vnLength;
int targetType;
+ *outScpp = NULL;
+
if (scp->mountRootFid.cell != 0 && scp->mountRootGen >= cm_data.mountRootGen) {
tfid = scp->mountRootFid;
lock_ReleaseWrite(&scp->rw);
mpNamep = scp->mountPointStringp;
if (!mpNamep[0])
return CM_ERROR_NOSUCHPATH;
- tlen = cm_FsStrLen(scp->mountPointStringp);
mtType = *scp->mountPointStringp;
cp = cm_FsStrChr(mpNamep, _FS(':'));
/* normal mt pt */
volNamep = cm_FsStrDup(mpNamep + 1);
- cellp = cm_FindCellByID(scp->fid.cell, 0);
+#ifdef AFS_FREELANCE_CLIENT
+ /*
+ * Mount points in the Freelance cell should default
+ * to the workstation cell.
+ */
+ if (cm_freelanceEnabled &&
+ scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ scp->fid.volume==AFS_FAKE_ROOT_VOL_ID )
+ {
+ fschar_t rootCellName[256]="";
+ cm_GetRootCellName(rootCellName);
+ cellp = cm_GetCell(rootCellName, 0);
+ } else
+#endif /* AFS_FREELANCE_CLIENT */
+ cellp = cm_FindCellByID(scp->fid.cell, 0);
}
if (!cellp) {
}
long cm_LookupInternal(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_user_t *userp,
- cm_req_t *reqp, cm_scache_t **outpScpp)
+ cm_req_t *reqp, cm_scache_t **outScpp)
{
long code;
int dnlcHit = 1; /* did we hit in the dnlc? yes, we did */
normchar_t *nnamep = NULL;
fschar_t *fnamep = NULL;
+ *outScpp = NULL;
+
memset(&rock, 0, sizeof(rock));
if (dscp->fid.vnode == 1 && dscp->fid.unique == 1
}
nnamep = cm_ClientStringToNormStringAlloc(cnamep, -1, NULL);
+ if (!nnamep) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
+ }
fnamep = cm_ClientStringToFsStringAlloc(cnamep, -1, NULL);
+ if (!fnamep) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
+ }
if (flags & CM_FLAG_NOMOUNTCHASE) {
/* In this case, we should go and call cm_Dir* functions
cm_ClientStrCmpI(cnamep, _C("ipc$")))
{
/* nonexistent dir on freelance root, so add it */
- fschar_t fullname[200] = ".";
+ fschar_t fullname[CELL_MAXNAMELEN + 1] = "."; /* +1 so that when we skip the . the size is still CELL_MAXNAMELEN */
int found = 0;
osi_Log1(afsd_logp,"cm_Lookup adding mount for non-existent directory: %S",
code = cm_FreelanceAddSymlink(fnamep, fullname, &rock.fid);
}
}
- if (!found || code < 0) { /* add mount point failed, so give up */
+ if (!found || code) { /* add mount point failed, so give up */
if (flags & CM_FLAG_CHECKPATH)
code = CM_ERROR_NOSUCHPATH;
else
}
/* copy back pointer */
- *outpScpp = tscp;
+ *outScpp = tscp;
/* insert scache in dnlc */
if ( !dnlcHit && !(flags & CM_FLAG_NOMOUNTCHASE) && rock.ExactFound ) {
if (nnamep)
free(nnamep);
nnamep = cm_ClientStringToNormStringAlloc(cnamep, -1, NULL);
- cm_dnlcEnter(dscp, nnamep, tscp);
+ if (nnamep)
+ cm_dnlcEnter(dscp, nnamep, tscp);
}
lock_ReleaseRead(&dscp->rw);
}
}
long cm_EvaluateVolumeReference(clientchar_t * namep, long flags, cm_user_t * userp,
- cm_req_t *reqp, cm_scache_t ** outpScpp)
+ cm_req_t *reqp, cm_scache_t ** outScpp)
{
afs_uint32 code = 0;
fschar_t cellName[CELL_MAXNAMELEN];
cm_SetFid(&fid, cellp->cellID, volume, 1, 1);
- code = cm_GetSCache(&fid, outpScpp, userp, reqp);
+ code = cm_GetSCache(&fid, outScpp, userp, reqp);
_exit_cleanup:
if (fnamep)
#ifdef DEBUG_REFCOUNT
long cm_LookupDbg(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
- cm_req_t *reqp, cm_scache_t **outpScpp, char * file, long line)
+ cm_req_t *reqp, cm_scache_t **outScpp, char * file, long line)
#else
long cm_Lookup(cm_scache_t *dscp, clientchar_t *namep, long flags, cm_user_t *userp,
- cm_req_t *reqp, cm_scache_t **outpScpp)
+ cm_req_t *reqp, cm_scache_t **outScpp)
#endif
{
long code;
if (dscp == cm_data.rootSCachep &&
cm_ClientStrCmpNI(namep, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH) == 0) {
- return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outpScpp);
+ return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outScpp);
}
if (cm_ExpandSysName(namep, NULL, 0, 0) > 0) {
#endif
if (code == 0) {
- *outpScpp = scp;
+ *outScpp = scp;
return 0;
}
if (scp) {
afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
#endif
- *outpScpp = scp;
+ *outScpp = scp;
return code;
}
}
afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0);
osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp);
#endif
- *outpScpp = scp;
+ *outScpp = scp;
return code;
}
cm_scache_t *scp = NULL;
int free_fnamep = FALSE;
+ memset(&volSync, 0, sizeof(volSync));
+
if (fnamep == NULL) {
code = -1;
#ifdef USE_BPLUS
cm_dnlcRemove(dscp, cnamep);
cm_SyncOpDone(dscp, NULL, sflags);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
} else if (code == CM_ERROR_NOSUCHFILE) {
/* windows would not have allowed the request to delete the file
* if it did not believe the file existed. therefore, we must
cm_ReleaseSCache(scp);
if (code == 0) {
lock_ObtainWrite(&scp->rw);
- scp->flags |= CM_SCACHEFLAG_DELETED;
+ if (--scp->linkCount == 0)
+ scp->flags |= CM_SCACHEFLAG_DELETED;
+ cm_DiscardSCache(scp);
lock_ReleaseWrite(&scp->rw);
}
}
lock_AssertWrite(&linkScp->rw);
if (!linkScp->mountPointStringp[0]) {
- /* read the link data */
- lock_ReleaseWrite(&linkScp->rw);
- thyper.LowPart = thyper.HighPart = 0;
- code = buf_Get(linkScp, &thyper, &bufp);
- lock_ObtainWrite(&linkScp->rw);
- if (code)
- return code;
- while (1) {
- code = cm_SyncOp(linkScp, bufp, userp, reqp, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
- if (code) {
- buf_Release(bufp);
+
+#ifdef AFS_FREELANCE_CLIENT
+ /* File servers do not have data for freelance entries */
+ if (cm_freelanceEnabled &&
+ linkScp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ linkScp->fid.volume==AFS_FAKE_ROOT_VOL_ID )
+ {
+ code = cm_FreelanceFetchMountPointString(linkScp);
+ } else
+#endif /* AFS_FREELANCE_CLIENT */
+ {
+ /* read the link data from the file server*/
+ lock_ReleaseWrite(&linkScp->rw);
+ thyper.LowPart = thyper.HighPart = 0;
+ code = buf_Get(linkScp, &thyper, reqp, &bufp);
+ lock_ObtainWrite(&linkScp->rw);
+ if (code)
return code;
- }
- cm_SyncOpDone(linkScp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+ while (1) {
+ code = cm_SyncOp(linkScp, bufp, userp, reqp, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+ if (code) {
+ buf_Release(bufp);
+ return code;
+ }
+ cm_SyncOpDone(linkScp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
- if (cm_HaveBuffer(linkScp, bufp, 0))
- break;
+ if (cm_HaveBuffer(linkScp, bufp, 0))
+ break;
- code = cm_GetBuffer(linkScp, bufp, NULL, userp, reqp);
- if (code) {
+ code = cm_GetBuffer(linkScp, bufp, NULL, userp, reqp);
+ if (code) {
+ buf_Release(bufp);
+ return code;
+ }
+ } /* while loop to get the data */
+
+ /* now if we still have no link read in,
+ * copy the data from the buffer */
+ if ((temp = linkScp->length.LowPart) >= MOUNTPOINTLEN) {
buf_Release(bufp);
- return code;
+ return CM_ERROR_TOOBIG;
+ }
+
+ /* otherwise, it fits; make sure it is still null (could have
+ * lost race with someone else referencing this link above),
+ * and if so, copy in the data.
+ */
+ if (!linkScp->mountPointStringp[0]) {
+ strncpy(linkScp->mountPointStringp, bufp->datap, temp);
+ linkScp->mountPointStringp[temp] = 0; /* null terminate */
}
- } /* while loop to get the data */
-
- /* now if we still have no link read in,
- * copy the data from the buffer */
- if ((temp = linkScp->length.LowPart) >= MOUNTPOINTLEN) {
buf_Release(bufp);
- return CM_ERROR_TOOBIG;
}
+
+ if ( !strnicmp(linkScp->mountPointStringp, "msdfs:", strlen("msdfs:")) )
+ linkScp->fileType = CM_SCACHETYPE_DFSLINK;
- /* otherwise, it fits; make sure it is still null (could have
- * lost race with someone else referencing this link above),
- * and if so, copy in the data.
- */
- if (!linkScp->mountPointStringp[0]) {
- strncpy(linkScp->mountPointStringp, bufp->datap, temp);
- linkScp->mountPointStringp[temp] = 0; /* null terminate */
-
- if ( !strnicmp(linkScp->mountPointStringp, "msdfs:", strlen("msdfs:")) )
- linkScp->fileType = CM_SCACHETYPE_DFSLINK;
- }
- buf_Release(bufp);
} /* don't have sym link contents cached */
return 0;
StringCchCatA(tsp->data,lengthof(tsp->data), "\\");
StringCchCatA(tsp->data,lengthof(tsp->data), pathSuffixp);
}
+
if (code == 0) {
clientchar_t * cpath = cm_FsStringToClientStringAlloc(tsp->data, -1, NULL);
+ if (cpath != NULL) {
cm_ClientStrCpy(tsp->wdata, lengthof(tsp->wdata), cpath);
free(cpath);
*newSpaceBufferp = tsp;
} else {
+ code = CM_ERROR_NOSUCHPATH;
+ }
+ }
+
+ if (code != 0) {
cm_FreeSpace(tsp);
if (code == CM_ERROR_PATH_NOT_COVERED && reqp->tidPathp && reqp->relPathp) {
int fid_count = 0; /* number of fids processed in this path walk */
int i;
+ *outScpp = NULL;
+
#ifdef DEBUG_REFCOUNT
afsi_log("%s:%d cm_NameI rootscp 0x%p ref %d", file, line, rootSCachep, rootSCachep->refCount);
osi_Log4(afsd_logp,"cm_NameI rootscp 0x%p path %S tidpath %S flags 0x%x",
- rootSCachep, pathp ? pathp : "<NULL>", tidPathp ? tidPathp : "<NULL>",
+ rootSCachep, pathp ? pathp : L"<NULL>", tidPathp ? tidPathp : L"<NULL>",
flags);
#endif
fid_count = i+1;
} else {
/* add the new fid to the list */
- for ( i=0; i<fid_count; i++) {
- if ( !cm_FidCmp(&nscp->fid, &fids[i]) ) {
- code = CM_ERROR_TOO_MANY_SYMLINKS;
- cm_ReleaseSCache(nscp);
- nscp = NULL;
- break;
- }
- }
- if (i == fid_count && fid_count < MAX_FID_COUNT) {
- fids[fid_count++] = nscp->fid;
- }
+ if (fid_count == MAX_FID_COUNT) {
+ code = CM_ERROR_TOO_MANY_SYMLINKS;
+ cm_ReleaseSCache(nscp);
+ nscp = NULL;
+ break;
+ }
+ fids[fid_count++] = nscp->fid;
}
}
}
if (code == 0 && linkScp != NULL) {
- if (linkScp == cm_data.rootSCachep)
+ if (linkScp == cm_data.rootSCachep) {
fid_count = 0;
- else {
+ i = 0;
+ } else {
for ( i=0; i<fid_count; i++) {
if ( !cm_FidCmp(&linkScp->fid, &fids[i]) ) {
code = CM_ERROR_TOO_MANY_SYMLINKS;
cm_ReleaseSCache(tscp);
#ifdef DEBUG_REFCOUNT
- afsi_log("%s:%d cm_NameI code 0x%x outScpp 0x%p ref %d", file, line, code, *outScpp, (*outScpp)->refCount);
+ afsi_log("%s:%d cm_NameI code 0x%x outScpp 0x%p ref %d", file, line, code, *outScpp, (*outScpp) ? (*outScpp)->refCount : 0);
#endif
osi_Log2(afsd_logp,"cm_NameI code 0x%x outScpp 0x%p", code, *outScpp);
return code;
cm_space_t *spacep;
cm_scache_t *newRootScp;
+ *outScpp = NULL;
+
osi_Log1(afsd_logp, "Evaluating symlink scp 0x%p", linkScp);
code = cm_AssembleLink(linkScp, "", &newRootScp, &spacep, userp, reqp);
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, 0);
+ cm_MergeStatus(dscp, scp, &bbp->stats[j], &volSync, userp, reqp, 0);
}
lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
} /* 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);
lock_ObtainWrite(&scp->rw);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_STORESTATUS);
if (code == 0)
- cm_MergeStatus(NULL, scp, &afsOutStatus, &volSync, userp,
+ cm_MergeStatus(NULL, scp, &afsOutStatus, &volSync, userp, reqp,
CM_MERGEFLAG_FORCE|CM_MERGEFLAG_STOREDATA);
/* if we're changing the mode bits, discard the ACL cache,
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(&dscp->rw);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseWrite(&dscp->rw);
lock_ObtainWrite(&scp->rw);
scp->creator = userp; /* remember who created it */
if (!cm_HaveCallback(scp)) {
- cm_MergeStatus(dscp, scp, &newFileStatus, &volSync,
- userp, 0);
cm_EndCallbackGrantingCall(scp, &cbReq,
- &newFileCallback, 0);
+ &newFileCallback, &volSync, 0);
+ cm_MergeStatus(dscp, scp, &newFileStatus, &volSync,
+ userp, reqp, 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.
*/
lock_ObtainWrite(&dscp->rw);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseWrite(&dscp->rw);
if (code == 0) {
lock_ObtainWrite(&scp->rw);
if (!cm_HaveCallback(scp)) {
- cm_MergeStatus(dscp, scp, &newDirStatus, &volSync,
- userp, 0);
cm_EndCallbackGrantingCall(scp, &cbReq,
- &newDirCallback, 0);
+ &newDirCallback, &volSync, 0);
+ cm_MergeStatus(dscp, scp, &newDirStatus, &volSync,
+ userp, reqp, 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;
lock_ObtainWrite(&dscp->rw);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseWrite(&dscp->rw);
}
cm_EndDirOp(&dirop);
+ /* Update the linked object status */
+ if (code == 0) {
+ lock_ObtainWrite(&sscp->rw);
+ cm_MergeStatus(NULL, sscp, &newLinkStatus, &volSync, userp, reqp, 0);
+ lock_ReleaseWrite(&sscp->rw);
+ }
+
free(fnamep);
return code;
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.
lock_ObtainWrite(&dscp->rw);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseWrite(&dscp->rw);
lock_ObtainWrite(&scp->rw);
if (!cm_HaveCallback(scp)) {
cm_MergeStatus(dscp, scp, &newLinkStatus, &volSync,
- userp, 0);
+ userp, reqp, 0);
}
lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
cm_scache_t *scp = NULL;
int free_fnamep = FALSE;
+ memset(&volSync, 0, sizeof(volSync));
+
if (fnamep == NULL) {
code = -1;
#ifdef USE_BPLUS
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
cm_dnlcRemove(dscp, cnamep);
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, reqp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseWrite(&dscp->rw);
cm_dirOp_t newDirOp;
fschar_t * newNamep = NULL;
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)
return CM_ERROR_INVAL;
+ /*
+ * Before we permit the operation, make sure that we do not already have
+ * an object in the destination directory that has a case-insensitive match
+ * for this name UNLESS the matching object is the object we are renaming.
+ */
+ code = cm_Lookup(oldDscp, cOldNamep, 0, userp, reqp, &oldScp);
+ if (code) {
+ osi_Log2(afsd_logp, "cm_Rename oldDscp 0x%p cOldName %S old name lookup failed",
+ oldDscp, osi_LogSaveStringW(afsd_logp, cOldNamep));
+ goto done;
+ }
+
+ code = cm_Lookup(newDscp, cNewNamep, CM_FLAG_CASEFOLD, userp, reqp, &newScp);
+ if (code == 0) {
+ /* found a matching object with the new name */
+ if (cm_FidCmp(&oldScp->fid, &newScp->fid)) {
+ /* and they don't match so return an error */
+ osi_Log2(afsd_logp, "cm_Rename newDscp 0x%p cNewName %S new name already exists",
+ newDscp, osi_LogSaveStringW(afsd_logp, cNewNamep));
+ code = CM_ERROR_EXISTS;
+ }
+ cm_ReleaseSCache(newScp);
+ newScp = NULL;
+ } else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+ code = CM_ERROR_EXISTS;
+ } else {
+ code = 0;
+ }
+ if (code)
+ goto done;
+
if (oldNamep == NULL) {
code = -1;
#ifdef USE_BPLUS
if (code == 0)
cm_MergeStatus(NULL, oldDscp, &updatedOldDirStatus, &volSync,
- userp, CM_MERGEFLAG_DIROP);
+ userp, reqp, CM_MERGEFLAG_DIROP);
lock_ReleaseWrite(&oldDscp->rw);
- if (code == 0) {
- if (cm_CheckDirOpForSingleChange(&oldDirOp)) {
-
+ if (code == 0 && cm_CheckDirOpForSingleChange(&oldDirOp)) {
#ifdef USE_BPLUS
- diropCode = cm_BPlusDirLookup(&oldDirOp, cOldNamep, &fileFid);
- if (diropCode == CM_ERROR_INEXACT_MATCH)
- diropCode = 0;
- else if (diropCode == EINVAL)
+ diropCode = cm_BPlusDirLookup(&oldDirOp, cOldNamep, &fileFid);
+ if (diropCode == CM_ERROR_INEXACT_MATCH)
+ diropCode = 0;
+ else if (diropCode == EINVAL)
#endif
- diropCode = cm_DirLookup(&oldDirOp, oldNamep, &fileFid);
+ diropCode = cm_DirLookup(&oldDirOp, oldNamep, &fileFid);
- if (diropCode == 0) {
- if (oneDir) {
- diropCode = cm_DirCreateEntry(&oldDirOp, newNamep, &fileFid);
-#ifdef USE_BPLUS
- cm_BPlusDirCreateEntry(&oldDirOp, cNewNamep, &fileFid);
+ if (diropCode == 0) {
+ if (oneDir) {
+ diropCode = cm_DirCreateEntry(&oldDirOp, newNamep, &fileFid);
+#ifdef USE_BPLUS
+ cm_BPlusDirCreateEntry(&oldDirOp, cNewNamep, &fileFid);
#endif
- }
+ }
- if (diropCode == 0) {
- diropCode = cm_DirDeleteEntry(&oldDirOp, oldNamep);
+ if (diropCode == 0) {
+ diropCode = cm_DirDeleteEntry(&oldDirOp, oldNamep);
#ifdef USE_BPLUS
- cm_BPlusDirDeleteEntry(&oldDirOp, cOldNamep);
-#endif
- }
+ cm_BPlusDirDeleteEntry(&oldDirOp, cOldNamep);
+#endif
}
}
}
cm_SyncOpDone(newDscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0)
cm_MergeStatus(NULL, newDscp, &updatedNewDirStatus, &volSync,
- userp, CM_MERGEFLAG_DIROP);
+ userp, reqp, CM_MERGEFLAG_DIROP);
lock_ReleaseWrite(&newDscp->rw);
+#if 0
+ /*
+ * The following optimization does not work.
+ * When the file server processed a RXAFS_Rename() request the
+ * FID of the object being moved between directories is not
+ * preserved. The client does not know the new FID nor the
+ * version number of the target. Not only can we not create
+ * the directory entry in the new directory, but we can't
+ * preserve the cached data for the file. It must be re-read
+ * from the file server. - jaltman, 2009/02/20
+ */
if (code == 0) {
/* we only make the local change if we successfully made
the change in the old directory AND there was only one
#endif
}
}
+#endif /* 0 */
cm_EndDirOp(&newDirOp);
}
+ /*
+ * After the rename the file server has invalidated the callbacks
+ * on the file that was moved nor do we have a directory reference
+ * to it anymore.
+ */
+ lock_ObtainWrite(&oldScp->rw);
+ cm_DiscardSCache(oldScp);
+ lock_ReleaseWrite(&oldScp->rw);
+
done:
+ if (oldScp)
+ cm_ReleaseSCache(oldScp);
+
if (free_oldNamep)
free(oldNamep);
if (INTERSECT_RANGE(range, fileLock->range)) {
if (IS_LOCK_ACTIVE(fileLock)) {
- if (fileLock->key == key) {
+ if (cm_KeyEquals(&fileLock->key, &key, 0)) {
/* If there is an active lock for this client, it
is safe to substract ranges.*/
cm_LockRangeSubtract(&range, &fileLock->range);
}
} else if (IS_LOCK_LOST(fileLock) &&
- (fileLock->key == key || fileLock->lockType == LockWrite)) {
+ (cm_KeyEquals(&fileLock->key, &key, 0) || fileLock->lockType == LockWrite)) {
code = CM_ERROR_BADFD;
break;
}
if (INTERSECT_RANGE(range, fileLock->range)) {
if (IS_LOCK_ACTIVE(fileLock)) {
- if (fileLock->key == key) {
+ if (cm_KeyEquals(&fileLock->key, &key, 0)) {
if (fileLock->lockType == LockWrite) {
/* if there is an active lock for this client, it
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;
osi_Log4(afsd_logp, "cm_Lock scp 0x%x type 0x%x offset %d length %d",
scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart);
- osi_Log3(afsd_logp, "... allowWait %d key 0x%x:%x", allowWait,
- (unsigned long)(key >> 32), (unsigned long)(key & 0xffffffff));
+ osi_Log4(afsd_logp, "... allowWait %d key <0x%x, 0x%x, 0x%x>", allowWait,
+ key.process_id, key.session_id, key.file_id);
/*
A client C can OBTAIN a lock L on cm_scache_t S iff (both 3 and 4):
(cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq));
if (IS_LOCK_LOST(fileLock)) {
- if (fileLock->key == key) {
+ if (cm_KeyEquals(&fileLock->key, &key, 0)) {
code = CM_ERROR_BADFD;
break;
} else if (fileLock->lockType == LockWrite && INTERSECT_RANGE(range, fileLock->range)) {
"cm_Lock Rejecting lock (code = 0x%x)", code);
}
+ /* Convert from would block to lock not granted */
+ if (code == CM_ERROR_WOULDBLOCK)
+ code = CM_ERROR_LOCK_NOT_GRANTED;
+
return code;
}
-static int cm_KeyEquals(cm_key_t k1, cm_key_t k2, int flags);
-
/* Called with scp->rw held */
long cm_UnlockByKey(cm_scache_t * scp,
cm_key_t key,
osi_queue_t *q, *qn;
int n_unlocks = 0;
- osi_Log4(afsd_logp, "cm_UnlockByKey scp 0x%p key 0x%x:%x flags=0x%x",
- scp,
- (unsigned long)(key >> 32),
- (unsigned long)(key & 0xffffffff),
- flags);
+ osi_Log4(afsd_logp, "cm_UnlockByKey scp 0x%p key <0x%x,0x%x,0x%x",
+ scp, key.process_id, key.session_id, key.file_id);
+ osi_Log1(afsd_logp, " flags=0x%x", flags);
lock_ObtainWrite(&cm_scacheLock);
(unsigned long) fileLock->range.offset,
(unsigned long) fileLock->range.length,
fileLock->lockType);
- osi_Log3(afsd_logp, " key[0x%x:%x] flags[0x%x]",
- (unsigned long)(fileLock->key >> 32),
- (unsigned long)(fileLock->key & 0xffffffff),
+ osi_Log4(afsd_logp, " key<0x%x, 0x%x, 0x%x> flags[0x%x]",
+ fileLock->key.process_id, fileLock->key.session_id, fileLock->key.file_id,
fileLock->flags);
if (cm_FidCmp(&fileLock->fid, &fileLock->scp->fid)) {
#endif
if (!IS_LOCK_DELETED(fileLock) &&
- cm_KeyEquals(fileLock->key, key, flags)) {
+ cm_KeyEquals(&fileLock->key, &key, flags)) {
osi_Log3(afsd_logp, "...Unlock range [%d,+%d] type %d",
fileLock->range.offset,
fileLock->range.length,
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)
unsigned char sLockType,
LARGE_INTEGER LOffset, LARGE_INTEGER LLength,
cm_key_t key,
+ afs_uint32 flags,
cm_user_t *userp,
cm_req_t *reqp)
{
cm_file_lock_t *fileLock;
osi_queue_t *q;
int release_userp = FALSE;
+ int exact_match = !(flags & CM_UNLOCK_FLAG_MATCH_RANGE);
+ int lock_found = 0;
+ LARGE_INTEGER RangeEnd;
osi_Log4(afsd_logp, "cm_Unlock scp 0x%p type 0x%x offset %d length %d",
scp, sLockType, (unsigned long)LOffset.QuadPart, (unsigned long)LLength.QuadPart);
- osi_Log2(afsd_logp, "... key 0x%x:%x",
- (unsigned long) (key >> 32), (unsigned long) (key & 0xffffffff));
+ osi_Log4(afsd_logp, "... key <0x%x,0x%x,0x%x> flags 0x%x",
+ key.process_id, key.session_id, key.file_id, flags);
+
+ if (!exact_match)
+ RangeEnd.QuadPart = LOffset.QuadPart + LLength.QuadPart;
+ try_again:
lock_ObtainRead(&cm_scacheLock);
for (q = scp->fileLocksH; q; q = osi_QNext(q)) {
osi_assertx(FALSE, "invalid fid value");
}
#endif
- if (!IS_LOCK_DELETED(fileLock) &&
- fileLock->key == key &&
- fileLock->range.offset == LOffset.QuadPart &&
- fileLock->range.length == LLength.QuadPart) {
- break;
+ if (exact_match) {
+ if (!IS_LOCK_DELETED(fileLock) &&
+ cm_KeyEquals(&fileLock->key, &key, 0) &&
+ fileLock->range.offset == LOffset.QuadPart &&
+ fileLock->range.length == LLength.QuadPart) {
+ lock_found = 1;
+ break;
+ }
+ } else {
+
+ if (!IS_LOCK_DELETED(fileLock) &&
+ cm_KeyEquals(&fileLock->key, &key, 0) &&
+ fileLock->range.offset >= LOffset.QuadPart &&
+ fileLock->range.offset < RangeEnd.QuadPart &&
+ (fileLock->range.offset + fileLock->range.length) <= RangeEnd.QuadPart) {
+ lock_found = 1;
+ break;
+ }
}
}
if (!q) {
- osi_Log0(afsd_logp, "cm_Unlock lock not found; failure");
-
lock_ReleaseRead(&cm_scacheLock);
- /* The lock didn't exist anyway. *shrug* */
- return CM_ERROR_RANGE_NOT_LOCKED;
+ if (lock_found && !exact_match) {
+ code = 0;
+ goto done;
+ } else {
+ osi_Log0(afsd_logp, "cm_Unlock lock not found; failure");
+
+ /* The lock didn't exist anyway. *shrug* */
+ return CM_ERROR_RANGE_NOT_LOCKED;
+ }
}
/* discard lock record */
/* 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) {
}
}
- if (release_userp)
+ if (release_userp) {
cm_ReleaseUser(userp);
+ release_userp = FALSE;
+ }
+
+ if (!exact_match)
+ goto try_again; /* might be more than one lock in the range */
done:
}
scp->serverLock = -1;
- scp->lockDataVersion = -1;
+ scp->lockDataVersion = CM_SCACHE_VERSION_BAD;
lock_ReleaseWrite(&cm_scacheLock);
}
struct rx_connection * rxconnp;
cm_scache_t * scp;
+ memset(&volSync, 0, sizeof(volSync));
+
cm_InitReq(&req);
lock_ObtainWrite(&cm_scacheLock);
(unsigned)(oldFileLock->range.offset & 0xffffffff),
(unsigned)(oldFileLock->range.length >> 32),
(unsigned)(oldFileLock->range.length & 0xffffffff));
- osi_Log3(afsd_logp, " key(%x:%x) flags=%x",
- (unsigned)(oldFileLock->key >> 32),
- (unsigned)(oldFileLock->key & 0xffffffff),
+ osi_Log4(afsd_logp, " key<0x%x,0x%x,0x%x> flags=%x",
+ oldFileLock->key.process_id, oldFileLock->key.session_id, oldFileLock->key.file_id,
(unsigned)(oldFileLock->flags));
/* if the lock has already been granted, then we have nothing to do */
((char *) q - offsetof(cm_file_lock_t, fileq));
if (IS_LOCK_LOST(fileLock)) {
- if (fileLock->key == oldFileLock->key) {
+ if (cm_KeyEquals(&fileLock->key, &oldFileLock->key, 0)) {
code = CM_ERROR_BADFD;
oldFileLock->flags |= CM_FILELOCK_FLAG_LOST;
osi_Log1(afsd_logp, " found lost lock %p for same key. Marking lock as lost",
return code;
}
-cm_key_t cm_GenerateKey(unsigned int session_id, unsigned long process_id, unsigned int file_id)
+cm_key_t cm_GenerateKey(afs_uint16 session_id, afs_offs_t process_id, afs_uint16 file_id)
{
-#ifdef DEBUG
- osi_assertx((process_id & 0xffffffff) == process_id, "unexpected process_id");
- osi_assertx((session_id & 0xffff) == session_id, "unexpected session_id");
- osi_assertx((file_id & 0xffff) == file_id, "unexpected file_id");
-#endif
+ cm_key_t key;
- return
- (((cm_key_t) (process_id & 0xffffffff)) << 32) |
- (((cm_key_t) (session_id & 0xffff)) << 16) |
- (((cm_key_t) (file_id & 0xffff)));
+ key.process_id = process_id;
+ key.session_id = session_id;
+ key.file_id = file_id;
+
+ return key;
}
-static int cm_KeyEquals(cm_key_t k1, cm_key_t k2, int flags)
+int cm_KeyEquals(cm_key_t *k1, cm_key_t *k2, int flags)
{
- if (flags & CM_UNLOCK_BY_FID) {
- return ((k1 & 0xffffffff) == (k2 & 0xffffffff));
- } else {
- return (k1 == k2);
- }
+ return (k1->session_id == k2->session_id) && (k1->file_id == k2->file_id) &&
+ ((flags & CM_UNLOCK_BY_FID) || (k1->process_id == k2->process_id));
}
void cm_ReleaseAllLocks(void)