int cm_enableServerLocks = 1;
+int cm_followBackupPath = 0;
+
/*
* Case-folding array. This was constructed by inspecting of SMBtrace output.
* I do not know anything more about it.
long rights;
long code;
- osi_assert(ldpp != NULL);
+ osi_assertx(ldpp != NULL, "null cm_lock_data_t");
*ldpp = NULL;
/* Always allow delete; the RPC will tell us if it's OK */
_done:
lock_ReleaseMutex(&scp->mx);
+ osi_Log3(afsd_logp,"cm_CheckNTOpen scp 0x%p ldp 0x%p code 0x%x", scp, *ldpp, code);
return code;
}
extern long cm_CheckNTOpenDone(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
cm_lock_data_t ** ldpp)
{
+ osi_Log2(afsd_logp,"cm_CheckNTOpenDone scp 0x%p ldp 0x%p", scp, *ldpp);
if (*ldpp) {
lock_ObtainMutex(&scp->mx);
cm_Unlock(scp, (*ldpp)->sLockType, (*ldpp)->LOffset, (*ldpp)->LLength,
long code;
osi_hyper_t thyper;
cm_buf_t *bufferp;
- cm_dirEntry_t *dep;
+ cm_dirEntry_t *dep = 0;
unsigned short *hashTable;
unsigned int i, idx;
int BeyondPage = 0, HaveDot = 0, HaveDotDot = 0;
return code;
thyper.HighPart = 0; thyper.LowPart = 0;
- lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
if (code)
return code;
{
char *tp;
long code;
- cm_dirEntry_t *dep;
+ cm_dirEntry_t *dep = 0;
cm_buf_t *bufferp;
long temp;
osi_hyper_t dirLength;
return 0;
}
- return CM_ERROR_NOSUCHFILE;
+ return CM_ERROR_BPLUS_NOMATCH;
}
#endif
}
bufferp = NULL;
}
- lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
if (code) {
/* if buf_Get() fails we do not have a buffer object to lock */
bufferp = NULL;
/* otherwise, we have to read it in */
lock_ReleaseMutex(&scp->mx);
- lock_ObtainRead(&scp->bufCreateLock);
thyper.LowPart = thyper.HighPart = 0;
code = buf_Get(scp, &thyper, &bufp);
- lock_ReleaseRead(&scp->bufCreateLock);
lock_ObtainMutex(&scp->mx);
if (code)
char mtType;
cm_fid_t tfid;
size_t vnLength;
- int type;
+ int targetType;
if (scp->mountRootFid.cell != 0 && scp->mountRootGen >= cm_data.mountRootGen) {
tfid = scp->mountRootFid;
strncpy(cellNamep, mpNamep+1, cp - mpNamep - 1);
strcpy(volNamep, cp+1);
/* now look up the cell */
+ lock_ReleaseMutex(&scp->mx);
cellp = cm_GetCell(cellNamep, CM_FLAG_CREATE);
+ lock_ObtainMutex(&scp->mx);
}
else {
/* normal mt pt */
strcpy(volNamep, mpNamep+1);
- cellp = cm_FindCellByID(scp->fid.cell);
+ cellp = cm_FindCellByID(scp->fid.cell, 0);
}
if (!cellp) {
vnLength = strlen(volNamep);
if (vnLength >= 8 && strcmp(volNamep + vnLength - 7, ".backup") == 0)
- type = BACKVOL;
+ targetType = BACKVOL;
else if (vnLength >= 10
&& strcmp(volNamep + vnLength - 9, ".readonly") == 0)
- type = ROVOL;
+ targetType = ROVOL;
else
- type = RWVOL;
+ targetType = RWVOL;
/* check for backups within backups */
- if (type == BACKVOL
+ if (targetType == BACKVOL
&& (scp->flags & (CM_SCACHEFLAG_RO | CM_SCACHEFLAG_PURERO))
== CM_SCACHEFLAG_RO) {
code = CM_ERROR_NOSUCHVOLUME;
lock_ObtainMutex(&scp->mx);
if (code == 0) {
+ afs_uint32 cell, volume;
+
/* save the parent of the volume root for this is the
* place where the volume is mounted and we must remember
* this in the volume structure rather than just in the
volp->dotdotFid = dscp->fid;
lock_ReleaseMutex(&volp->mx);
- scp->mountRootFid.cell = cellp->cellID;
+ cell = cellp->cellID;
+
+ /* if the mt pt originates in a .backup volume (not a .readonly)
+ * and FollowBackupPath is active, and if there is a .backup
+ * volume for the target, then use the .backup of the target
+ * instead of the read-write.
+ */
+ if (cm_followBackupPath &&
+ volp->bk.ID != 0 &&
+ (dscp->flags & (CM_SCACHEFLAG_RO|CM_SCACHEFLAG_PURERO)) == CM_SCACHEFLAG_RO &&
+ (targetType == RWVOL || targetType == ROVOL && volp->ro.ID == 0)
+ ) {
+ targetType = BACKVOL;
+ }
/* if the mt pt is in a read-only volume (not just a
* backup), and if there is a read-only volume for the
- * target, and if this is a type '#' mount point, use
+ * target, and if this is a targetType '#' mount point, use
* the read-only, otherwise use the one specified.
*/
- if (mtType == '#' && (scp->flags & CM_SCACHEFLAG_PURERO)
- && volp->ro.ID != 0 && type == RWVOL)
- type = ROVOL;
- if (type == ROVOL)
- scp->mountRootFid.volume = volp->ro.ID;
- else if (type == BACKVOL)
- scp->mountRootFid.volume = volp->bk.ID;
+ else if (mtType == '#' && targetType == RWVOL &&
+ (scp->flags & CM_SCACHEFLAG_PURERO) &&
+ volp->ro.ID != 0) {
+ targetType = ROVOL;
+ }
+ if (targetType == ROVOL)
+ volume = volp->ro.ID;
+ else if (targetType == BACKVOL)
+ volume = volp->bk.ID;
else
- scp->mountRootFid.volume = volp->rw.ID;
+ volume = volp->rw.ID;
/* the rest of the fid is a magic number */
- scp->mountRootFid.vnode = 1;
- scp->mountRootFid.unique = 1;
+ cm_SetFid(&scp->mountRootFid, cell, volume, 1, 1);
scp->mountRootGen = cm_data.mountRootGen;
tfid = scp->mountRootFid;
goto haveFid;
}
- return CM_ERROR_NOSUCHFILE;
+ return CM_ERROR_BPLUS_NOMATCH;
}
#endif
}
else
return CM_ERROR_NOSUCHFILE;
}
- else { /* nonexistent dir on freelance root, so add it */
+ else if (!strchr(namep, '#') && !strchr(namep, '%') &&
+ strcmp(namep, "srvsvc") && strcmp(namep, "wkssvc") &&
+ strcmp(namep, "ipc$")) {
+ /* nonexistent dir on freelance root, so add it */
char fullname[200] = ".";
int found = 0;
osi_Log1(afsd_logp,"cm_Lookup adding mount for non-existent directory: %s",
osi_LogSaveString(afsd_logp,namep));
+
+ /*
+ * There is an ugly behavior where a share name "foo" will be searched
+ * for as "fo". If the searched for name differs by an already existing
+ * symlink or mount point in the Freelance directory, do not add the
+ * new value automatically.
+ */
+
+ code = -1;
if (namep[0] == '.') {
if (cm_GetCell_Gen(&namep[1], &fullname[1], CM_FLAG_CREATE)) {
found = 1;
- if ( stricmp(&namep[1], &fullname[1]) )
+ if (!cm_FreelanceMountPointExists(fullname, 0))
+ code = cm_FreelanceAddMount(fullname, &fullname[1], "root.cell.", 1, &rock.fid);
+ if ( stricmp(&namep[1], &fullname[1]) &&
+ !cm_FreelanceMountPointExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0) &&
+ !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid);
- else
- code = cm_FreelanceAddMount(namep, &fullname[1], "root.cell.", 1, &rock.fid);
}
} else {
if (cm_GetCell_Gen(namep, fullname, CM_FLAG_CREATE)) {
found = 1;
- if ( stricmp(namep, fullname) )
+ if (!cm_FreelanceMountPointExists(fullname, 0))
+ code = cm_FreelanceAddMount(fullname, fullname, "root.cell.", 0, &rock.fid);
+ if ( stricmp(namep, fullname) &&
+ !cm_FreelanceMountPointExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0) &&
+ !cm_FreelanceSymlinkExists(namep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
code = cm_FreelanceAddSymlink(namep, fullname, &rock.fid);
- else
- code = cm_FreelanceAddMount(namep, fullname, "root.cell.", 0, &rock.fid);
}
}
if (!found || code < 0) { /* add mount point failed, so give up */
cm_cell_t * cellp = NULL;
cm_volume_t * volp = NULL;
cm_fid_t fid;
+ afs_uint32 volume;
int volType;
int mountType = RWVOL;
if (code != 0)
goto _exit_cleanup;
- fid.cell = cellp->cellID;
-
if (volType == BACKVOL)
- fid.volume = volp->bk.ID;
+ volume = volp->bk.ID;
else if (volType == ROVOL ||
(volType == RWVOL && mountType == ROVOL && volp->ro.ID != 0))
- fid.volume = volp->ro.ID;
+ volume = volp->ro.ID;
else
- fid.volume = volp->rw.ID;
+ volume = volp->rw.ID;
- fid.vnode = 1;
- fid.unique = 1;
+ cm_SetFid(&fid, cellp->cellID, volume, 1, 1);
code = cm_GetSCache(&fid, outpScpp, userp, reqp);
#endif
{
long code;
- char tname[256];
+ char tname[AFSPATHMAX];
int sysNameIndex = 0;
cm_scache_t *scp = NULL;
else
osi_Log0(afsd_logp, "CALL RemoveFile SUCCESS");
- lock_ObtainWrite(&dscp->dirlock);
- dirop.lockType = CM_DIRLOCK_WRITE;
+ if (dirop.scp) {
+ lock_ObtainWrite(&dirop.scp->dirlock);
+ dirop.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&dscp->mx);
cm_dnlcRemove(dscp, namep);
cm_SyncOpDone(dscp, NULL, sflags);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, 0);
+ cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, 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
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 */
char *linkp;
cm_space_t *tsp;
+ *newRootScpp = NULL;
+ *newSpaceBufferp = NULL;
+
lock_ObtainMutex(&linkScp->mx);
code = cm_HandleLink(linkScp, userp, reqp);
- if (code)
+ if (code)
goto done;
/* if we may overflow the buffer, bail out; buffer is signficantly
} else {
linkScp->fileType = CM_SCACHETYPE_DFSLINK;
strcpy(tsp->data, linkp);
- *newRootScpp = NULL;
code = CM_ERROR_PATH_NOT_COVERED;
}
- } else if ( !strnicmp(linkp, "msdfs:", (len = (long)strlen("msdfs:"))) ) {
+ } else if ( linkScp->fileType == CM_SCACHETYPE_DFSLINK ||
+ !strnicmp(linkp, "msdfs:", (len = (long)strlen("msdfs:"))) ) {
linkScp->fileType = CM_SCACHETYPE_DFSLINK;
strcpy(tsp->data, linkp);
- *newRootScpp = NULL;
code = CM_ERROR_PATH_NOT_COVERED;
} else if (*linkp == '\\' || *linkp == '/') {
#if 0
*/
linkScp->fileType = CM_SCACHETYPE_INVALID;
strcpy(tsp->data, linkp);
- *newRootScpp = NULL;
code = CM_ERROR_NOSUCHPATH;
#endif
} else {
/* a relative link */
strcpy(tsp->data, linkp);
- *newRootScpp = NULL;
}
if (pathSuffixp[0] != 0) { /* if suffix string is non-null */
strcat(tsp->data, "\\");
strcat(tsp->data, pathSuffixp);
}
- *newSpaceBufferp = tsp;
+ if (code == 0)
+ *newSpaceBufferp = tsp;
+ else {
+ cm_FreeSpace(tsp);
+
+ if (code == CM_ERROR_PATH_NOT_COVERED && reqp->tidPathp && reqp->relPathp)
+ cm_VolStatus_Notify_DFS_Mapping(linkScp, reqp->tidPathp, reqp->relPathp);
+ }
done:
lock_ReleaseMutex(&linkScp->mx);
char *tp; /* ptr moving through input buffer */
char tc; /* temp char */
int haveComponent; /* has new component started? */
- char component[256]; /* this is the new component */
+ char component[AFSPATHMAX]; /* this is the new component */
char *cp; /* component name being assembled */
cm_scache_t *tscp; /* current location in the hierarchy */
cm_scache_t *nscp; /* next dude down */
if (!cm_FidCmp(&nscp->fid, &fids[i]))
break;
}
+ fid_count = i+1;
} else {
/* add the new fid to the list */
for ( i=0; i<fid_count; i++) {
fids[fid_count++] = nscp->fid;
}
}
- } else {
+ }
+
+ if (code) {
cm_ReleaseSCache(tscp);
if (dirScp)
cm_ReleaseSCache(dirScp);
if (psp)
cm_FreeSpace(psp);
- if (code == CM_ERROR_NOSUCHFILE && tscp->fileType == CM_SCACHETYPE_SYMLINK) {
+ if ((code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) &&
+ tscp->fileType == CM_SCACHETYPE_SYMLINK)
+ {
osi_Log0(afsd_logp,"cm_NameI code CM_ERROR_NOSUCHPATH");
return CM_ERROR_NOSUCHPATH;
} else {
osi_Log1(afsd_logp,"cm_NameI code 0x%x", code);
return code;
}
- }
+ }
+
haveComponent = 0; /* component done */
if (dirScp)
cm_ReleaseSCache(dirScp);
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW | CM_FLAG_DIRSEARCH,
userp, NULL, reqp, outScpp);
- if (code == CM_ERROR_NOSUCHFILE)
+ if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH)
code = CM_ERROR_NOSUCHPATH;
/* this stuff is allocated no matter what happened on the namei call,
if (strcmp(dep->name, ".") == 0 || strcmp(dep->name, "..") == 0)
return 0;
- tfid.cell = scp->fid.cell;
- tfid.volume = scp->fid.volume;
- tfid.vnode = ntohl(dep->fid.vnode);
- tfid.unique = ntohl(dep->fid.unique);
+ cm_SetFid(&tfid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
tscp = cm_FindSCache(&tfid);
if (tscp) {
if (lock_TryMutex(&tscp->mx)) {
osi_Log1(afsd_logp, "cm_TryBulkStat dir 0x%p", dscp);
/* should be on a buffer boundary */
- osi_assert((offsetp->LowPart & (cm_data.buf_blockSize - 1)) == 0);
+ osi_assertx((offsetp->LowPart & (cm_data.buf_blockSize - 1)) == 0, "invalid offset");
memset(&bb, 0, sizeof(bb));
bb.bufOffset = *offsetp;
/* otherwise, we should do the merges */
for (i = 0; i<filesThisCall; i++) {
j = filex + i;
- tfid.cell = dscp->fid.cell;
- tfid.volume = bb.fids[j].Volume;
- tfid.vnode = bb.fids[j].Vnode;
- tfid.unique = bb.fids[j].Unique;
+ cm_SetFid(&tfid, dscp->fid.cell, bb.fids[j].Volume, bb.fids[j].Vnode, bb.fids[j].Unique);
code = cm_GetSCache(&tfid, &scp, userp, reqp);
if (code != 0)
continue;
return CM_ERROR_ATSYS;
}
+#ifdef AFS_FREELANCE_CLIENT
+ /* Freelance root volume does not hold files */
+ if (cm_freelanceEnabled &&
+ dscp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ dscp->fid.volume==AFS_FAKE_ROOT_VOL_ID )
+ {
+ return CM_ERROR_NOACCESS;
+ }
+#endif /* AFS_FREELANCE_CLIENT */
+
/* before starting the RPC, mark that we're changing the file data, so
* that someone who does a chmod will know to wait until our call
* completes.
else
osi_Log0(afsd_logp, "CALL CreateFile SUCCESS");
- lock_ObtainWrite(&dscp->dirlock);
- dirop.lockType = CM_DIRLOCK_WRITE;
+ if (dirop.scp) {
+ lock_ObtainWrite(&dirop.scp->dirlock);
+ dirop.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&dscp->mx);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseMutex(&dscp->mx);
* info.
*/
if (code == 0) {
- newFid.cell = dscp->fid.cell;
- newFid.volume = dscp->fid.volume;
- newFid.vnode = newAFSFid.Vnode;
- newFid.unique = newAFSFid.Unique;
+ cm_SetFid(&newFid, dscp->fid.cell, dscp->fid.volume, newAFSFid.Vnode, newAFSFid.Unique);
code = cm_GetSCache(&newFid, &scp, userp, reqp);
if (code == 0) {
lock_ObtainMutex(&scp->mx);
{
long code;
- lock_ObtainWrite(&scp->bufCreateLock);
code = buf_CleanVnode(scp, userp, reqp);
- lock_ReleaseWrite(&scp->bufCreateLock);
if (code == 0) {
lock_ObtainMutex(&scp->mx);
return CM_ERROR_ATSYS;
}
+#ifdef AFS_FREELANCE_CLIENT
+ /* Freelance root volume does not hold subdirectories */
+ if (cm_freelanceEnabled &&
+ dscp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ dscp->fid.volume==AFS_FAKE_ROOT_VOL_ID )
+ {
+ return CM_ERROR_NOACCESS;
+ }
+#endif /* AFS_FREELANCE_CLIENT */
+
/* 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.
else
osi_Log0(afsd_logp, "CALL MakeDir SUCCESS");
- lock_ObtainWrite(&dscp->dirlock);
- dirop.lockType = CM_DIRLOCK_WRITE;
+ if (dirop.scp) {
+ lock_ObtainWrite(&dirop.scp->dirlock);
+ dirop.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&dscp->mx);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseMutex(&dscp->mx);
* info.
*/
if (code == 0) {
- newFid.cell = dscp->fid.cell;
- newFid.volume = dscp->fid.volume;
- newFid.vnode = newAFSFid.Vnode;
- newFid.unique = newAFSFid.Unique;
+ cm_SetFid(&newFid, dscp->fid.cell, dscp->fid.volume, newAFSFid.Vnode, newAFSFid.Unique);
code = cm_GetSCache(&newFid, &scp, userp, reqp);
if (code == 0) {
lock_ObtainMutex(&scp->mx);
else
osi_Log0(afsd_logp, "CALL Link SUCCESS");
- lock_ObtainWrite(&dscp->dirlock);
- dirop.lockType = CM_DIRLOCK_WRITE;
+ if (dirop.scp) {
+ lock_ObtainWrite(&dirop.scp->dirlock);
+ dirop.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&dscp->mx);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ }
+ lock_ReleaseMutex(&dscp->mx);
+
+ if (code == 0) {
if (cm_CheckDirOpForSingleChange(&dirop)) {
cm_DirCreateEntry(&dirop, namep, &sscp->fid);
#ifdef USE_BPLUS
}
}
cm_EndDirOp(&dirop);
- lock_ReleaseMutex(&dscp->mx);
return code;
}
else
osi_Log0(afsd_logp, "CALL Symlink SUCCESS");
- lock_ObtainWrite(&dscp->dirlock);
- dirop.lockType = CM_DIRLOCK_WRITE;
+ if (dirop.scp) {
+ lock_ObtainWrite(&dirop.scp->dirlock);
+ dirop.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&dscp->mx);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
+ }
+ lock_ReleaseMutex(&dscp->mx);
+
+ if (code == 0) {
if (cm_CheckDirOpForSingleChange(&dirop)) {
- newFid.cell = dscp->fid.cell;
- newFid.volume = dscp->fid.volume;
- newFid.vnode = newAFSFid.Vnode;
- newFid.unique = newAFSFid.Unique;
+ cm_SetFid(&newFid, dscp->fid.cell, dscp->fid.volume, newAFSFid.Vnode, newAFSFid.Unique);
cm_DirCreateEntry(&dirop, namep, &newFid);
#ifdef USE_BPLUS
}
}
cm_EndDirOp(&dirop);
- lock_ReleaseMutex(&dscp->mx);
/* now try to create the new dir's entry, too, but be careful to
* make sure that we don't merge in old info. Since we weren't locking
* info.
*/
if (code == 0) {
- newFid.cell = dscp->fid.cell;
- newFid.volume = dscp->fid.volume;
- newFid.vnode = newAFSFid.Vnode;
- newFid.unique = newAFSFid.Unique;
+ cm_SetFid(&newFid, dscp->fid.cell, dscp->fid.volume, newAFSFid.Vnode, newAFSFid.Unique);
code = cm_GetSCache(&newFid, &scp, userp, reqp);
if (code == 0) {
lock_ObtainMutex(&scp->mx);
else
osi_Log0(afsd_logp, "CALL RemoveDir SUCCESS");
- lock_ObtainWrite(&dscp->dirlock);
- dirop.lockType = CM_DIRLOCK_WRITE;
+ if (dirop.scp) {
+ lock_ObtainWrite(&dirop.scp->dirlock);
+ dirop.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&dscp->mx);
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
cm_dnlcRemove(dscp, namep);
- cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, CM_MERGEFLAG_DIROP);
}
lock_ReleaseMutex(&dscp->mx);
osi_Log0(afsd_logp, "CALL Rename SUCCESS");
/* update the individual stat cache entries for the directories */
- lock_ObtainWrite(&oldDscp->dirlock);
- oldDirOp.lockType = CM_DIRLOCK_WRITE;
+ if (oldDirOp.scp) {
+ lock_ObtainWrite(&oldDirOp.scp->dirlock);
+ oldDirOp.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&oldDscp->mx);
cm_SyncOpDone(oldDscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0)
cm_MergeStatus(NULL, oldDscp, &updatedOldDirStatus, &volSync,
- userp, 0);
+ userp, CM_MERGEFLAG_DIROP);
lock_ReleaseMutex(&oldDscp->mx);
if (code == 0) {
/* and update it for the new one, too, if necessary */
if (!oneDir) {
- lock_ObtainWrite(&newDscp->dirlock);
- newDirOp.lockType = CM_DIRLOCK_WRITE;
+ if (newDirOp.scp) {
+ lock_ObtainWrite(&newDirOp.scp->dirlock);
+ newDirOp.lockType = CM_DIRLOCK_WRITE;
+ }
lock_ObtainMutex(&newDscp->mx);
cm_SyncOpDone(newDscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0)
cm_MergeStatus(NULL, newDscp, &updatedNewDirStatus, &volSync,
- userp, 0);
+ userp, CM_MERGEFLAG_DIROP);
lock_ReleaseMutex(&newDscp->mx);
if (code == 0) {
#endif
}
-/* Forward dcl. */
-static void cm_LockMarkSCacheLost(cm_scache_t * scp);
-
/* Called with cm_scacheLock write locked */
static cm_file_lock_t * cm_GetFileLock(void) {
cm_file_lock_t * l;
osi_QRemove(&cm_freeFileLocks, &l->q);
} else {
l = malloc(sizeof(cm_file_lock_t));
- osi_assert(l);
+ osi_assertx(l, "null cm_file_lock_t");
}
memset(l, 0, sizeof(cm_file_lock_t));
rights |= PRSFS_WRITE | PRSFS_LOCK;
else {
/* hmmkay */
- osi_assert(FALSE);
+ osi_assertx(FALSE, "invalid lock type");
return 0;
}
osi_Log0(afsd_logp,
" attempting to UPGRADE from LockRead to LockWrite.");
osi_Log1(afsd_logp,
- " dataVersion on scp: %d", scp->dataVersion);
+ " dataVersion on scp: %I64d", scp->dataVersion);
/* we assume at this point (because scp->serverLock
was valid) that we had a valid server lock. */
newLock = Which;
/* am I sane? */
- osi_assert(newLock == LockRead);
+ osi_assertx(newLock == LockRead, "lock type not read");
code = cm_IntSetLock(scp, userp, newLock, reqp);
}
osi_Log0(afsd_logp,
" Data version mismatch while upgrading lock.");
osi_Log2(afsd_logp,
- " Data versions before=%d, after=%d",
+ " Data versions before=%I64d, after=%I64d",
scp->lockDataVersion,
scp->dataVersion);
osi_Log1(afsd_logp,
fileLock->scp->fid.volume,
fileLock->scp->fid.vnode,
fileLock->scp->fid.unique);
- osi_assert(FALSE);
+ osi_assertx(FALSE, "invalid fid value");
}
#endif
/* since scp->serverLock looked sane, we are going to assume
that we have a valid server lock. */
scp->lockDataVersion = scp->dataVersion;
- osi_Log1(afsd_logp, " dataVersion on scp = %d", scp->dataVersion);
+ osi_Log1(afsd_logp, " dataVersion on scp = %I64d", scp->dataVersion);
code = cm_IntReleaseLock(scp, userp, reqp);
we have lost the lock we had during the transition. */
osi_Log0(afsd_logp, "Data version mismatch during lock downgrade");
- osi_Log2(afsd_logp, " Data versions before=%d, after=%d",
+ osi_Log2(afsd_logp, " Data versions before=%I64d, after=%I64d",
scp->lockDataVersion,
scp->dataVersion);
fileLock->scp->fid.volume,
fileLock->scp->fid.vnode,
fileLock->scp->fid.unique);
- osi_assert(FALSE);
+ osi_assertx(FALSE, "invalid fid value");
}
#endif
if (!IS_LOCK_DELETED(fileLock) &&
lock_ReleaseRead(&cm_scacheLock);
/* The lock didn't exist anyway. *shrug* */
- return 0;
+ return CM_ERROR_RANGE_NOT_LOCKED;
}
lock_ReleaseRead(&cm_scacheLock);
/* Since we already had a lock, we assume that there is a
valid server lock. */
scp->lockDataVersion = scp->dataVersion;
- osi_Log1(afsd_logp, " dataVersion on scp is %d", scp->dataVersion);
+ osi_Log1(afsd_logp, " dataVersion on scp is %I64d", scp->dataVersion);
/* before we downgrade, make sure that we have enough
permissions to get the read lock. */
osi_Log0(afsd_logp,
"Data version mismatch while downgrading lock");
osi_Log2(afsd_logp,
- " Data versions before=%d, after=%d",
+ " Data versions before=%I64d, after=%I64d",
scp->lockDataVersion,
scp->dataVersion);
}
/* called with scp->mx held */
-static void cm_LockMarkSCacheLost(cm_scache_t * scp)
+void cm_LockMarkSCacheLost(cm_scache_t * scp)
{
cm_file_lock_t *fileLock;
osi_queue_t *q;
#ifdef DEBUG
/* With the current code, we can't lose a lock on a RO scp */
- osi_assert(!(scp->flags & CM_SCACHEFLAG_RO));
+ osi_assertx(!(scp->flags & CM_SCACHEFLAG_RO), "CM_SCACHEFLAG_RO unexpected");
#endif
/* cm_scacheLock needed because we are modifying fileLock->flags */
/* Server locks must have been enabled for us to have
received an active non-client-only lock. */
- osi_assert(cm_enableServerLocks);
+ osi_assertx(cm_enableServerLocks, "!cm_enableServerLocks");
scp = fileLock->scp;
- osi_assert(scp != NULL);
+ osi_assertx(scp != NULL, "null cm_scache_t");
cm_HoldSCacheNoLock(scp);
fileLock->scp->fid.volume,
fileLock->scp->fid.vnode,
fileLock->scp->fid.unique);
- osi_assert(FALSE);
+ osi_assertx(FALSE, "invalid fid");
}
#endif
/* Server locks are extended once per scp per refresh
if (!IS_LOCK_ACTIVE(fileLock))
goto pre_syncopdone;
- if (scp->serverLock != -1) {
+ if (scp->serverLock != -1 && !(scp->flags & CM_SCACHEFLAG_DELETED)) {
cm_fid_t cfid;
cm_user_t * userp;
"Data version mismatch on scp 0x%p",
scp);
osi_Log2(afsd_logp,
- " Data versions: before=%d, after=%d",
+ " Data versions: before=%I64d, after=%I64d",
scp->lockDataVersion,
scp->dataVersion);
}
}
- if (code == EINVAL || code == CM_ERROR_INVAL) {
+ if (code == EINVAL || code == CM_ERROR_INVAL ||
+ code == CM_ERROR_BADFD) {
cm_LockMarkSCacheLost(scp);
}
scp = oldFileLock->scp;
- osi_assert(scp != NULL);
+ osi_assertx(scp != NULL, "null cm_scache_t");
lock_ReleaseRead(&cm_scacheLock);
lock_ObtainMutex(&scp->mx);
oldFileLock->flags |= CM_FILELOCK_FLAG_WAITLOCK;
}
- osi_assert(IS_LOCK_WAITLOCK(oldFileLock));
+ osi_assertx(IS_LOCK_WAITLOCK(oldFileLock), "!IS_LOCK_WAITLOCK");
if (force_client_lock ||
!SERVERLOCKS_ENABLED(scp) ||
if (scp->serverLock == LockRead) {
- osi_assert(newLock == LockWrite);
+ osi_assertx(newLock == LockWrite, "!LockWrite");
osi_Log0(afsd_logp, " Attempting to UPGRADE from LockRead to LockWrite");
osi_Log0(afsd_logp,
" Data version mismatch while upgrading lock.");
osi_Log2(afsd_logp,
- " Data versions before=%d, after=%d",
+ " Data versions before=%I64d, after=%I64d",
scp->lockDataVersion,
scp->dataVersion);
osi_Log1(afsd_logp,
cm_key_t cm_GenerateKey(unsigned int session_id, unsigned long process_id, unsigned int file_id)
{
#ifdef DEBUG
- osi_assert((process_id & 0xffffffff) == process_id);
- osi_assert((session_id & 0xffff) == session_id);
- osi_assert((file_id & 0xffff) == file_id);
+ 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
return