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
lock_ObtainWrite(&scp->rw);
if (*ldpp) {
cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength,
- (*ldpp)->key, userp, reqp);
+ (*ldpp)->key, 0, userp, reqp);
free(*ldpp);
*ldpp = NULL;
}
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;
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;
lock_ReleaseWrite(&scp->rw);
thyper.LowPart = thyper.HighPart = 0;
- code = buf_Get(scp, &thyper, &bufp);
+ code = buf_Get(scp, &thyper, reqp, &bufp);
lock_ObtainWrite(&scp->rw);
if (code)
/* 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) {
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
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);
}
}
/* read the link data from the file server*/
lock_ReleaseWrite(&linkScp->rw);
thyper.LowPart = thyper.HighPart = 0;
- code = buf_Get(linkScp, &thyper, &bufp);
+ code = buf_Get(linkScp, &thyper, reqp, &bufp);
lock_ObtainWrite(&linkScp->rw);
if (code)
return code;
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;
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.
* much better on the next immediate call, either.
*/
if (code) {
- cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
+ cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
break;
}
| CM_SCACHEFLAG_SIZESTORING))) {
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);
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);
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)
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 && cm_CheckDirOpForSingleChange(&oldDirOp)) {
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
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;
"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;
}
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_Log3(afsd_logp, "... key <0x%x,0x%x,0x%x>",
- key.process_id, key.session_id, key.file_id);
+ 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) &&
- cm_KeyEquals(&fileLock->key, &key, 0) &&
- 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 */
}
}
- 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);