Index: openafs/src/WINNT/afsclass/afsclassfn.cpp
diff -c openafs/src/WINNT/afsclass/afsclassfn.cpp:1.6 openafs/src/WINNT/afsclass/afsclassfn.cpp:1.6.4.1
*** openafs/src/WINNT/afsclass/afsclassfn.cpp:1.6 Sat Nov 5 01:47:44 2005
--- openafs/src/WINNT/afsclass/afsclassfn.cpp Thu Jul 19 11:56:53 2007
***************
*** 51,59 ****
AfsClass_Enter();
NOTIFYCALLBACK::SendNotificationToAll (evtGetServerLogFileBegin, lpiServer, pszRemote, 0);
! PVOID hCell;
! PVOID hBOS;
! LPSERVER lpServer;
if ((lpServer = lpiServer->OpenServer (&status)) == NULL)
rc = FALSE;
else
--- 51,59 ----
AfsClass_Enter();
NOTIFYCALLBACK::SendNotificationToAll (evtGetServerLogFileBegin, lpiServer, pszRemote, 0);
! PVOID hCell = NULL;
! PVOID hBOS = NULL;
! LPSERVER lpServer = NULL;
if ((lpServer = lpiServer->OpenServer (&status)) == NULL)
rc = FALSE;
else
***************
*** 387,394 ****
AfsClass_Enter();
NOTIFYCALLBACK::SendNotificationToAll (evtRestartServiceBegin, lpiRestart);
! PVOID hCell;
! PVOID hBOS;
LPSERVER lpServer;
if ((lpServer = lpiRestart->OpenServer (&status)) == NULL)
rc = FALSE;
--- 387,394 ----
AfsClass_Enter();
NOTIFYCALLBACK::SendNotificationToAll (evtRestartServiceBegin, lpiRestart);
! PVOID hCell = NULL;
! PVOID hBOS = NULL;
LPSERVER lpServer;
if ((lpServer = lpiRestart->OpenServer (&status)) == NULL)
rc = FALSE;
***************
*** 489,497 ****
// Obtain hCell and hVOS
//
! PVOID hCell;
PVOID hVOS = NULL;
! LPSERVER lpServer;
if ((lpServer = lpiAggregate->OpenServer (&status)) == NULL)
rc = FALSE;
else
--- 489,497 ----
// Obtain hCell and hVOS
//
! PVOID hCell = NULL;
PVOID hVOS = NULL;
! LPSERVER lpServer = NULL;
if ((lpServer = lpiAggregate->OpenServer (&status)) == NULL)
rc = FALSE;
else
***************
*** 603,611 ****
// Obtain hCell and hVOS
//
! PVOID hCell;
PVOID hVOS = NULL;
! LPSERVER lpServer;
if ((lpServer = lpiFileset->OpenServer (&status)) == NULL)
rc = FALSE;
else
--- 603,611 ----
// Obtain hCell and hVOS
//
! PVOID hCell = NULL;
PVOID hVOS = NULL;
! LPSERVER lpServer = NULL;
if ((lpServer = lpiFileset->OpenServer (&status)) == NULL)
rc = FALSE;
else
***************
*** 1151,1157 ****
lpServer->Close();
}
- LPCELL lpCell;
if ((lpCell = lpiServer->OpenCell (&status)) == NULL)
rc = FALSE;
else
--- 1151,1156 ----
Index: openafs/src/WINNT/afsclass/c_svr.cpp
diff -c openafs/src/WINNT/afsclass/c_svr.cpp:1.5 openafs/src/WINNT/afsclass/c_svr.cpp:1.5.4.1
*** openafs/src/WINNT/afsclass/c_svr.cpp:1.5 Sat Nov 5 01:47:44 2005
--- openafs/src/WINNT/afsclass/c_svr.cpp Thu Jul 19 11:56:53 2007
***************
*** 783,790 ****
// the lpServer pointer won't have been freed.)
//
PVOID hCell;
! PVOID hBOS;
! PVOID hVOS;
TCHAR szServer[ cchNAME ];
--- 783,790 ----
// the lpServer pointer won't have been freed.)
//
PVOID hCell;
! PVOID hBOS = NULL;
! PVOID hVOS = NULL;
TCHAR szServer[ cchNAME ];
Index: openafs/src/WINNT/afsd/cm_buf.c
diff -c openafs/src/WINNT/afsd/cm_buf.c:1.31.2.16 openafs/src/WINNT/afsd/cm_buf.c:1.31.2.18
*** openafs/src/WINNT/afsd/cm_buf.c:1.31.2.16 Sun Jun 10 13:00:07 2007
--- openafs/src/WINNT/afsd/cm_buf.c Thu Aug 9 01:33:56 2007
***************
*** 593,598 ****
--- 593,599 ----
long code = 0;
long isdirty = 0;
cm_scache_t * scp = NULL;
+ osi_hyper_t offset;
osi_assert(bp->magic == CM_BUF_MAGIC);
***************
*** 603,611 ****
scp = cm_FindSCache(&bp->fid);
if (scp) {
osi_Log2(buf_logp, "buf_CleanAsyncLocked starts I/O on scp 0x%p buf 0x%p", scp, bp);
! code = (*cm_buf_opsp->Writep)(scp, &bp->offset,
! cm_data.buf_blockSize, 0, bp->userp,
! reqp);
osi_Log3(buf_logp, "buf_CleanAsyncLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
cm_ReleaseSCache(scp);
--- 604,613 ----
scp = cm_FindSCache(&bp->fid);
if (scp) {
osi_Log2(buf_logp, "buf_CleanAsyncLocked starts I/O on scp 0x%p buf 0x%p", scp, bp);
!
! offset = bp->offset;
! LargeIntegerAdd(offset, ConvertLongToLargeInteger(bp->dirty_offset));
! code = (*cm_buf_opsp->Writep)(scp, &offset, bp->dirty_length, 0, bp->userp, reqp);
osi_Log3(buf_logp, "buf_CleanAsyncLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
cm_ReleaseSCache(scp);
***************
*** 623,628 ****
--- 625,632 ----
if (code == CM_ERROR_NOSUCHFILE){
bp->flags &= ~CM_BUF_DIRTY;
bp->flags |= CM_BUF_ERROR;
+ bp->dirty_offset = 0;
+ bp->dirty_length = 0;
bp->error = CM_ERROR_NOSUCHFILE;
bp->dataVersion = -1; /* bad */
bp->dirtyCounter++;
***************
*** 1034,1045 ****
/* load the page; freshly created pages should be idle */
osi_assert(!(bp->flags & (CM_BUF_READING | CM_BUF_WRITING)));
- /* setup offset, event */
- #ifndef DJGPP /* doesn't seem to be used */
- bp->over.Offset = bp->offset.LowPart;
- bp->over.OffsetHigh = bp->offset.HighPart;
- #endif /* !DJGPP */
-
/* start the I/O; may drop lock */
bp->flags |= CM_BUF_READING;
code = (*cm_buf_opsp->Readp)(bp, cm_data.buf_blockSize, &tcount, NULL);
--- 1038,1043 ----
***************
*** 1174,1215 ****
*
* The buffer must be locked before calling this routine.
*/
! void buf_SetDirty(cm_buf_t *bp)
{
osi_assert(bp->magic == CM_BUF_MAGIC);
osi_assert(bp->refCount > 0);
!
if (bp->flags & CM_BUF_DIRTY) {
osi_Log1(buf_logp, "buf_SetDirty 0x%p already dirty", bp);
} else {
osi_Log1(buf_logp, "buf_SetDirty 0x%p", bp);
- }
- /* set dirty bit */
- bp->flags |= CM_BUF_DIRTY;
! /* and turn off EOF flag, since it has associated data now */
! bp->flags &= ~CM_BUF_EOF;
! /* and add to the dirty list.
! * we obtain a hold on the buffer for as long as it remains
! * in the list. buffers are only removed from the list by
! * the buf_IncrSyncer function regardless of when else the
! * dirty flag might be cleared.
! *
! * This should never happen but just in case there is a bug
! * elsewhere, never add to the dirty list if the buffer is
! * already there.
! */
! lock_ObtainWrite(&buf_globalLock);
! if (bp->dirtyp == NULL && cm_data.buf_dirtyListEndp != bp) {
! buf_HoldLocked(bp);
! if (!cm_data.buf_dirtyListp) {
! cm_data.buf_dirtyListp = cm_data.buf_dirtyListEndp = bp;
! } else {
! cm_data.buf_dirtyListEndp->dirtyp = bp;
! cm_data.buf_dirtyListEndp = bp;
! }
! bp->dirtyp = NULL;
}
lock_ReleaseWrite(&buf_globalLock);
}
--- 1172,1233 ----
*
* The buffer must be locked before calling this routine.
*/
! void buf_SetDirty(cm_buf_t *bp, afs_uint32 offset, afs_uint32 length)
{
osi_assert(bp->magic == CM_BUF_MAGIC);
osi_assert(bp->refCount > 0);
!
! lock_ObtainWrite(&buf_globalLock);
if (bp->flags & CM_BUF_DIRTY) {
+
osi_Log1(buf_logp, "buf_SetDirty 0x%p already dirty", bp);
+
+ if (bp->dirty_offset <= offset) {
+ if (bp->dirty_offset + bp->dirty_length >= offset + length) {
+ /* dirty_length remains the same */
+ } else {
+ bp->dirty_length = offset + length - bp->dirty_offset;
+ }
+ } else /* bp->dirty_offset > offset */ {
+ if (bp->dirty_offset + bp->dirty_length >= offset + length) {
+ bp->dirty_length = bp->dirty_offset + bp->dirty_length - offset;
+ } else {
+ bp->dirty_length = length;
+ }
+ bp->dirty_offset = offset;
+ }
} else {
osi_Log1(buf_logp, "buf_SetDirty 0x%p", bp);
! /* set dirty bit */
! bp->flags |= CM_BUF_DIRTY;
! /* and turn off EOF flag, since it has associated data now */
! bp->flags &= ~CM_BUF_EOF;
!
! bp->dirty_offset = offset;
! bp->dirty_length = length;
!
! /* and add to the dirty list.
! * we obtain a hold on the buffer for as long as it remains
! * in the list. buffers are only removed from the list by
! * the buf_IncrSyncer function regardless of when else the
! * dirty flag might be cleared.
! *
! * This should never happen but just in case there is a bug
! * elsewhere, never add to the dirty list if the buffer is
! * already there.
! */
! if (bp->dirtyp == NULL && cm_data.buf_dirtyListEndp != bp) {
! buf_HoldLocked(bp);
! if (!cm_data.buf_dirtyListp) {
! cm_data.buf_dirtyListp = cm_data.buf_dirtyListEndp = bp;
! } else {
! cm_data.buf_dirtyListEndp->dirtyp = bp;
! cm_data.buf_dirtyListEndp = bp;
! }
! bp->dirtyp = NULL;
! }
}
lock_ReleaseWrite(&buf_globalLock);
}
***************
*** 1392,1397 ****
--- 1410,1417 ----
if (LargeIntegerLessThanOrEqualTo(*sizep, bufp->offset)) {
/* truncating the entire page */
bufp->flags &= ~CM_BUF_DIRTY;
+ bufp->dirty_offset = 0;
+ bufp->dirty_length = 0;
bufp->dataVersion = -1; /* known bad */
bufp->dirtyCounter++;
}
***************
*** 1511,1516 ****
--- 1531,1564 ----
return code;
}
+ /* Must be called with scp->mx held */
+ long buf_ForceDataVersion(cm_scache_t * scp, afs_uint32 fromVersion, afs_uint32 toVersion)
+ {
+ cm_buf_t * bp;
+ cm_buf_t * nbp;
+ unsigned int i;
+ int found = 0;
+
+ i = BUF_FILEHASH(&scp->fid);
+
+ lock_ObtainWrite(&buf_globalLock);
+
+ for (bp = cm_data.buf_fileHashTablepp[i]; bp; bp = bp->fileHashp) {
+ if (cm_FidCmp(&bp->fid, &scp->fid) == 0) {
+ if (bp->dataVersion == fromVersion) {
+ bp->dataVersion = toVersion;
+ found = 1;
+ }
+ }
+ }
+ lock_ReleaseWrite(&buf_globalLock);
+
+ if (found)
+ return 0;
+ else
+ return ENOENT;
+ }
+
long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
{
long code = 0;
***************
*** 1702,1709 ****
{
cm_buf_t *bp;
afs_uint32 bcount = 0;
! for (bp = cm_data.buf_allp; bp; bp=bp->allp, bcount++) {
if (!cm_FidCmp(fidp, &bp->fid) && (bp->flags & CM_BUF_DIRTY))
return 1;
}
--- 1750,1760 ----
{
cm_buf_t *bp;
afs_uint32 bcount = 0;
+ afs_uint32 i;
! i = BUF_FILEHASH(fidp);
!
! for (bp = cm_data.buf_fileHashTablepp[i]; bp; bp=bp->allp, bcount++) {
if (!cm_FidCmp(fidp, &bp->fid) && (bp->flags & CM_BUF_DIRTY))
return 1;
}
***************
*** 1723,1728 ****
--- 1774,1781 ----
lock_ObtainMutex(&bp->mx);
bp->cmFlags &= ~CM_BUF_CMSTORING;
bp->flags &= ~CM_BUF_DIRTY;
+ bp->dirty_offset = 0;
+ bp->dirty_length = 0;
bp->flags |= CM_BUF_ERROR;
bp->error = VNOVNODE;
bp->dataVersion = -1; /* bad */
Index: openafs/src/WINNT/afsd/cm_buf.h
diff -c openafs/src/WINNT/afsd/cm_buf.h:1.12.4.4 openafs/src/WINNT/afsd/cm_buf.h:1.12.4.6
*** openafs/src/WINNT/afsd/cm_buf.h:1.12.4.4 Sun Feb 4 22:41:41 2007
--- openafs/src/WINNT/afsd/cm_buf.h Thu Aug 9 01:33:56 2007
***************
*** 72,106 ****
long dirtyCounter; /* bumped at each dirty->clean transition */
osi_hyper_t offset; /* offset */
cm_fid_t fid; /* file ID */
- #ifdef DEBUG
- cm_scache_t *scp; /* for debugging, the scache object belonging to */
- /* the fid at the time of fid assignment. */
- #endif
long flags; /* flags we're using */
char *datap; /* data in this buffer */
unsigned long error; /* last error code, if CM_BUF_ERROR is set */
cm_user_t *userp; /* user who wrote to the buffer last */
- #ifndef DJGPP
- OVERLAPPED over; /* overlapped structure for I/O */
- #endif
/* fields added for the CM; locked by scp->mx */
long dataVersion; /* data version of this page */
long cmFlags; /* flags for cm */
#ifdef DISKCACHE95
cm_diskcache_t *dcp; /* diskcache structure */
#endif /* DISKCACHE95 */
!
! /* syncop state */
! afs_uint32 waitCount; /* number of threads waiting */
! afs_uint32 waitRequests; /* num of thread wait requests */
} cm_buf_t;
/* values for cmFlags */
#define CM_BUF_CMFETCHING 1 /* fetching this buffer */
#define CM_BUF_CMSTORING 2 /* storing this buffer */
#define CM_BUF_CMFULLYFETCHED 4 /* read-while-fetching optimization */
! /* waiting is done based on scp->flags */
/* represents soft reference which is OK to lose on a recycle */
typedef struct cm_softRef {
--- 72,111 ----
long dirtyCounter; /* bumped at each dirty->clean transition */
osi_hyper_t offset; /* offset */
cm_fid_t fid; /* file ID */
long flags; /* flags we're using */
char *datap; /* data in this buffer */
unsigned long error; /* last error code, if CM_BUF_ERROR is set */
cm_user_t *userp; /* user who wrote to the buffer last */
/* fields added for the CM; locked by scp->mx */
long dataVersion; /* data version of this page */
long cmFlags; /* flags for cm */
+
+ /* syncop state */
+ afs_uint32 waitCount; /* number of threads waiting */
+ afs_uint32 waitRequests; /* num of thread wait requests */
+
+ afs_uint32 dirty_offset; /* offset from beginning of buffer containing dirty bytes */
+ afs_uint32 dirty_length; /* number of dirty bytes within the buffer */
+
#ifdef DISKCACHE95
cm_diskcache_t *dcp; /* diskcache structure */
#endif /* DISKCACHE95 */
! #ifdef DEBUG
! cm_scache_t *scp; /* for debugging, the scache object belonging to */
! /* the fid at the time of fid assignment. */
! #else
! void * dummy;
! #endif
} cm_buf_t;
/* values for cmFlags */
#define CM_BUF_CMFETCHING 1 /* fetching this buffer */
#define CM_BUF_CMSTORING 2 /* storing this buffer */
#define CM_BUF_CMFULLYFETCHED 4 /* read-while-fetching optimization */
! #define CM_BUF_CMWRITING 8 /* writing to this buffer */
! /* waiting is done based on scp->flags. Removing bits from cmFlags
! should be followed by waking the scp. */
/* represents soft reference which is OK to lose on a recycle */
typedef struct cm_softRef {
***************
*** 161,167 ****
extern void buf_CleanWait(cm_scache_t *, cm_buf_t *);
! extern void buf_SetDirty(cm_buf_t *);
extern long buf_CleanAndReset(void);
--- 166,172 ----
extern void buf_CleanWait(cm_scache_t *, cm_buf_t *);
! extern void buf_SetDirty(cm_buf_t *, afs_uint32 offset, afs_uint32 length);
extern long buf_CleanAndReset(void);
***************
*** 196,201 ****
--- 201,208 ----
extern long buf_CleanDirtyBuffers(cm_scache_t *scp);
+ extern long buf_ForceDataVersion(cm_scache_t * scp, afs_uint32 fromVersion, afs_uint32 toVersion);
+
/* error codes */
#define CM_BUF_EXISTS 1 /* buffer exists, and shouldn't */
#endif /* _BUF_H__ENV_ */
Index: openafs/src/WINNT/afsd/cm_callback.c
diff -c openafs/src/WINNT/afsd/cm_callback.c:1.41.4.17 openafs/src/WINNT/afsd/cm_callback.c:1.41.4.18
*** openafs/src/WINNT/afsd/cm_callback.c:1.41.4.17 Sat Jul 7 09:38:33 2007
--- openafs/src/WINNT/afsd/cm_callback.c Thu Aug 2 16:46:12 2007
***************
*** 1756,1767 ****
return code;
}
/* called periodically by cm_daemon to shut down use of expired callbacks */
void cm_CheckCBExpiration(void)
{
int i;
cm_scache_t *scp;
! time_t now;
osi_Log0(afsd_logp, "CheckCBExpiration");
--- 1756,1807 ----
return code;
}
+
+ /* called with cm_scacheLock held */
+ long cm_CBServersUp(cm_scache_t *scp, time_t * downTime)
+ {
+ cm_vol_state_t *statep;
+ cm_volume_t * volp = scp->volp;
+ afs_uint32 volID = scp->fid.volume;
+ cm_serverRef_t *tsrp;
+ int found;
+
+ *downTime = 0;
+
+ if (scp->cbServerp == NULL)
+ return 1;
+
+ if (volp->rw.ID == volID) {
+ statep = &volp->rw;
+ } else if (volp->ro.ID == volID) {
+ statep = &volp->ro;
+ } else if (volp->bk.ID == volID) {
+ statep = &volp->bk;
+ }
+
+ if (statep->state == vl_online)
+ return 1;
+
+ for (found = 0,tsrp = statep->serversp; tsrp; tsrp=tsrp->next) {
+ if (tsrp->server == scp->cbServerp)
+ found = 1;
+ if (tsrp->server->downTime > *downTime)
+ *downTime = tsrp->server->downTime;
+ }
+
+ /* if the cbServerp does not match the current volume server list
+ * we report the callback server as up so the callback can be
+ * expired.
+ */
+ return(found ? 0 : 1);
+ }
+
/* called periodically by cm_daemon to shut down use of expired callbacks */
void cm_CheckCBExpiration(void)
{
int i;
cm_scache_t *scp;
! time_t now, downTime = 0;
osi_Log0(afsd_logp, "CheckCBExpiration");
***************
*** 1769,1786 ****
lock_ObtainWrite(&cm_scacheLock);
for (i=0; inextp) {
! cm_HoldSCacheNoLock(scp);
! if (scp->cbExpires > 0 && (scp->cbServerp == NULL || now > scp->cbExpires)) {
lock_ReleaseWrite(&cm_scacheLock);
! osi_Log4(afsd_logp, "Callback Expiration Discarding SCache scp 0x%p vol %u vn %u uniq %u",
scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
lock_ObtainMutex(&scp->mx);
cm_DiscardSCache(scp);
lock_ReleaseMutex(&scp->mx);
cm_CallbackNotifyChange(scp);
lock_ObtainWrite(&cm_scacheLock);
}
- cm_ReleaseSCacheNoLock(scp);
}
}
lock_ReleaseWrite(&cm_scacheLock);
--- 1809,1831 ----
lock_ObtainWrite(&cm_scacheLock);
for (i=0; inextp) {
!
! if (scp->cbServerp && scp->cbExpires > 0 && now > scp->cbExpires &&
! (cm_CBServersUp(scp, &downTime) || downTime == 0 || downTime >= scp->cbExpires))
! {
! cm_HoldSCacheNoLock(scp);
lock_ReleaseWrite(&cm_scacheLock);
!
! osi_Log4(afsd_logp, "Callback Expiration Discarding SCache scp 0x%p vol %u vn %u uniq %u",
scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
lock_ObtainMutex(&scp->mx);
cm_DiscardSCache(scp);
lock_ReleaseMutex(&scp->mx);
cm_CallbackNotifyChange(scp);
+
+ cm_ReleaseSCacheNoLock(scp);
lock_ObtainWrite(&cm_scacheLock);
}
}
}
lock_ReleaseWrite(&cm_scacheLock);
Index: openafs/src/WINNT/afsd/cm_config.h
diff -c openafs/src/WINNT/afsd/cm_config.h:1.8 openafs/src/WINNT/afsd/cm_config.h:1.8.6.1
*** openafs/src/WINNT/afsd/cm_config.h:1.8 Fri Mar 11 00:33:22 2005
--- openafs/src/WINNT/afsd/cm_config.h Thu Aug 9 01:33:56 2007
***************
*** 13,19 ****
#define CM_CONFIGDEFAULT_CACHESIZE 98304
#define CM_CONFIGDEFAULT_BLOCKSIZE 4096
#define CM_CONFIGDEFAULT_STATS 10000
! #define CM_CONFIGDEFAULT_CHUNKSIZE 17
#define CM_CONFIGDEFAULT_DAEMONS 2
#define CM_CONFIGDEFAULT_SVTHREADS 25
#define CM_CONFIGDEFAULT_TRACEBUFSIZE 5000
--- 13,19 ----
#define CM_CONFIGDEFAULT_CACHESIZE 98304
#define CM_CONFIGDEFAULT_BLOCKSIZE 4096
#define CM_CONFIGDEFAULT_STATS 10000
! #define CM_CONFIGDEFAULT_CHUNKSIZE 20
#define CM_CONFIGDEFAULT_DAEMONS 2
#define CM_CONFIGDEFAULT_SVTHREADS 25
#define CM_CONFIGDEFAULT_TRACEBUFSIZE 5000
Index: openafs/src/WINNT/afsd/cm_conn.c
diff -c openafs/src/WINNT/afsd/cm_conn.c:1.49.2.19 openafs/src/WINNT/afsd/cm_conn.c:1.49.2.21
*** openafs/src/WINNT/afsd/cm_conn.c:1.49.2.19 Mon Jun 25 00:59:40 2007
--- openafs/src/WINNT/afsd/cm_conn.c Tue Aug 7 00:00:49 2007
***************
*** 551,559 ****
else if (errorCode >= -64 && errorCode < 0) {
/* mark server as down */
lock_ObtainMutex(&serverp->mx);
! if (reqp->flags & CM_REQ_NEW_CONN_FORCED)
serverp->flags |= CM_SERVERFLAG_DOWN;
! else {
reqp->flags |= CM_REQ_NEW_CONN_FORCED;
forcing_new = 1;
}
--- 551,560 ----
else if (errorCode >= -64 && errorCode < 0) {
/* mark server as down */
lock_ObtainMutex(&serverp->mx);
! if (reqp->flags & CM_REQ_NEW_CONN_FORCED) {
serverp->flags |= CM_SERVERFLAG_DOWN;
! serverp->downTime = osi_Time();
! } else {
reqp->flags |= CM_REQ_NEW_CONN_FORCED;
forcing_new = 1;
}
***************
*** 708,720 ****
struct timeval now;
#endif /* DJGPP */
if (serversp == NULL) {
osi_Log1(afsd_logp, "cm_ConnByMServers returning 0x%x", CM_ERROR_ALLDOWN);
return CM_ERROR_ALLDOWN;
}
- *connpp = NULL;
-
#ifndef DJGPP
timeUsed = (GetTickCount() - reqp->startTime) / 1000;
#else
--- 709,721 ----
struct timeval now;
#endif /* DJGPP */
+ *connpp = NULL;
+
if (serversp == NULL) {
osi_Log1(afsd_logp, "cm_ConnByMServers returning 0x%x", CM_ERROR_ALLDOWN);
return CM_ERROR_ALLDOWN;
}
#ifndef DJGPP
timeUsed = (GetTickCount() - reqp->startTime) / 1000;
#else
***************
*** 867,872 ****
--- 868,875 ----
cm_conn_t *tcp;
cm_ucell_t *ucellp;
+ *connpp = NULL;
+
lock_ObtainMutex(&userp->mx);
lock_ObtainWrite(&cm_connLock);
for (tcp = serverp->connsp; tcp; tcp=tcp->nextp) {
Index: openafs/src/WINNT/afsd/cm_dcache.c
diff -c openafs/src/WINNT/afsd/cm_dcache.c:1.30.2.15 openafs/src/WINNT/afsd/cm_dcache.c:1.30.2.16
*** openafs/src/WINNT/afsd/cm_dcache.c:1.30.2.15 Sun Jun 10 13:00:07 2007
--- openafs/src/WINNT/afsd/cm_dcache.c Thu Aug 9 01:33:56 2007
***************
*** 1254,1261 ****
}
if (failed)
bufp->flags &= ~CM_BUF_WRITING;
! else
bufp->flags &= ~(CM_BUF_WRITING | CM_BUF_DIRTY);
}
lock_ReleaseMutex(&scp->mx);
--- 1254,1263 ----
}
if (failed)
bufp->flags &= ~CM_BUF_WRITING;
! else {
bufp->flags &= ~(CM_BUF_WRITING | CM_BUF_DIRTY);
+ bufp->dirty_offset = bufp->dirty_length = 0;
+ }
}
lock_ReleaseMutex(&scp->mx);
Index: openafs/src/WINNT/afsd/cm_dir.c
diff -c openafs/src/WINNT/afsd/cm_dir.c:1.4.4.1 openafs/src/WINNT/afsd/cm_dir.c:1.4.4.2
*** openafs/src/WINNT/afsd/cm_dir.c:1.4.4.1 Sat Jun 24 16:41:54 2006
--- openafs/src/WINNT/afsd/cm_dir.c Thu Aug 2 16:53:51 2007
***************
*** 20,33 ****
#include
/* compute how many 32 byte entries an AFS 3 dir requires for storing
* the specified name.
*/
! long cm_NameEntries(char *namep, long *lenp)
{
long i;
! i = (long)strlen(namep);
if (lenp) *lenp = i;
! return 1+((i+16)>>5);
}
--- 20,1437 ----
#include
+ afs_int32 DErrno;
+
+ /* Local static prototypes */
+ static long
+ cm_DirGetBlob(cm_dirOp_t * op,
+ unsigned int blobno, cm_buf_t ** bufferpp, cm_dirEntry_t ** blobpp);
+
+ static long
+ cm_DirFindItem(cm_dirOp_t * op,
+ char *ename,
+ cm_buf_t ** itembufpp, cm_dirEntry_t ** itempp,
+ cm_buf_t ** prevbufpp, unsigned short **previtempp);
+
+ static long
+ cm_DirOpAddBuffer(cm_dirOp_t * op, cm_buf_t * buffer);
+
+ /* flags for cm_DirOpDelBuffer */
+ #define DIROP_MODIFIED 1
+ #define DIROP_SCPLOCKED 2
+
+ static int
+ cm_DirOpDelBuffer(cm_dirOp_t * op, cm_buf_t * buffer, int flags);
+
+ static long
+ cm_DirCheckStatus(cm_dirOp_t * op);
+
+ static long
+ cm_DirReleasePage(cm_dirOp_t * op, cm_buf_t ** bufferpp, int modified);
+
+ static long
+ cm_DirGetPage(cm_dirOp_t * op,
+ long index, cm_buf_t ** bufferpp, void ** datapp);
+
+ static long
+ cm_DirFindBlobs(cm_dirOp_t * op, int nblobs);
+
+ static long
+ cm_DirAddPage(cm_dirOp_t * op, int pageno);
+
+ static long
+ cm_DirFreeBlobs(cm_dirOp_t * op, int firstblob, int nblobs);
+
+
/* compute how many 32 byte entries an AFS 3 dir requires for storing
* the specified name.
*/
! long
! cm_NameEntries(char *namep, long *lenp)
{
long i;
! i = (long)strlen(namep) + 1;
if (lenp) *lenp = i;
! return 1 + ((i+15) >> 5);
! }
!
! /* Create an entry in a file. Dir is a file representation, while
! entry is a string name.
!
! On entry:
! op->scp->mx is locked
!
! On exit:
! op->scp->mx is locked
!
! None of the directory buffers for op->scp should be locked by the
! calling thread.
! */
! long
! cm_DirCreateEntry(cm_dirOp_t * op, char *entry, cm_fid_t * cfid)
! {
! int blobs, firstelt;
! int i;
!
! cm_dirEntry_t *ep = NULL;
! cm_buf_t *entrybuf = NULL;
!
! unsigned short *pp = NULL;
! cm_buf_t *prevptrbuf = NULL;
!
! cm_dirHeader_t *dhp = NULL;
! cm_buf_t *dhpbuf = NULL;
!
! long code = 0;
!
! /* check name quality */
! if (*entry == 0)
! return EINVAL;
!
! osi_Log4(afsd_logp, "cm_DirCreateEntry for op 0x%p, name [%s] and fid[%d,%d]",
! op, osi_LogSaveString(afsd_logp, entry), cfid->vnode, cfid->unique);
!
! /* First check if file already exists. */
! code = cm_DirFindItem(op,
! entry,
! &entrybuf, &ep,
! &prevptrbuf, &pp);
! if (code == 0) {
! cm_DirReleasePage(op, &entrybuf, FALSE);
! cm_DirReleasePage(op, &prevptrbuf, FALSE);
! return EEXIST;
! }
!
! blobs = cm_NameEntries(entry, NULL); /* number of entries required */
! firstelt = cm_DirFindBlobs(op, blobs);
! if (firstelt < 0) {
! osi_Log0(afsd_logp, "cm_DirCreateEntry returning EFBIG");
! return EFBIG; /* directory is full */
! }
!
! /* First, we fill in the directory entry. */
! code = cm_DirGetBlob(op, firstelt, &entrybuf, &ep);
! if (code != 0)
! return EIO;
!
! ep->flag = CM_DIR_FFIRST;
! ep->fid.vnode = htonl(cfid->vnode);
! ep->fid.unique = htonl(cfid->unique);
! strcpy(ep->name, entry);
!
! /* Now we just have to thread it on the hash table list. */
! code = cm_DirGetPage(op, 0, &dhpbuf, &dhp);
! if (code != 0) {
! cm_DirReleasePage(op, &entrybuf, TRUE);
! return EIO;
! }
!
! i = cm_DirHash(entry);
!
! ep->next = dhp->hashTable[i];
! dhp->hashTable[i] = htons(firstelt);
!
! cm_DirReleasePage(op, &dhpbuf, TRUE);
! cm_DirReleasePage(op, &entrybuf, TRUE);
!
! osi_Log0(afsd_logp, "cm_DirCreateEntry returning success");
!
! return 0;
! }
!
! /* Return the length of a directory in pages
!
! On entry:
! op->scp->mx is locked
!
! On exit:
! op->scp->mx is locked
!
! The first directory page for op->scp should not be locked by the
! calling thread.
! */
! int
! cm_DirLength(cm_dirOp_t * op)
! {
! int i, ctr;
! cm_dirHeader_t *dhp = NULL;
! cm_buf_t *dhpbuf = NULL;
!
! long code;
!
! code = cm_DirGetPage(op, 0, &dhpbuf, &dhp);
! if (code != 0)
! return 0;
!
! if (dhp->header.pgcount != 0)
! ctr = ntohs(dhp->header.pgcount);
! else {
! /* old style, count the pages */
! ctr = 0;
! for (i = 0; i < CM_DIR_MAXPAGES; i++)
! if (dhp->alloMap[i] != CM_DIR_EPP)
! ctr++;
! }
! cm_DirReleasePage(op, &dhpbuf, FALSE);
! return ctr * CM_DIR_PAGESIZE;
! }
!
! /* Delete a directory entry.
!
! On entry:
! op->scp->mx is locked
!
! On exit:
! op->scp->mx is locked
!
! None of the directory buffers for op->scp should be locked by the
! calling thread.
! */
! int
! cm_DirDeleteEntry(cm_dirOp_t * op, char *entry)
! {
! /* Delete an entry from a directory, including update of all free
! entry descriptors. */
!
! int nitems, index;
! cm_dirEntry_t *firstitem = NULL;
! cm_buf_t *itembuf = NULL;
! unsigned short *previtem = NULL;
! cm_buf_t *pibuf = NULL;
! osi_hyper_t thyper;
! unsigned long junk;
!
! long code;
!
! osi_Log2(afsd_logp, "cm_DirDeleteEntry for op 0x%p, entry [%s]",
! op, osi_LogSaveString(afsd_logp, entry));
!
! code = cm_DirFindItem(op, entry,
! &itembuf, &firstitem,
! &pibuf, &previtem);
! if (code != 0) {
! osi_Log0(afsd_logp, "cm_DirDeleteEntry returning ENOENT");
! return ENOENT;
! }
!
! *previtem = firstitem->next;
! cm_DirReleasePage(op, &pibuf, TRUE);
!
! thyper = itembuf->offset;
! thyper = LargeIntegerAdd(thyper,
! ConvertLongToLargeInteger(((char *) firstitem) - itembuf->datap));
! thyper = ExtendedLargeIntegerDivide(thyper, 32, &junk);
!
! index = thyper.LowPart;
! osi_assert(thyper.HighPart == 0);
!
! nitems = cm_NameEntries(firstitem->name, NULL);
! cm_DirReleasePage(op, &itembuf, FALSE);
!
! cm_DirFreeBlobs(op, index, nitems);
!
! osi_Log0(afsd_logp, "cm_DirDeleteEntry returning success");
!
! return 0;
! }
!
! /* Find a bunch of contiguous entries; at least nblobs in a row.
!
! Called with op->scp->mx */
! static long
! cm_DirFindBlobs(cm_dirOp_t * op, int nblobs)
! {
! int i, j, k;
! int failed = 0;
!
! cm_dirHeader_t *dhp = NULL;
! cm_buf_t *dhpbuf = NULL;
! int dhpModified = FALSE;
!
! cm_pageHeader_t *pp = NULL;
! cm_buf_t *pagebuf = NULL;
! int pageModified = FALSE;
!
! int pgcount;
!
! long code;
!
! osi_Log2(afsd_logp, "cm_DirFindBlobs for op 0x%p, nblobs = %d",
! op, nblobs);
!
! code = cm_DirGetPage(op, 0, &dhpbuf, (void **) &dhp);
! if (code)
! return -1;
!
! for (i = 0; i < CM_DIR_BIGMAXPAGES; i++) {
! if (i >= CM_DIR_MAXPAGES || dhp->alloMap[i] >= nblobs) {
! /* if page could contain enough entries */
! /* If there are CM_DIR_EPP free entries, then the page is
! not even allocated. */
! if (i >= CM_DIR_MAXPAGES) {
!
! /* this pages exists past the end of the old-style dir */
! pgcount = ntohs(dhp->header.pgcount);
! if (pgcount == 0) {
! pgcount = CM_DIR_MAXPAGES;
! dhp->header.pgcount = htons(pgcount);
! dhpModified = TRUE;
! }
!
! if (i > pgcount - 1) {
! /* this page is bigger than last allocated page */
! cm_DirAddPage(op, i);
! dhp->header.pgcount = htons(i + 1);
! dhpModified = TRUE;
! }
! } else if (dhp->alloMap[i] == CM_DIR_EPP) {
! /* Add the page to the directory. */
! cm_DirAddPage(op, i);
! dhp->alloMap[i] = CM_DIR_EPP - 1;
! dhp->header.pgcount = htons(i + 1);
! dhpModified = TRUE;
! }
!
! code = cm_DirGetPage(op, i, &pagebuf, &pp);
! if (code) {
! cm_DirReleasePage(op, &dhpbuf, dhpModified);
! break;
! }
!
! for (j = 0; j <= CM_DIR_EPP - nblobs; j++) {
! failed = 0;
! for (k = 0; k < nblobs; k++)
! if ((pp->freeBitmap[(j + k) >> 3] >> ((j + k) & 7)) & 1) {
! failed = 1;
! break;
! }
! if (!failed)
! break;
! failed = 1;
! }
!
! if (!failed) {
! /* Here we have the first index in j. We update the allocation maps
! * and free up any resources we've got allocated. */
! if (i < CM_DIR_MAXPAGES) {
! dhp->alloMap[i] -= nblobs;
! dhpModified = TRUE;
! }
!
! cm_DirReleasePage(op, &dhpbuf, dhpModified);
!
! for (k = 0; k < nblobs; k++)
! pp->freeBitmap[(j + k) >> 3] |= 1 << ((j + k) & 7);
!
! cm_DirReleasePage(op, &pagebuf, TRUE);
!
! osi_Log0(afsd_logp, "cm_DirFindBlobs returning success");
!
! return j + i * CM_DIR_EPP;
! }
! cm_DirReleasePage(op, &pagebuf, pageModified);
! }
! }
!
! /* If we make it here, the directory is full. */
! osi_Log0(afsd_logp, "cm_DirFindBlobs directory is full");
! cm_DirReleasePage(op, &dhpbuf, dhpModified);
! return -1;
! }
!
! /* Add a page to a directory.
!
! Called with op->scp->mx
! */
! static long
! cm_DirAddPage(cm_dirOp_t * op, int pageno)
! {
! int i;
! cm_pageHeader_t *pp = NULL;
! cm_buf_t *pagebuf = NULL;
! long code = 0;
!
! osi_Log2(afsd_logp, "cm_DirAddPage for op 0x%p, pageno=%d", op, pageno);
!
! code = cm_DirGetPage(op, pageno, &pagebuf, (void **) &pp);
! if (code != 0)
! return code;
!
! pp->tag = htons(1234);
! if (pageno > 0)
! pp->pgcount = 0;
! pp->freeCount = CM_DIR_EPP - 1; /* The first dude is already allocated */
! pp->freeBitmap[0] = 0x01;
! for (i = 1; i < CM_DIR_EPP / 8; i++) /* It's a constant */
! pp->freeBitmap[i] = 0;
!
! cm_DirReleasePage(op, &pagebuf, TRUE);
!
! osi_Log0(afsd_logp, "cm_DirAddPage returning success");
!
! return code;
! }
!
! /* Free a whole bunch of directory entries.
!
! Called with op->scp->mx
! */
! static long
! cm_DirFreeBlobs(cm_dirOp_t * op, int firstblob, int nblobs)
! {
! int i;
! int page;
!
! cm_dirHeader_t *dhp = NULL;
! cm_buf_t *dhpbuf = NULL;
! int dhpmodified = FALSE;
!
! cm_pageHeader_t *pp = NULL;
! cm_buf_t *pagebuf = NULL;
! long code = 0;
!
! osi_Log3(afsd_logp, "cm_DirFreeBlobs for op 0x%p, firstblob=%d, nblobs=%d",
! op, firstblob, nblobs);
!
! page = firstblob / CM_DIR_EPP;
! firstblob -= CM_DIR_EPP * page; /* convert to page-relative entry */
!
! code = cm_DirGetPage(op, 0, &dhpbuf, &dhp);
! if (code)
! return code;
!
! if (page < CM_DIR_MAXPAGES) {
! dhp->alloMap[page] += nblobs;
! dhpmodified = TRUE;
! }
!
! cm_DirReleasePage(op, &dhpbuf, dhpmodified);
!
! code = cm_DirGetPage(op, page, &pagebuf, &pp);
! if (code == 0) {
! for (i = 0; i < nblobs; i++)
! pp->freeBitmap[(firstblob + i) >> 3] &=
! ~(1 << ((firstblob + i) & 7));
! cm_DirReleasePage(op, &pagebuf, TRUE);
! }
!
! osi_Log1(afsd_logp, "cm_DirFreeBlobs returning code 0x%x", code);
!
! return code;
! }
!
! /*
! * Format an empty directory properly. Note that the first 13 entries in a
! * directory header page are allocated, 1 to the page header, 4 to the
! * allocation map and 8 to the hash table.
! *
! * Called with op->scp->mx
! */
! int
! cm_DirMakeDir(cm_dirOp_t * op, cm_fid_t * me, cm_fid_t * parent)
! {
! int i;
! cm_dirHeader_t *dhp = NULL;
! cm_buf_t *dhpbuf = NULL;
!
! long code;
!
! osi_Log3(afsd_logp, "cm_DirMakeDir for op 0x%p, directory fid[%d, %d]",
! op, me->vnode, me->unique);
! osi_Log2(afsd_logp, " parent[%d, %d]",
! parent->vnode, parent->unique);
!
! code = cm_DirGetPage(op, 0, &dhpbuf, &dhp);
! if (code)
! return 1;
!
! dhp->header.pgcount = htons(1);
! dhp->header.tag = htons(1234);
! dhp->header.freeCount = (CM_DIR_EPP - CM_DIR_DHE - 1);
! dhp->header.freeBitmap[0] = 0xff;
! dhp->header.freeBitmap[1] = 0x1f;
! for (i = 2; i < CM_DIR_EPP / 8; i++)
! dhp->header.freeBitmap[i] = 0;
! dhp->alloMap[0] = (CM_DIR_EPP - CM_DIR_DHE - 1);
! for (i = 1; i < CM_DIR_MAXPAGES; i++)
! dhp->alloMap[i] = CM_DIR_EPP;
! for (i = 0; i < CM_DIR_NHASHENT; i++)
! dhp->hashTable[i] = 0;
!
! cm_DirReleasePage(op, &dhpbuf, TRUE);
!
! cm_DirCreateEntry(op, ".", me);
! cm_DirCreateEntry(op, "..", parent); /* Virtue is its own .. */
!
! osi_Log0(afsd_logp, "cm_DirMakeDir returning success");
!
! return 0;
! }
!
! /* Look up a file name in directory.
!
! On entry:
! op->scp->mx is locked
!
! On exit:
! op->scp->mx is locked
!
! None of the directory buffers for op->scp should be locked by the
! calling thread.
! */
! int
! cm_DirLookup(cm_dirOp_t * op, char *entry, cm_fid_t * cfid)
! {
! cm_dirEntry_t *firstitem = NULL;
! cm_buf_t *itembuf = NULL;
! unsigned short *previtem = NULL;
! cm_buf_t *pibuf = NULL;
!
! long code;
!
! osi_Log2(afsd_logp, "cm_DirLookup for op 0x%p, entry[%s]",
! op, osi_LogSaveString(afsd_logp, entry));
!
! code = cm_DirFindItem(op, entry,
! &itembuf, &firstitem,
! &pibuf, &previtem);
! if (code != 0) {
! return ENOENT;
! }
!
! cm_DirReleasePage(op, &pibuf, FALSE);
!
! cfid->cell = op->scp->fid.cell;
! cfid->volume = op->scp->fid.volume;
! cfid->vnode = ntohl(firstitem->fid.vnode);
! cfid->unique = ntohl(firstitem->fid.unique);
!
! cm_DirReleasePage(op, &itembuf, FALSE);
!
! osi_Log2(afsd_logp, "cm_DirLookup returning fid[%d,%d]",
! cfid->vnode, cfid->unique);
!
! return 0;
! }
!
! /* Look up a file name in directory.
!
! On entry:
! op->scp->mx is locked
!
! On exit:
! op->scp->mx is locked
!
! None of the directory buffers for op->scp should be locked by the
! calling thread.
! */
! int
! cm_DirLookupOffset(cm_dirOp_t * op, char *entry, cm_fid_t *cfid, osi_hyper_t *offsetp)
! {
! cm_dirEntry_t *firstitem = NULL;
! cm_buf_t *itembuf = NULL;
! unsigned short *previtem = NULL;
! cm_buf_t *pibuf = NULL;
!
! long code;
!
! osi_Log2(afsd_logp, "cm_DirLookupOffset for op 0x%p, entry[%s]",
! op, osi_LogSaveString(afsd_logp, entry));
!
! code = cm_DirFindItem(op, entry,
! &itembuf, &firstitem,
! &pibuf, &previtem);
! if (code != 0)
! return ENOENT;
!
! cm_DirReleasePage(op, &pibuf, FALSE);
!
! cfid->cell = op->scp->fid.cell;
! cfid->volume = op->scp->fid.volume;
! cfid->vnode = ntohl(firstitem->fid.vnode);
! cfid->unique = ntohl(firstitem->fid.unique);
! if (offsetp) {
! osi_hyper_t thyper;
!
! thyper = itembuf->offset;
! thyper = LargeIntegerAdd(thyper,
! ConvertLongToLargeInteger(((char *) firstitem) - itembuf->datap));
!
! *offsetp = thyper;
! }
!
! cm_DirReleasePage(op, &itembuf, FALSE);
!
! osi_Log2(afsd_logp, "cm_DirLookupOffset returning fid[%d,%d]",
! cfid->vnode, cfid->unique);
! if (offsetp) {
! osi_Log2(afsd_logp, " offset [%x:%x]",
! offsetp->HighPart, offsetp->LowPart);
! }
!
! return 0;
! }
!
! /* Apply a function to every directory entry in a directory.
!
! On entry:
! op->scp->mx is locked
!
! On exit:
! op->scp->mx is locked
!
! None of the directory buffers for op->scp should be locked by the
! calling thread.
!
! The hook function cannot modify or lock any directory buffers.
! */
! int
! cm_DirApply(cm_dirOp_t * op, int (*hookproc) (void *, char *, long, long), void *hook)
! {
! /* Enumerate the contents of a directory. */
! int i;
! int num;
!
! cm_dirHeader_t *dhp = NULL;
! cm_buf_t *dhpbuf = NULL;
!
! cm_dirEntry_t *ep = NULL;
! cm_buf_t *epbuf = NULL;
!
! long code = 0;
!
! code = cm_DirGetPage(op, 0, &dhpbuf, &dhp);
! if (code != 0)
! return EIO;
!
! for (i = 0; i < CM_DIR_NHASHENT; i++) {
! /* For each hash chain, enumerate everyone on the list. */
! num = ntohs(dhp->hashTable[i]);
! while (num != 0) {
! /* Walk down the hash table list. */
! code = cm_DirGetBlob(op, num, &epbuf, &ep);
! if (code != 0) {
! cm_DirReleasePage(op, &dhpbuf, FALSE);
! return code;
! }
!
! num = ntohs(ep->next);
! (*hookproc) (hook, ep->name, ntohl(ep->fid.vnode),
! ntohl(ep->fid.unique));
!
! cm_DirReleasePage(op, &epbuf, FALSE);
! }
! }
! cm_DirReleasePage(op, &dhpbuf, FALSE);
!
! return 0;
! }
!
! /* Check if a directory is empty
!
! On entry:
! op->scp->mx is locked
!
! On exit:
! op->scp->mx is locked
!
! None of the directory buffers for op->scp should be locked by the
! calling thread.
! */
! int
! cm_DirIsEmpty(cm_dirOp_t * op)
! {
! /* Enumerate the contents of a directory. */
! int i;
! int num;
!
! cm_dirHeader_t *dhp = NULL;
! cm_buf_t *dhpbuf = NULL;
!
! cm_dirEntry_t *ep = NULL;
! cm_buf_t *epbuf = NULL;
!
! long code = 0;
!
! code = cm_DirGetPage(op, 0, &dhpbuf, &dhp);
! if (code != 0)
! return 0;
!
! for (i = 0; i < CM_DIR_NHASHENT; i++) {
! /* For each hash chain, enumerate everyone on the list. */
! num = ntohs(dhp->hashTable[i]);
!
! while (num != 0) {
! /* Walk down the hash table list. */
! code = cm_DirGetBlob(op, num, &epbuf, &ep);
! if (code != 0)
! break;
!
! if (strcmp(ep->name, "..") && strcmp(ep->name, ".")) {
! cm_DirReleasePage(op, &epbuf, FALSE);
! cm_DirReleasePage(op, &dhpbuf, FALSE);
! return 1;
! }
! num = ntohs(ep->next);
! cm_DirReleasePage(op, &epbuf, FALSE);
! }
! }
! cm_DirReleasePage(op, &dhpbuf, FALSE);
! return 0;
! }
!
! /* Return a pointer to an entry, given its number.
!
! On entry:
! scp->mx locked
! if *bufferpp != NULL, then *bufferpp->mx is locked
!
! During:
! scp->mx may be unlocked
! *bufferpp may be released
!
! On exit:
! scp->mx locked
! if *bufferpp != NULL, then *bufferpp->mx is locked
!
! *bufferpp should be released via cm_DirReleasePage() or any other
! *call that releases a directory buffer.
! */
! static long
! cm_DirGetBlob(cm_dirOp_t * op,
! unsigned int blobno, cm_buf_t ** bufferpp, cm_dirEntry_t ** blobpp)
! {
! unsigned char * ep;
! long code = 0;
!
! osi_Log2(afsd_logp, "cm_DirGetBlob for op 0x%p, blobno=%d",
! op, blobno);
!
! code = cm_DirGetPage(op, blobno >> CM_DIR_LEPP,
! bufferpp, (void **) &ep);
! if (code != 0)
! return code;
!
! *blobpp = (cm_dirEntry_t *) (ep + 32 * (blobno & (CM_DIR_EPP - 1)));
!
! return code;
}
+
+ int
+ cm_DirHash(char *string)
+ {
+ /* Hash a string to a number between 0 and NHASHENT. */
+ register unsigned char tc;
+ register int hval;
+ register int tval;
+ hval = 0;
+ while ((tc = (*string++))) {
+ hval *= 173;
+ hval += tc;
+ }
+ tval = hval & (CM_DIR_NHASHENT - 1);
+ if (tval == 0)
+ return tval;
+ else if (hval < 0)
+ tval = CM_DIR_NHASHENT - tval;
+ return tval;
+ }
+
+ /* Find a directory entry, given its name. This entry returns a
+ * pointer to a locked buffer, and a pointer to a locked buffer (in
+ * previtem) referencing the found item (to aid the delete code). If
+ * no entry is found, however, no items are left locked, and a null
+ * pointer is returned instead.
+ *
+ * On entry:
+ * scp->mx locked
+ *
+ * On exit:
+ * scp->mx locked
+ */
+ static long
+ cm_DirFindItem(cm_dirOp_t * op,
+ char *ename,
+ cm_buf_t ** itembufpp, cm_dirEntry_t ** itempp,
+ cm_buf_t ** prevbufpp, unsigned short **previtempp)
+ {
+ int i;
+ cm_dirHeader_t *dhp = NULL;
+ unsigned short *lp = NULL;
+ cm_dirEntry_t *tp = NULL;
+ cm_buf_t *hashbufp = NULL;
+ cm_buf_t *itembufp = NULL;
+ long code = 0;
+
+ osi_Log2(afsd_logp, "cm_DirFindItem for op 0x%p, entry[%s]",
+ op, osi_LogSaveString(afsd_logp, ename));
+
+ i = cm_DirHash(ename);
+
+ if (op->scp->fileType != CM_SCACHETYPE_DIRECTORY) {
+ osi_Log0(afsd_logp, "cm_DirFindItem: The scp is not a directory");
+ return CM_ERROR_INVAL;
+ }
+
+ code = cm_DirGetPage(op, 0, &hashbufp, (void **) &dhp);
+ if (code != 0) {
+ return code;
+ }
+
+ if (dhp->hashTable[i] == 0) {
+ /* no such entry */
+ osi_Log1(afsd_logp, "cm_DirFindItem: Hash bucket %d is empty", i);
+ cm_DirReleasePage(op, &hashbufp, FALSE);
+ return ENOENT;
+ }
+
+ code = cm_DirGetBlob(op,
+ (u_short) ntohs(dhp->hashTable[i]),
+ &itembufp, &tp);
+ if (code != 0) {
+ cm_DirReleasePage(op, &hashbufp, FALSE);
+ return code;
+ }
+
+ lp = &(dhp->hashTable[i]);
+
+ /* loop invariant:
+
+ lp : pointer to blob number of entry we are looking at
+ hashbufp : buffer containing lp
+ tp : pointer to entry we are looking at
+ itembufp : buffer containing tp
+ */
+ while (1) {
+ /* Look at each hash conflict entry. */
+ if (!strcmp(ename, tp->name)) {
+ osi_Log0(afsd_logp, "cm_DirFindItem: returning success");
+ /* Found our entry. */
+ *previtempp = lp;
+ *prevbufpp = hashbufp;
+ *itempp = tp;
+ *itembufpp = itembufp;
+ return 0;
+ }
+
+ lp = &(tp->next);
+ cm_DirReleasePage(op, &hashbufp, FALSE);
+ hashbufp = itembufp;
+
+ itembufp = NULL;
+ tp = NULL;
+
+ if (*lp == 0) {
+ /* The end of the line */
+ osi_Log0(afsd_logp, "cm_DirFindItem: returning ENOENT");
+ cm_DirReleasePage(op, &hashbufp, FALSE);
+ return ENOENT;
+ }
+
+ code = cm_DirGetBlob(op,
+ (u_short) ntohs(*lp),
+ &itembufp, &tp);
+
+ if (code != 0) {
+ cm_DirReleasePage(op, &hashbufp, FALSE);
+ return code;
+ }
+ }
+ }
+
+ /* Begin a sequence of directory operations. scp->mx should be
+ locked.
+ */
+ long
+ cm_BeginDirOp(cm_scache_t * scp, cm_user_t * userp, cm_req_t * reqp,
+ cm_dirOp_t * op)
+ {
+ long code;
+ int i;
+
+ osi_Log3(afsd_logp, "Beginning dirOp[0x%p] for scp[0x%p], userp[0x%p]",
+ op, scp, userp);
+
+ memset(op, 0, sizeof(*op));
+
+ cm_HoldSCache(scp);
+ op->scp = scp;
+ cm_HoldUser(userp);
+ op->userp = userp;
+ cm_InitReq(&op->req);
+
+ op->dirtyBufCount = 0;
+ op->nBuffers = 0;
+
+ for (i=0; i < CM_DIROP_MAXBUFFERS; i++) {
+ op->buffers[i].flags = 0;
+ }
+
+ code = cm_DirCheckStatus(op);
+
+ if (code == 0) {
+ op->length = scp->length;
+ op->newLength = op->length;
+ op->dataVersion = scp->dataVersion;
+ op->newDataVersion = op->dataVersion;
+ } else {
+ cm_EndDirOp(op);
+ }
+
+ return code;
+ }
+
+ /* Check if it is safe for us to perform local directory updates.
+ Called with scp->mx held. */
+ int
+ cm_CheckDirOpForSingleChange(cm_dirOp_t * op)
+ {
+ long code;
+
+ if (op->scp == NULL)
+ return 0;
+
+ code = cm_DirCheckStatus(op);
+
+ if (code == 0 &&
+ op->dataVersion == op->scp->dataVersion - 1) {
+ /* only one set of changes happened between cm_BeginDirOp()
+ and this function. It is safe for us to perform local
+ changes. */
+ op->newDataVersion = op->scp->dataVersion;
+ op->newLength = op->scp->serverLength;
+
+ osi_Log0(afsd_logp, "cm_CheckDirOpForSingleChange succeeded");
+
+ return 1;
+ }
+
+ osi_Log3(afsd_logp,
+ "cm_CheckDirOpForSingleChange failed. code=0x%x, old dv=%d, new dv=%d",
+ code, op->dataVersion, op->scp->dataVersion);
+ return 0;
+ }
+
+ /* End a sequence of directory operations. Called with op->scp->mx
+ locked.*/
+ long
+ cm_EndDirOp(cm_dirOp_t * op)
+ {
+ long code = 0;
+
+ if (op->scp == NULL)
+ return 0;
+
+ osi_Log2(afsd_logp, "Ending dirOp 0x%p with %d dirty buffer releases",
+ op, op->dirtyBufCount);
+
+ if (op->dirtyBufCount > 0) {
+ /* we made changes. We should go through the list of buffers
+ and update the dataVersion for each. */
+
+ lock_ReleaseMutex(&op->scp->mx);
+ code = buf_ForceDataVersion(op->scp, op->dataVersion, op->newDataVersion);
+ lock_ObtainMutex(&op->scp->mx);
+ }
+
+ if (op->scp)
+ cm_ReleaseSCache(op->scp);
+ op->scp = NULL;
+
+ if (op->userp)
+ cm_ReleaseUser(op->userp);
+ op->userp = 0;
+
+ osi_assertx(op->nBuffers == 0, "Buffer leak after dirOp termination");
+
+ return code;
+ }
+
+ /* NOTE: Called without scp->mx and without bufferp->mx */
+ static long
+ cm_DirOpAddBuffer(cm_dirOp_t * op, cm_buf_t * bufferp)
+ {
+ int i;
+ long code = 0;
+
+ osi_Log2(afsd_logp, "cm_DirOpAddBuffer for op 0x%p, buffer %p", op, bufferp);
+
+ if (bufferp == NULL)
+ return -1;
+
+ for (i=0; i < CM_DIROP_MAXBUFFERS; i++) {
+ if ((op->buffers[i].flags & CM_DIROPBUFF_INUSE) &&
+ op->buffers[i].bufferp == bufferp) {
+ break;
+ }
+ }
+
+ if (i < CM_DIROP_MAXBUFFERS) {
+ /* we already have this buffer on our list */
+
+ op->buffers[i].refcount++;
+ osi_Log0(afsd_logp,
+ "cm_DirOpAddBuffer: the buffer is already listed for the dirOp");
+ return 0;
+ } else {
+ /* we have to add a new buffer */
+ osi_assertx(op->nBuffers < CM_DIROP_MAXBUFFERS - 1,
+ "DirOp has exceeded CM_DIROP_MAXBUFFERS buffers");
+
+ for (i=0; i < CM_DIROP_MAXBUFFERS; i++) {
+ if (!(op->buffers[i].flags & CM_DIROPBUFF_INUSE))
+ break;
+ }
+
+ osi_assert(i < CM_DIROP_MAXBUFFERS);
+
+ lock_ObtainMutex(&bufferp->mx);
+ lock_ObtainMutex(&op->scp->mx);
+
+ /* Make sure we are synchronized. */
+ code = cm_SyncOp(op->scp, bufferp, op->userp, &op->req, PRSFS_LOOKUP,
+ CM_SCACHESYNC_NEEDCALLBACK |
+ CM_SCACHESYNC_WRITE |
+ CM_SCACHESYNC_BUFLOCKED);
+
+ if (code == 0 &&
+ bufferp->dataVersion != op->dataVersion) {
+
+ osi_Log2(afsd_logp, "cm_DirOpAddBuffer: buffer version mismatch. buf ver = %d. want %d", bufferp->dataVersion, op->dataVersion);
+
+ cm_SyncOpDone(op->scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK |
+ CM_SCACHESYNC_WRITE |
+ CM_SCACHESYNC_BUFLOCKED);
+
+ code = CM_ERROR_INVAL;
+ }
+
+ lock_ReleaseMutex(&op->scp->mx);
+ lock_ReleaseMutex(&bufferp->mx);
+
+ if (code) {
+ osi_Log1(afsd_logp, "cm_DirOpAddBuffer: failed to sync buffer. code=0x%x",
+ code);
+ return code;
+ }
+
+ buf_Hold(bufferp);
+ op->buffers[i].bufferp = bufferp;
+ op->buffers[i].refcount = 1; /* start with one ref */
+ op->buffers[i].flags = CM_DIROPBUFF_INUSE;
+
+ op->nBuffers++;
+
+ osi_Log0(afsd_logp, "cm_DirOpAddBuffer: returning success");
+
+ return 0;
+ }
+ }
+
+ /* Note: Called without op->scp->mx */
+ static int
+ cm_DirOpFindBuffer(cm_dirOp_t * op, osi_hyper_t offset, cm_buf_t ** bufferpp)
+ {
+ int i;
+
+ for (i=0; i < CM_DIROP_MAXBUFFERS; i++) {
+ if ((op->buffers[i].flags & CM_DIROPBUFF_INUSE) &&
+ LargeIntegerEqualTo(op->buffers[i].bufferp->offset, offset))
+ break;
+ }
+
+ if (i < CM_DIROP_MAXBUFFERS) {
+ /* found it */
+ op->buffers[i].refcount++;
+ buf_Hold(op->buffers[i].bufferp);
+ *bufferpp = op->buffers[i].bufferp;
+
+ osi_Log2(afsd_logp, "cm_DirOpFindBuffer: found buffer for offset [%x:%x]",
+ offset.HighPart, offset.LowPart);
+ return 1;
+ }
+
+ osi_Log2(afsd_logp, "cm_DirOpFindBuffer: buffer not found for offset [%x:%x]",
+ offset.HighPart, offset.LowPart);
+ return 0;
+ }
+
+
+ /* NOTE: called with scp->mx NOT held */
+ static int
+ cm_DirOpDelBuffer(cm_dirOp_t * op, cm_buf_t * bufferp, int flags)
+ {
+ int i;
+
+ osi_Log3(afsd_logp, "cm_DirOpDelBuffer for op 0x%p, buffer 0x%p, flags=%d",
+ op, bufferp, flags);
+
+ for (i=0; i < CM_DIROP_MAXBUFFERS; i++) {
+ if ((op->buffers[i].flags & CM_DIROPBUFF_INUSE) &&
+ op->buffers[i].bufferp == bufferp)
+ break;
+ }
+
+ if (i < CM_DIROP_MAXBUFFERS) {
+
+ if (flags & DIROP_MODIFIED)
+ op->dirtyBufCount++;
+
+ osi_assert(op->buffers[i].refcount > 0);
+ op->buffers[i].refcount --;
+
+ if (op->buffers[i].refcount == 0) {
+ /* this was the last reference we had */
+
+ osi_Log0(afsd_logp, "cm_DirOpDelBuffer: releasing buffer");
+
+ /* if this buffer was modified, then we update the data
+ version of the buffer with the data version of the
+ scp. */
+ if (!(flags & DIROP_SCPLOCKED)) {
+ lock_ObtainMutex(&op->scp->mx);
+ }
+
+ /* first make sure that the buffer is idle. It should
+ have been idle all along. */
+ osi_assertx((bufferp->cmFlags & (CM_BUF_CMFETCHING |
+ CM_BUF_CMSTORING)) == 0,
+ "Buffer is not idle while performing dirOp");
+
+ cm_SyncOpDone(op->scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK |
+ CM_SCACHESYNC_WRITE);
+
+ #ifdef DEBUG
+ osi_assert(bufferp->dataVersion == op->dataVersion);
+ #endif
+
+ lock_ReleaseMutex(&op->scp->mx);
+
+ lock_ObtainMutex(&bufferp->mx);
+
+ if (flags & DIROP_SCPLOCKED) {
+ lock_ObtainMutex(&op->scp->mx);
+ }
+
+ if (flags & DIROP_MODIFIED) {
+ /* We don't update the dataversion here. Instead we
+ wait until the dirOp is completed and then flip the
+ dataversion on all the buffers in one go.
+ Otherwise we won't know if the dataversion is
+ current because it was fetched from the server or
+ because we touched it during the dirOp. */
+
+ if (bufferp->userp != op->userp) {
+ if (bufferp->userp != NULL)
+ cm_ReleaseUser(bufferp->userp);
+ cm_HoldUser(op->userp);
+ bufferp->userp = op->userp;
+ }
+ }
+
+ lock_ReleaseMutex(&bufferp->mx);
+
+ op->buffers[i].bufferp = NULL;
+ buf_Release(bufferp);
+ op->buffers[i].flags = 0;
+
+ op->nBuffers--;
+
+ return 1;
+ } else {
+ /* we have other references to this buffer. so we have to
+ let it be */
+ return 0;
+ }
+
+ } else {
+ osi_Log0(afsd_logp, "cm_DirOpDelBuffer: buffer not found");
+ osi_assertx(FALSE, "Attempt to delete a non-existent buffer from a dirOp");
+ return -1;
+ }
+ }
+
+ /* Check if we have current status and a callback for the given scp.
+ This should be called before cm_DirGetPage() is called per scp.
+
+ On entry:
+ scp->mx locked
+
+ On exit:
+ scp->mx locked
+
+ During:
+ scp->mx may be released
+ */
+ static long
+ cm_DirCheckStatus(cm_dirOp_t * op)
+ {
+ long code;
+
+ code = cm_SyncOp(op->scp, NULL, op->userp, &op->req, PRSFS_LOOKUP,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+ osi_Log2(afsd_logp, "cm_DirCheckStatus for op 0x%p returning code 0x%x",
+ op, code);
+
+ return code;
+ }
+
+ /* Release a directory buffer that was obtained via a call to
+ cm_DirGetPage() or any other function that returns a locked, held,
+ directory page buffer.
+
+ Called with scp->mx held
+ */
+ static long
+ cm_DirReleasePage(cm_dirOp_t * op, cm_buf_t ** bufferpp, int modified)
+ {
+ long code = 0;
+
+ if (!*bufferpp)
+ return EINVAL;
+
+ cm_DirOpDelBuffer(op, *bufferpp,
+ ((modified ? DIROP_MODIFIED : 0) | DIROP_SCPLOCKED));
+ buf_Release(*bufferpp);
+ *bufferpp = NULL;
+
+ return code;
+ }
+
+ /*
+ Returns the index'th directory page from scp. The userp and reqp
+ will be used to fetch the buffer from the fileserver if necessary.
+ If the call is successful, a locked and held cm_buf_t is returned
+ via buferpp and a pointer to the directory page is returned via
+ datapp.
+
+ The returned buffer should be released via a call to
+ cm_DirReleasePage() or by passing it into a subsequent call to
+ cm_DirGetPage() for the *same* scp.
+
+ If a *locked* buffer for the *same* scp is passed in via bufferpp
+ to the function, it will check if the requested directory page is
+ located in the specified buffer. If not, the buffer will be
+ released and a new buffer returned that contains the requested
+ page.
+
+ Note: If a buffer is specified on entry via bufferpp, it is assumed
+ that the buffer is unmodified. If the buffer is modified, it
+ should be released via cm_DirReleasePage().
+
+ On entry:
+ scp->mx locked.
+ If *bufferpp is non-NULL, then *bufferpp->mx is locked.
+
+ On exit:
+ scp->mxlocked
+ If *bufferpp is non-NULL, then *bufferpp->mx is locked.
+
+ During:
+ scp->mx will be released
+
+ */
+ static long
+ cm_DirGetPage(cm_dirOp_t * op,
+ long index, cm_buf_t ** bufferpp, void ** datapp)
+ {
+ osi_hyper_t pageOffset; /* offset of the dir page from the
+ start of the directory */
+ osi_hyper_t bufferOffset; /* offset of the buffer from the start
+ of the directory */
+ osi_hyper_t thyper;
+
+ cm_buf_t * bufferp = NULL;
+
+ void * datap = NULL;
+
+ long code = 0;
+
+ osi_Log2(afsd_logp, "cm_DirGetPage for op 0x%p, index %d", op, index);
+
+ pageOffset = ConvertLongToLargeInteger(index * CM_DIR_PAGESIZE);
+ bufferOffset.HighPart = pageOffset.HighPart;
+ bufferOffset.LowPart = pageOffset.LowPart & ~(cm_data.buf_blockSize - 1);
+
+ bufferp = *bufferpp;
+ if (bufferp != NULL) {
+ osi_assert(cm_FidCmp(&bufferp->fid, &op->scp->fid) == 0);
+
+ thyper = bufferp->offset;
+ }
+
+ lock_ReleaseMutex(&op->scp->mx);
+
+ if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+ /* wrong buffer */
+
+ if (bufferp) {
+ buf_Release(bufferp);
+ cm_DirOpDelBuffer(op, bufferp, 0);
+ bufferp = NULL;
+ }
+
+ /* first check if we are already working with the buffer */
+ if (cm_DirOpFindBuffer(op, bufferOffset, &bufferp)) {
+ code = 0;
+ goto _has_buffer;
+ }
+
+ lock_ObtainRead(&op->scp->bufCreateLock);
+ code = buf_Get(op->scp, &bufferOffset, &bufferp);
+ lock_ReleaseRead(&op->scp->bufCreateLock);
+
+ if (code) {
+ osi_Log1(afsd_logp, " buf_Get returned code 0x%x", code);
+ bufferp = NULL;
+ goto _exit;
+ }
+
+ osi_assert(bufferp != NULL);
+
+ /* DirOpAddBuffer will obtain bufferp->mx if necessary */
+ code = cm_DirOpAddBuffer(op, bufferp);
+
+ if (code != 0) {
+ /* for some reason, the buffer was rejected. We can't use
+ this buffer, and since this is the only buffer we can
+ potentially use, there's no recourse.*/
+ buf_Release(bufferp);
+ bufferp = NULL;
+ goto _exit;
+ }
+
+ #if 0
+ /* The code below is for making sure the buffer contains
+ current data. This is a bad idea, since the whole point of
+ doing directory updates locally is to avoid fetching all
+ the data from the server. */
+ while (1) {
+ lock_ObtainMutex(&op->scp->mx);
+ code = cm_SyncOp(op->scp, bufferp, op->userp, &op->req, PRSFS_LOOKUP,
+ CM_SCACHESYNC_NEEDCALLBACK |
+ CM_SCACHESYNC_READ |
+ CM_SCACHESYNC_BUFLOCKED);
+
+ if (code) {
+ lock_ReleaseMutex(&op->scp->mx);
+ break;
+ }
+
+ cm_SyncOpDone(op->scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK |
+ CM_SCACHESYNC_READ |
+ CM_SCACHESYNC_BUFLOCKED);
+
+ if (cm_HaveBuffer(op->scp, bufferp, 1)) {
+ lock_ReleaseMutex(&op->scp->mx);
+ break;
+ }
+
+ lock_ReleaseMutex(&bufferp->mx);
+ code = cm_GetBuffer(op->scp, bufferp, NULL, op->userp, &op->req);
+ lock_ReleaseMutex(&op->scp->mx);
+ lock_ObtainMutex(&bufferp->mx);
+
+ if (code)
+ break;
+ }
+
+ if (code) {
+ cm_DirOpDelBuffer(op, bufferp, 0);
+ buf_Release(bufferp);
+ bufferp = NULL;
+ goto _exit;
+ }
+ #endif
+ }
+
+ _has_buffer:
+
+ /* now to figure out where the data is */
+ thyper = LargeIntegerSubtract(pageOffset, bufferOffset);
+
+ osi_assert(thyper.HighPart == 0);
+ osi_assert(cm_data.buf_blockSize > thyper.LowPart &&
+ cm_data.buf_blockSize - thyper.LowPart >= CM_DIR_PAGESIZE);
+
+ datap = (void *) (((char *)bufferp->datap) + thyper.LowPart);
+
+ if (datapp)
+ *datapp = datap;
+
+ /* also, if we are writing past EOF, we should make a note of the
+ new length */
+ thyper = LargeIntegerAdd(pageOffset,
+ ConvertLongToLargeInteger(CM_DIR_PAGESIZE));
+ if (LargeIntegerLessThan(op->newLength, thyper)) {
+ op->newLength = thyper;
+ }
+
+ _exit:
+
+ *bufferpp = bufferp;
+ if (op->scp)
+ lock_ObtainMutex(&op->scp->mx);
+
+ osi_Log1(afsd_logp, "cm_DirGetPage returning code 0x%x", code);
+
+ return code;
+ }
+
+
+ void
+ cm_DirEntryListAdd(char * namep, cm_dirEntryList_t ** list)
+ {
+ size_t len;
+ cm_dirEntryList_t * entry;
+
+ len = strlen(namep);
+ len += sizeof(cm_dirEntryList_t);
+
+ entry = malloc(len);
+ if (entry) {
+ entry->nextp = *list;
+ strcpy(entry->name, namep);
+ *list = entry;
+ }
+ }
+
+ void
+ cm_DirEntryListFree(cm_dirEntryList_t ** list)
+ {
+ cm_dirEntryList_t * entry;
+ cm_dirEntryList_t * next;
+
+ for (entry = *list; entry; entry = next) {
+ next = entry->nextp;
+ free(entry);
+ }
+
+ *list = NULL;
+ }
+
Index: openafs/src/WINNT/afsd/cm_dir.h
diff -c openafs/src/WINNT/afsd/cm_dir.h:1.4.4.1 openafs/src/WINNT/afsd/cm_dir.h:1.4.4.2
*** openafs/src/WINNT/afsd/cm_dir.h:1.4.4.1 Mon Feb 19 22:14:45 2007
--- openafs/src/WINNT/afsd/cm_dir.h Thu Aug 2 16:53:52 2007
***************
*** 31,36 ****
--- 31,39 ----
* header alone.
*/
+ #define CM_DIR_FFIRST 1
+ #define CM_DIR_FNEXT 2
+
typedef struct cm_dirFid {
/* A file identifier. */
afs_int32 vnode; /* file's vnode slot */
***************
*** 56,63 ****
unsigned short hashTable[CM_DIR_NHASHENT];
} cm_dirHeader_t;
! /* this represents a directory entry. We use strlen to find out how many bytes are
! * really in the dir entry; it is always a multiple of 32.
*/
typedef struct cm_dirEntry {
/* A directory entry */
--- 59,67 ----
unsigned short hashTable[CM_DIR_NHASHENT];
} cm_dirHeader_t;
! /* this represents a directory entry. We use strlen to find out how
! * many bytes are really in the dir entry; it is always a multiple of
! * 32.
*/
typedef struct cm_dirEntry {
/* A directory entry */
***************
*** 87,92 ****
} cm_dirPage1_t;
#endif /* UNUSED */
! extern long cm_NameEntries(char *namep, long *lenp);
#endif /* __CM_DIR_ENV__ */
--- 91,178 ----
} cm_dirPage1_t;
#endif /* UNUSED */
! #define CM_DIROP_MAXBUFFERS 8
!
! typedef struct cm_dirOpBuffer {
! int flags;
! cm_buf_t * bufferp;
! int refcount;
! } cm_dirOpBuffer_t;
!
! #define CM_DIROPBUFF_INUSE 0x1
!
! /* Used for managing transactional directory operations. Each
! instance should only be used by one thread. */
! typedef struct cm_dirOp {
! cm_scache_t * scp;
! cm_user_t * userp;
! cm_req_t req;
!
! osi_hyper_t length; /* scp->length at the time
! cm_BeginDirOp() was called.*/
! osi_hyper_t newLength; /* adjusted scp->length */
! afs_uint32 dataVersion; /* scp->dataVersion when
! cm_BeginDirOp() was called.*/
! afs_uint32 newDataVersion; /* scp->dataVersion when
! cm_CheckDirOpForSingleChange()
! was called. */
!
! afs_uint32 dirtyBufCount;
!
! int nBuffers; /* number of buffers below */
! cm_dirOpBuffer_t buffers[CM_DIROP_MAXBUFFERS];
! } cm_dirOp_t;
!
! extern long
! cm_BeginDirOp(cm_scache_t * scp, cm_user_t * userp, cm_req_t * reqp,
! cm_dirOp_t * op);
!
! extern int
! cm_CheckDirOpForSingleChange(cm_dirOp_t * op);
!
! extern long
! cm_EndDirOp(cm_dirOp_t * op);
!
! extern long
! cm_NameEntries(char *namep, long *lenp);
!
! extern long
! cm_DirCreateEntry(cm_dirOp_t * op, char *entry, cm_fid_t * cfid);
!
! extern int
! cm_DirLength(cm_dirOp_t * op);
!
! extern int
! cm_DirDeleteEntry(cm_dirOp_t * op, char *entry);
!
! extern int
! cm_DirMakeDir(cm_dirOp_t * op, cm_fid_t * me, cm_fid_t * parent);
!
! extern int
! cm_DirLookup(cm_dirOp_t * op, char *entry, cm_fid_t * cfid);
!
! extern int
! cm_DirLookupOffset(cm_dirOp_t * op, char *entry, cm_fid_t *cfid, osi_hyper_t *offsetp);
!
! extern int
! cm_DirApply(cm_dirOp_t * op, int (*hookproc) (void *, char *, long, long), void *hook);
!
! extern int
! cm_DirIsEmpty(cm_dirOp_t * op);
!
! extern int
! cm_DirHash(char *string);
!
! /* Directory entry lists */
! typedef struct cm_dirEntryList {
! struct cm_dirEntryList * nextp;
! char name[1];
! } cm_dirEntryList_t;
!
! extern void
! cm_DirEntryListAdd(char * namep, cm_dirEntryList_t ** list);
!
! extern void
! cm_DirEntryListFree(cm_dirEntryList_t ** list);
#endif /* __CM_DIR_ENV__ */
Index: openafs/src/WINNT/afsd/cm_ioctl.c
diff -c openafs/src/WINNT/afsd/cm_ioctl.c:1.73.2.18 openafs/src/WINNT/afsd/cm_ioctl.c:1.73.2.19
*** openafs/src/WINNT/afsd/cm_ioctl.c:1.73.2.18 Sat Jun 30 00:44:23 2007
--- openafs/src/WINNT/afsd/cm_ioctl.c Sun Jul 22 19:10:17 2007
***************
*** 1995,2001 ****
if (r && !stricmp(r+1,ucellp->cellp->name))
*r = '\0';
! code = ubik_Call(PR_NameToID, pruclient, 0, &lnames, &lids);
if (lids.idlist_val) {
*uid = *lids.idlist_val;
free(lids.idlist_val);
--- 1995,2001 ----
if (r && !stricmp(r+1,ucellp->cellp->name))
*r = '\0';
! code = ubik_PR_NameToID(pruclient, 0, &lnames, &lids);
if (lids.idlist_val) {
*uid = *lids.idlist_val;
free(lids.idlist_val);
Index: openafs/src/WINNT/afsd/cm_scache.c
diff -c openafs/src/WINNT/afsd/cm_scache.c:1.35.2.39 openafs/src/WINNT/afsd/cm_scache.c:1.35.2.41
*** openafs/src/WINNT/afsd/cm_scache.c:1.35.2.39 Fri Jul 6 19:22:03 2007
--- openafs/src/WINNT/afsd/cm_scache.c Thu Aug 9 01:33:56 2007
***************
*** 107,112 ****
--- 107,114 ----
lock_ObtainMutex(&bufp->mx);
bufp->cmFlags &= ~CM_BUF_CMSTORING;
bufp->flags &= ~CM_BUF_DIRTY;
+ bufp->dirty_offset = 0;
+ bufp->dirty_length = 0;
bufp->flags |= CM_BUF_ERROR;
bufp->error = VNOVNODE;
bufp->dataVersion = -1; /* bad */
***************
*** 127,132 ****
--- 129,136 ----
lock_ObtainMutex(&bufp->mx);
bufp->cmFlags &= ~CM_BUF_CMFETCHING;
bufp->flags &= ~CM_BUF_DIRTY;
+ bufp->dirty_offset = 0;
+ bufp->dirty_length = 0;
bufp->flags |= CM_BUF_ERROR;
bufp->error = VNOVNODE;
bufp->dataVersion = -1; /* bad */
***************
*** 966,973 ****
osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING|GETCALLBACK want FETCHDATA", scp);
goto sleep;
}
! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) {
! osi_Log2(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is BUF_CMFETCHING|BUF_CMSTORING want FETCHDATA", scp, bufp);
goto sleep;
}
}
--- 970,977 ----
osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING|GETCALLBACK want FETCHDATA", scp);
goto sleep;
}
! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING | CM_BUF_CMWRITING))) {
! osi_Log2(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is BUF_CMFETCHING|BUF_CMSTORING|BUF_CMWRITING want FETCHDATA", scp, bufp);
goto sleep;
}
}
***************
*** 978,985 ****
osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING|GETCALLBACK want STOREDATA", scp);
goto sleep;
}
! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) {
! osi_Log2(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is BUF_CMFETCHING|BUF_CMSTORING want STOREDATA", scp, bufp);
goto sleep;
}
}
--- 982,989 ----
osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING|GETCALLBACK want STOREDATA", scp);
goto sleep;
}
! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING | CM_BUF_CMWRITING))) {
! osi_Log2(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is BUF_CMFETCHING|BUF_CMSTORING|BUF_CMWRITING want STOREDATA", scp, bufp);
goto sleep;
}
}
***************
*** 1045,1050 ****
--- 1049,1058 ----
osi_Log2(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is BUF_CMFETCHING want READ", scp, bufp);
goto sleep;
}
+ if (bufp && (bufp->cmFlags & CM_BUF_CMWRITING)) {
+ osi_Log2(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is BUF_CMWRITING want READ", scp, bufp);
+ goto sleep;
+ }
}
if (flags & CM_SCACHESYNC_WRITE) {
/* don't write unless the status is stable and the chunk
***************
*** 1055,1062 ****
osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING want WRITE", scp);
goto sleep;
}
! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING))) {
! osi_Log2(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is BUF_CMFETCHING|BUF_CMSTORING want WRITE", scp, bufp);
goto sleep;
}
}
--- 1063,1077 ----
osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING want WRITE", scp);
goto sleep;
}
! if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING |
! CM_BUF_CMSTORING |
! CM_BUF_CMWRITING))) {
! osi_Log3(afsd_logp, "CM SyncOp scp 0x%p bufp 0x%p is %s want WRITE",
! scp, bufp,
! ((bufp->cmFlags & CM_BUF_CMFETCHING) ? "CM_BUF_CMFETCHING":
! ((bufp->cmFlags & CM_BUF_CMSTORING) ? "CM_BUF_CMSTORING" :
! ((bufp->cmFlags & CM_BUF_CMWRITING) ? "CM_BUF_CMWRITING" :
! "UNKNOWN!!!"))));
goto sleep;
}
}
***************
*** 1217,1222 ****
--- 1232,1244 ----
osi_QAdd((osi_queue_t **) &scp->bufWritesp, &qdp->q);
}
+ if (flags & CM_SCACHESYNC_WRITE) {
+ /* mark the buffer as being written to. */
+ if (bufp) {
+ bufp->cmFlags |= CM_BUF_CMWRITING;
+ }
+ }
+
return 0;
}
***************
*** 1297,1302 ****
--- 1319,1332 ----
}
}
+ if (flags & CM_SCACHESYNC_WRITE) {
+ if (bufp) {
+ osi_assert(bufp->cmFlags & CM_BUF_CMWRITING);
+
+ bufp->cmFlags &= ~CM_BUF_CMWRITING;
+ }
+ }
+
/* and wakeup anyone who is waiting */
if (scp->flags & CM_SCACHEFLAG_WAITING) {
osi_Log1(afsd_logp, "CM SyncOpDone Waking scp 0x%p", scp);
Index: openafs/src/WINNT/afsd/cm_server.c
diff -c openafs/src/WINNT/afsd/cm_server.c:1.25.2.11 openafs/src/WINNT/afsd/cm_server.c:1.25.2.12
*** openafs/src/WINNT/afsd/cm_server.c:1.25.2.11 Sat Jul 7 09:38:33 2007
--- openafs/src/WINNT/afsd/cm_server.c Thu Aug 2 16:46:12 2007
***************
*** 110,115 ****
--- 110,116 ----
if (code >= 0) {
/* mark server as up */
tsp->flags &= ~CM_SERVERFLAG_DOWN;
+ tsp->downTime = 0;
/* we currently handle 32-bits of capabilities */
if (caps.Capabilities_len > 0) {
***************
*** 152,157 ****
--- 153,159 ----
} else {
/* mark server as down */
tsp->flags |= CM_SERVERFLAG_DOWN;
+ tsp->downTime = osi_Time();
if (code != VRESTARTING)
cm_ForceNewConnections(tsp);
Index: openafs/src/WINNT/afsd/cm_server.h
diff -c openafs/src/WINNT/afsd/cm_server.h:1.13.2.8 openafs/src/WINNT/afsd/cm_server.h:1.13.2.9
*** openafs/src/WINNT/afsd/cm_server.h:1.13.2.8 Thu Jun 28 00:50:15 2007
--- openafs/src/WINNT/afsd/cm_server.h Thu Aug 2 16:46:12 2007
***************
*** 40,45 ****
--- 40,46 ----
osi_mutex_t mx;
unsigned short ipRank; /* server priority */
cm_server_vols_t * vols; /* by mx */
+ time_t downTime; /* by mx */
} cm_server_t;
enum repstate {srv_not_busy, srv_busy, srv_offline, srv_deleted};
Index: openafs/src/WINNT/afsd/cm_vnodeops.c
diff -c openafs/src/WINNT/afsd/cm_vnodeops.c:1.69.2.32 openafs/src/WINNT/afsd/cm_vnodeops.c:1.69.2.34
*** openafs/src/WINNT/afsd/cm_vnodeops.c:1.69.2.32 Wed Jun 13 18:28:25 2007
--- openafs/src/WINNT/afsd/cm_vnodeops.c Thu Aug 2 16:58:42 2007
***************
*** 604,618 ****
{
cm_lookupSearch_t* sp = parmp;
#ifdef AFS_FREELANCE_CLIENT
/* Freelance entries never end up in the DNLC because they
* do not have an associated cm_server_t
*/
! if ( !(cm_freelanceEnabled &&
sp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
! sp->fid.volume==AFS_FAKE_ROOT_VOL_ID ) )
! #endif /* AFS_FREELANCE_CLIENT */
! {
int casefold = sp->caseFold;
sp->caseFold = 0; /* we have a strong preference for exact matches */
if ( *retscp = cm_dnlcLookup(scp, sp)) /* dnlc hit */
--- 604,621 ----
{
cm_lookupSearch_t* sp = parmp;
+ if (
#ifdef AFS_FREELANCE_CLIENT
/* Freelance entries never end up in the DNLC because they
* do not have an associated cm_server_t
*/
! !(cm_freelanceEnabled &&
sp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
! sp->fid.volume==AFS_FAKE_ROOT_VOL_ID )
! #else /* !AFS_FREELANCE_CLIENT */
! TRUE
! #endif
! ) {
int casefold = sp->caseFold;
sp->caseFold = 0; /* we have a strong preference for exact matches */
if ( *retscp = cm_dnlcLookup(scp, sp)) /* dnlc hit */
***************
*** 622,627 ****
--- 625,656 ----
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;
+
+ code = ENOENT;
+
+ code = cm_BeginDirOp(scp, userp, reqp, &dirop);
+ if (code == 0) {
+ code = cm_DirLookup(&dirop, sp->searchNamep, &sp->fid);
+ cm_EndDirOp(&dirop);
+ }
+
+ if (code == 0) {
+ /* found it */
+ sp->found = TRUE;
+ sp->ExactFound = TRUE;
+ lock_ReleaseMutex(&scp->mx);
+
+ *retscp = NULL; /* force caller to call cm_GetSCache() */
+
+ return 0;
+ }
+ }
}
}
***************
*** 1128,1133 ****
--- 1157,1164 ----
cm_lookupSearch_t rock;
int getroot;
+ memset(&rock, 0, sizeof(rock));
+
if (dscp->fid.vnode == 1 && dscp->fid.unique == 1
&& strcmp(namep, "..") == 0) {
if (dscp->dotdotFid.volume == 0)
***************
*** 1139,1145 ****
goto haveFid;
}
! memset(&rock, 0, sizeof(rock));
rock.fid.cell = dscp->fid.cell;
rock.fid.volume = dscp->fid.volume;
rock.searchNamep = namep;
--- 1170,1199 ----
goto haveFid;
}
! if (flags & CM_FLAG_NOMOUNTCHASE) {
! /* In this case, we should go and call cm_Dir* functions
! directly since the following cm_ApplyDir() function will
! not. */
!
! cm_dirOp_t dirop;
!
! lock_ObtainMutex(&dscp->mx);
!
! code = cm_BeginDirOp(dscp, userp, reqp, &dirop);
! if (code == 0) {
! code = cm_DirLookup(&dirop, namep, &rock.fid);
! cm_EndDirOp(&dirop);
! }
!
! lock_ReleaseMutex(&dscp->mx);
!
! if (code == 0) {
! /* found it */
! rock.found = TRUE;
! goto haveFid;
! }
! }
!
rock.fid.cell = dscp->fid.cell;
rock.fid.volume = dscp->fid.volume;
rock.searchNamep = namep;
***************
*** 1486,1491 ****
--- 1540,1546 ----
AFSFetchStatus newDirStatus;
AFSVolSync volSync;
struct rx_connection * callp;
+ cm_dirOp_t dirop;
#ifdef AFS_FREELANCE_CLIENT
if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
***************
*** 1497,1507 ****
/* make sure we don't screw up the dir status during the merge */
lock_ObtainMutex(&dscp->mx);
sflags = CM_SCACHESYNC_STOREDATA;
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, sflags);
lock_ReleaseMutex(&dscp->mx);
! if (code)
return code;
/* make the RPC */
afsFid.Volume = dscp->fid.volume;
--- 1552,1567 ----
/* make sure we don't screw up the dir status during the merge */
lock_ObtainMutex(&dscp->mx);
+
+ code = cm_BeginDirOp(dscp, userp, reqp, &dirop);
+
sflags = CM_SCACHESYNC_STOREDATA;
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, sflags);
lock_ReleaseMutex(&dscp->mx);
! if (code) {
! cm_EndDirOp(&dirop);
return code;
+ }
/* make the RPC */
afsFid.Volume = dscp->fid.volume;
***************
*** 1530,1544 ****
lock_ObtainMutex(&dscp->mx);
cm_dnlcRemove(dscp, namep);
cm_SyncOpDone(dscp, NULL, sflags);
! if (code == 0)
cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, 0);
! 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
* have an inconsistent view of the world.
*/
dscp->cbServerp = NULL;
}
lock_ReleaseMutex(&dscp->mx);
return code;
--- 1590,1608 ----
lock_ObtainMutex(&dscp->mx);
cm_dnlcRemove(dscp, namep);
cm_SyncOpDone(dscp, NULL, sflags);
! if (code == 0) {
cm_MergeStatus(NULL, dscp, &newDirStatus, &volSync, userp, 0);
! if (cm_CheckDirOpForSingleChange(&dirop)) {
! cm_DirDeleteEntry(&dirop, namep);
! }
! } 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
* have an inconsistent view of the world.
*/
dscp->cbServerp = NULL;
}
+ cm_EndDirOp(&dirop);
lock_ReleaseMutex(&dscp->mx);
return code;
***************
*** 1724,1729 ****
--- 1788,1797 ----
int symlinkCount; /* count of # of symlinks traversed */
int extraFlag; /* avoid chasing mt pts for dir cmd */
int phase = 1; /* 1 = tidPathp, 2 = pathp */
+ #define MAX_FID_COUNT 512
+ cm_fid_t fids[MAX_FID_COUNT]; /* array of fids processed in this path walk */
+ int fid_count = 0; /* number of fids processed in this path walk */
+ int i;
#ifdef DEBUG_REFCOUNT
afsi_log("%s:%d cm_NameI rootscp 0x%p ref %d", file, line, rootSCachep, rootSCachep->refCount);
***************
*** 1787,1793 ****
code = cm_Lookup(tscp, component,
flags | extraFlag,
userp, reqp, &nscp);
! if (code) {
cm_ReleaseSCache(tscp);
if (dirScp)
cm_ReleaseSCache(dirScp);
--- 1855,1876 ----
code = cm_Lookup(tscp, component,
flags | extraFlag,
userp, reqp, &nscp);
!
! if (code == 0) {
! for ( i=0; ifid, &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 (code) {
cm_ReleaseSCache(tscp);
if (dirScp)
cm_ReleaseSCache(dirScp);
***************
*** 1855,1860 ****
--- 1938,1958 ----
else
restp = tp;
code = cm_AssembleLink(tscp, restp, &linkScp, &tempsp, userp, reqp);
+
+ if (code == 0 && linkScp != NULL) {
+ for ( i=0; ifid, &fids[i]) ) {
+ code = CM_ERROR_TOO_MANY_SYMLINKS;
+ cm_ReleaseSCache(linkScp);
+ nscp = NULL;
+ break;
+ }
+ }
+ if (i == fid_count && fid_count < MAX_FID_COUNT) {
+ fids[fid_count++] = linkScp->fid;
+ }
+ }
+
if (code) {
/* something went wrong */
cm_ReleaseSCache(tscp);
***************
*** 1987,1992 ****
--- 2085,2096 ----
cm_FreeSpace(spacep);
cm_ReleaseSCache(newRootScp);
+ if (linkScp == *outScpp) {
+ cm_ReleaseSCache(*outScpp);
+ *outScpp = NULL;
+ code = CM_ERROR_NOSUCHPATH;
+ }
+
return code;
}
***************
*** 2461,2467 ****
cm_callbackRequest_t cbReq;
AFSFid newAFSFid;
cm_fid_t newFid;
! cm_scache_t *scp;
int didEnd;
AFSStoreStatus inStatus;
AFSFetchStatus updatedDirStatus;
--- 2565,2571 ----
cm_callbackRequest_t cbReq;
AFSFid newAFSFid;
cm_fid_t newFid;
! cm_scache_t *scp = NULL;
int didEnd;
AFSStoreStatus inStatus;
AFSFetchStatus updatedDirStatus;
***************
*** 2469,2474 ****
--- 2573,2579 ----
AFSCallBack newFileCallback;
AFSVolSync volSync;
struct rx_connection * callp;
+ cm_dirOp_t dirop;
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
***************
*** 2482,2490 ****
--- 2587,2598 ----
* completes.
*/
lock_ObtainMutex(&dscp->mx);
+ cm_BeginDirOp(dscp, userp, reqp, &dirop);
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
cm_StartCallbackGrantingCall(NULL, &cbReq);
+ } else {
+ cm_EndDirOp(&dirop);
}
lock_ReleaseMutex(&dscp->mx);
if (code) {
***************
*** 2558,2563 ****
--- 2666,2678 ----
if (!didEnd)
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
+ lock_ObtainMutex(&dscp->mx);
+ if (scp && cm_CheckDirOpForSingleChange(&dirop)) {
+ cm_DirCreateEntry(&dirop, namep, &newFid);
+ }
+ cm_EndDirOp(&dirop);
+ lock_ReleaseMutex(&dscp->mx);
+
return code;
}
***************
*** 2603,2608 ****
--- 2718,2724 ----
AFSCallBack newDirCallback;
AFSVolSync volSync;
struct rx_connection * callp;
+ cm_dirOp_t dirop;
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
***************
*** 2616,2624 ****
--- 2732,2743 ----
* our call completes.
*/
lock_ObtainMutex(&dscp->mx);
+ cm_BeginDirOp(dscp, userp, reqp, &dirop);
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
cm_StartCallbackGrantingCall(NULL, &cbReq);
+ } else {
+ cm_EndDirOp(&dirop);
}
lock_ReleaseMutex(&dscp->mx);
if (code) {
***************
*** 2691,2696 ****
--- 2810,2822 ----
if (!didEnd)
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
+ lock_ObtainMutex(&dscp->mx);
+ if (scp && cm_CheckDirOpForSingleChange(&dirop)) {
+ cm_DirCreateEntry(&dirop, namep, &newFid);
+ }
+ cm_EndDirOp(&dirop);
+ lock_ReleaseMutex(&dscp->mx);
+
/* and return error code */
return code;
}
***************
*** 2706,2711 ****
--- 2832,2838 ----
AFSFetchStatus newLinkStatus;
AFSVolSync volSync;
struct rx_connection * callp;
+ cm_dirOp_t dirop;
if (dscp->fid.cell != sscp->fid.cell ||
dscp->fid.volume != sscp->fid.volume) {
***************
*** 2713,2719 ****
--- 2840,2849 ----
}
lock_ObtainMutex(&dscp->mx);
+ cm_BeginDirOp(dscp, userp, reqp, &dirop);
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA);
+ if (code != 0)
+ cm_EndDirOp(&dirop);
lock_ReleaseMutex(&dscp->mx);
if (code)
***************
*** 2753,2759 ****
--- 2883,2893 ----
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ if (cm_CheckDirOpForSingleChange(&dirop)) {
+ cm_DirCreateEntry(&dirop, namep, &sscp->fid);
+ }
}
+ cm_EndDirOp(&dirop);
lock_ReleaseMutex(&dscp->mx);
return code;
***************
*** 2773,2785 ****
--- 2907,2923 ----
AFSFetchStatus newLinkStatus;
AFSVolSync volSync;
struct rx_connection * callp;
+ cm_dirOp_t dirop;
/* 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_ObtainMutex(&dscp->mx);
+ cm_BeginDirOp(dscp, userp, reqp, &dirop);
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA);
+ if (code != 0)
+ cm_EndDirOp(&dirop);
lock_ReleaseMutex(&dscp->mx);
if (code) {
return code;
***************
*** 2817,2823 ****
--- 2955,2970 ----
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA);
if (code == 0) {
cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ if (cm_CheckDirOpForSingleChange(&dirop)) {
+ newFid.cell = dscp->fid.cell;
+ newFid.volume = dscp->fid.volume;
+ newFid.vnode = newAFSFid.Vnode;
+ newFid.unique = newAFSFid.Unique;
+
+ cm_DirCreateEntry(&dirop, namep, &newFid);
+ }
}
+ cm_EndDirOp(&dirop);
lock_ReleaseMutex(&dscp->mx);
/* now try to create the new dir's entry, too, but be careful to
***************
*** 2856,2872 ****
AFSFetchStatus updatedDirStatus;
AFSVolSync volSync;
struct rx_connection * callp;
/* 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_ObtainMutex(&dscp->mx);
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA);
- lock_ReleaseMutex(&dscp->mx);
if (code) {
return code;
}
didEnd = 0;
/* try the RPC now */
--- 3003,3023 ----
AFSFetchStatus updatedDirStatus;
AFSVolSync volSync;
struct rx_connection * callp;
+ cm_dirOp_t dirOp;
/* 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_ObtainMutex(&dscp->mx);
+ cm_BeginDirOp(dscp, userp, reqp, &dirOp);
code = cm_SyncOp(dscp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA);
if (code) {
+ cm_EndDirOp(&dirOp);
+ lock_ReleaseMutex(&dscp->mx);
return code;
}
+ lock_ReleaseMutex(&dscp->mx);
didEnd = 0;
/* try the RPC now */
***************
*** 2899,2905 ****
--- 3050,3060 ----
if (code == 0) {
cm_dnlcRemove(dscp, namep);
cm_MergeStatus(NULL, dscp, &updatedDirStatus, &volSync, userp, 0);
+ if (cm_CheckDirOpForSingleChange(&dirOp)) {
+ cm_DirDeleteEntry(&dirOp, namep);
}
+ }
+ cm_EndDirOp(&dirOp);
lock_ReleaseMutex(&dscp->mx);
/* and return error code */
***************
*** 2937,2942 ****
--- 3092,3101 ----
AFSVolSync volSync;
int oneDir;
struct rx_connection * callp;
+ cm_dirOp_t oldDirOp;
+ cm_fid_t fileFid;
+ int diropCode = -1;
+ cm_dirOp_t newDirOp;
/* 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
***************
*** 2952,2959 ****
--- 3111,3122 ----
lock_ObtainMutex(&oldDscp->mx);
cm_dnlcRemove(oldDscp, oldNamep);
cm_dnlcRemove(oldDscp, newNamep);
+ cm_BeginDirOp(oldDscp, userp, reqp, &oldDirOp);
code = cm_SyncOp(oldDscp, NULL, userp, reqp, 0,
CM_SCACHESYNC_STOREDATA);
+ if (code != 0) {
+ cm_EndDirOp(&oldDirOp);
+ }
lock_ReleaseMutex(&oldDscp->mx);
}
else {
***************
*** 2972,2992 ****
--- 3135,3162 ----
if (oldDscp->fid.vnode < newDscp->fid.vnode) {
lock_ObtainMutex(&oldDscp->mx);
+ cm_BeginDirOp(oldDscp, userp, reqp, &oldDirOp);
cm_dnlcRemove(oldDscp, oldNamep);
code = cm_SyncOp(oldDscp, NULL, userp, reqp, 0,
CM_SCACHESYNC_STOREDATA);
+ if (code != 0)
+ cm_EndDirOp(&oldDirOp);
lock_ReleaseMutex(&oldDscp->mx);
if (code == 0) {
lock_ObtainMutex(&newDscp->mx);
+ cm_BeginDirOp(newDscp, userp, reqp, &newDirOp);
cm_dnlcRemove(newDscp, newNamep);
code = cm_SyncOp(newDscp, NULL, userp, reqp, 0,
CM_SCACHESYNC_STOREDATA);
+ if (code != 0)
+ cm_EndDirOp(&newDirOp);
lock_ReleaseMutex(&newDscp->mx);
if (code) {
/* cleanup first one */
lock_ObtainMutex(&oldDscp->mx);
cm_SyncOpDone(oldDscp, NULL,
CM_SCACHESYNC_STOREDATA);
+ cm_EndDirOp(&oldDirOp);
lock_ReleaseMutex(&oldDscp->mx);
}
}
***************
*** 2994,3014 ****
--- 3164,3191 ----
else {
/* lock the new vnode entry first */
lock_ObtainMutex(&newDscp->mx);
+ cm_BeginDirOp(newDscp, userp, reqp, &newDirOp);
cm_dnlcRemove(newDscp, newNamep);
code = cm_SyncOp(newDscp, NULL, userp, reqp, 0,
CM_SCACHESYNC_STOREDATA);
+ if (code != 0)
+ cm_EndDirOp(&newDirOp);
lock_ReleaseMutex(&newDscp->mx);
if (code == 0) {
lock_ObtainMutex(&oldDscp->mx);
+ cm_BeginDirOp(oldDscp, userp, reqp, &oldDirOp);
cm_dnlcRemove(oldDscp, oldNamep);
code = cm_SyncOp(oldDscp, NULL, userp, reqp, 0,
CM_SCACHESYNC_STOREDATA);
+ if (code != 0)
+ cm_EndDirOp(&oldDirOp);
lock_ReleaseMutex(&oldDscp->mx);
if (code) {
/* cleanup first one */
lock_ObtainMutex(&newDscp->mx);
cm_SyncOpDone(newDscp, NULL,
CM_SCACHESYNC_STOREDATA);
+ cm_EndDirOp(&newDirOp);
lock_ReleaseMutex(&newDscp->mx);
}
}
***************
*** 3054,3063 ****
--- 3231,3257 ----
/* update the individual stat cache entries for the directories */
lock_ObtainMutex(&oldDscp->mx);
cm_SyncOpDone(oldDscp, NULL, CM_SCACHESYNC_STOREDATA);
+
if (code == 0) {
cm_MergeStatus(NULL, oldDscp, &updatedOldDirStatus, &volSync,
userp, 0);
+
+ if (cm_CheckDirOpForSingleChange(&oldDirOp)) {
+
+ diropCode = cm_DirLookup(&oldDirOp, oldNamep, &fileFid);
+
+ if (diropCode == 0) {
+ if (oneDir) {
+ diropCode = cm_DirCreateEntry(&oldDirOp, newNamep, &fileFid);
+ }
+
+ if (diropCode == 0) {
+ diropCode = cm_DirDeleteEntry(&oldDirOp, oldNamep);
}
+ }
+ }
+ }
+ cm_EndDirOp(&oldDirOp);
lock_ReleaseMutex(&oldDscp->mx);
/* and update it for the new one, too, if necessary */
***************
*** 3067,3073 ****
--- 3261,3275 ----
if (code == 0) {
cm_MergeStatus(NULL, newDscp, &updatedNewDirStatus, &volSync,
userp, 0);
+
+ /* we only make the local change if we successfully made
+ the change in the old directory AND there was only one
+ change in the new directory */
+ if (diropCode == 0 && cm_CheckDirOpForSingleChange(&newDirOp)) {
+ cm_DirCreateEntry(&newDirOp, newNamep, &fileFid);
+ }
}
+ cm_EndDirOp(&newDirOp);
lock_ReleaseMutex(&newDscp->mx);
}
Index: openafs/src/WINNT/afsd/fs.c
diff -c openafs/src/WINNT/afsd/fs.c:1.32.4.11 openafs/src/WINNT/afsd/fs.c:1.32.4.12
*** openafs/src/WINNT/afsd/fs.c:1.32.4.11 Mon Jul 2 20:35:13 2007
--- openafs/src/WINNT/afsd/fs.c Fri Jul 27 23:04:37 2007
***************
*** 1099,1105 ****
blob.out = cellname;
code = pioctl(fname, VIOC_FILE_CELL_NAME, &blob, 1);
! return code ? errno : 0;
}
/* Check if a username is valid: If it contains only digits (or a
--- 1099,1105 ----
blob.out = cellname;
code = pioctl(fname, VIOC_FILE_CELL_NAME, &blob, 1);
! return code;
}
/* Check if a username is valid: If it contains only digits (or a
***************
*** 1930,1937 ****
cellName = localCellName;
}
} else {
! if (!cellName)
! GetCell(parent,space);
}
code = GetCellName(cellName?cellName:space, &info);
--- 1930,1940 ----
cellName = localCellName;
}
} else {
! if (!cellName) {
! code = GetCell(parent,space);
! if (code)
! return 1;
! }
}
code = GetCellName(cellName?cellName:space, &info);
Index: openafs/src/WINNT/afsd/rawops.c
diff -c openafs/src/WINNT/afsd/rawops.c:1.2.4.2 openafs/src/WINNT/afsd/rawops.c:1.2.4.3
*** openafs/src/WINNT/afsd/rawops.c:1.2.4.2 Mon Dec 11 23:01:26 2006
--- openafs/src/WINNT/afsd/rawops.c Thu Aug 9 01:33:56 2007
***************
*** 155,165 ****
long written = 0;
osi_hyper_t fileLength; /* file's length at start of write */
osi_hyper_t minLength; /* don't read past this */
! long nbytes; /* # of bytes to transfer this iteration */
cm_buf_t *bufferp;
osi_hyper_t thyper; /* hyper tmp variable */
osi_hyper_t bufferOffset;
! long bufIndex; /* index in buffer where our data is */
int doWriteBack;
osi_hyper_t writeBackOffset; /* offset of region to write back when
* I/O is done */
--- 155,165 ----
long written = 0;
osi_hyper_t fileLength; /* file's length at start of write */
osi_hyper_t minLength; /* don't read past this */
! afs_uint32 nbytes; /* # of bytes to transfer this iteration */
cm_buf_t *bufferp;
osi_hyper_t thyper; /* hyper tmp variable */
osi_hyper_t bufferOffset;
! afs_uint32 bufIndex; /* index in buffer where our data is */
int doWriteBack;
osi_hyper_t writeBackOffset; /* offset of region to write back when
* I/O is done */
***************
*** 333,339 ****
else
#endif /* DJGPP */
memcpy(bufferp->datap + bufIndex, op, nbytes);
! buf_SetDirty(bufferp);
/* and record the last writer */
if (bufferp->userp != userp) {
--- 333,339 ----
else
#endif /* DJGPP */
memcpy(bufferp->datap + bufIndex, op, nbytes);
! buf_SetDirty(bufferp, bufIndex, nbytes);
/* and record the last writer */
if (bufferp->userp != userp) {
Index: openafs/src/WINNT/afsd/smb.c
diff -c openafs/src/WINNT/afsd/smb.c:1.118.2.37 openafs/src/WINNT/afsd/smb.c:1.118.2.40
*** openafs/src/WINNT/afsd/smb.c:1.118.2.37 Thu Jul 5 15:22:16 2007
--- openafs/src/WINNT/afsd/smb.c Thu Aug 9 01:33:56 2007
***************
*** 4389,4395 ****
scp->bulkStatProgress)) {
/* Don't bulk stat if risking timeout */
int now = GetTickCount();
! if (now - req.startTime > RDRtimeout) {
scp->bulkStatProgress = thyper;
scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
--- 4389,4395 ----
scp->bulkStatProgress)) {
/* Don't bulk stat if risking timeout */
int now = GetTickCount();
! if (now - req.startTime > RDRtimeout * 1000) {
scp->bulkStatProgress = thyper;
scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
***************
*** 5182,5187 ****
--- 5182,5188 ----
char *maskp; /* pointer to the star pattern */
int flags;
int any;
+ cm_dirEntryList_t * matches;
} smb_unlinkRock_t;
int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
***************
*** 5210,5229 ****
match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
}
if (match) {
! osi_Log1(smb_logp, "Unlinking %s",
osi_LogSaveString(smb_logp, matchName));
! code = cm_Unlink(dscp, dep->name, rockp->userp, rockp->reqp);
! if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
! smb_NotifyChange(FILE_ACTION_REMOVED,
! FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
! dscp, dep->name, NULL, TRUE);
! if (code == 0) {
rockp->any = 1;
/* If we made a case sensitive exact match, we might as well quit now. */
if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
code = CM_ERROR_STOPNOW;
! }
}
else code = 0;
--- 5211,5228 ----
match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
}
if (match) {
! osi_Log1(smb_logp, "Found match %s",
osi_LogSaveString(smb_logp, matchName));
!
! cm_DirEntryListAdd(dep->name, &rockp->matches);
!
rockp->any = 1;
/* If we made a case sensitive exact match, we might as well quit now. */
if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
code = CM_ERROR_STOPNOW;
! else
! code = 0;
}
else code = 0;
***************
*** 5304,5309 ****
--- 5303,5309 ----
rock.reqp = &req;
rock.dscp = dscp;
rock.vcp = vcp;
+ rock.matches = NULL;
/* Now, if we aren't dealing with a wildcard match, we first try an exact
* match. If that fails, we do a case insensitve match.
***************
*** 5324,5329 ****
--- 5324,5347 ----
if (code == CM_ERROR_STOPNOW)
code = 0;
+ if (code == 0 && rock.matches) {
+ cm_dirEntryList_t * entry;
+
+ for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+
+ osi_Log1(smb_logp, "Unlinking %s",
+ osi_LogSaveString(smb_logp, entry->name));
+ code = cm_Unlink(dscp, entry->name, userp, &req);
+
+ if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ smb_NotifyChange(FILE_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
+ dscp, entry->name, NULL, TRUE);
+ }
+ }
+
+ cm_DirEntryListFree(&rock.matches);
+
cm_ReleaseUser(userp);
cm_ReleaseSCache(dscp);
***************
*** 5342,5347 ****
--- 5360,5366 ----
char *maskp; /* pointer to star pattern of old file name */
int flags; /* tilde, casefold, etc */
char *newNamep; /* ptr to the new file's name */
+ char oldName[MAX_PATH];
int any;
} smb_renameRock_t;
***************
*** 5366,5386 ****
cm_Gen8Dot3Name(dep, shortName, NULL);
match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
}
if (match) {
rockp->any = 1;
!
! code = cm_Rename(rockp->odscp, dep->name,
! rockp->ndscp, rockp->newNamep, rockp->userp,
! rockp->reqp);
! /* if the call worked, stop doing the search now, since we
! * really only want to rename one file.
! */
! osi_Log1(smb_logp, "cm_Rename returns %ld", code);
! if (code == 0)
code = CM_ERROR_STOPNOW;
! }
! else
code = 0;
return code;
}
--- 5385,5399 ----
cm_Gen8Dot3Name(dep, shortName, NULL);
match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
}
+
if (match) {
rockp->any = 1;
! strncpy(rockp->oldName, dep->name, sizeof(rockp->oldName)/sizeof(char) - 1);
! rockp->oldName[sizeof(rockp->oldName)/sizeof(char) - 1] = '\0';
code = CM_ERROR_STOPNOW;
! } else {
code = 0;
+ }
return code;
}
***************
*** 5485,5490 ****
--- 5498,5504 ----
rock.maskp = oldLastNamep;
rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
rock.newNamep = newLastNamep;
+ rock.oldName[0] = '\0';
rock.any = 0;
/* Check if the file already exists; if so return error */
***************
*** 5537,5552 ****
}
osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
! if (code == CM_ERROR_STOPNOW)
! code = 0;
! else if (code == 0)
code = CM_ERROR_NOSUCHFILE;
/* Handle Change Notification */
/*
* Being lazy, not distinguishing between files and dirs in this
* filter, since we'd have to do a lookup.
*/
filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME;
if (oldDscp == newDscp) {
if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
--- 5551,5574 ----
}
osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
! if (code == CM_ERROR_STOPNOW && rock.oldName[0] != '\0') {
! code = cm_Rename(rock.odscp, rock.oldName,
! rock.ndscp, rock.newNamep, rock.userp,
! rock.reqp);
! /* if the call worked, stop doing the search now, since we
! * really only want to rename one file.
! */
! osi_Log1(smb_logp, "cm_Rename returns %ld", code);
! } else if (code == 0) {
code = CM_ERROR_NOSUCHFILE;
+ }
/* Handle Change Notification */
/*
* Being lazy, not distinguishing between files and dirs in this
* filter, since we'd have to do a lookup.
*/
+ if (code == 0) {
filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME;
if (oldDscp == newDscp) {
if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
***************
*** 5563,5568 ****
--- 5585,5591 ----
filter, newDscp, newLastNamep,
NULL, TRUE);
}
+ }
if (tmpscp != NULL)
cm_ReleaseSCache(tmpscp);
***************
*** 5759,5764 ****
--- 5782,5788 ----
char *maskp; /* pointer to the star pattern */
int flags;
int any;
+ cm_dirEntryList_t * matches;
} smb_rmdirRock_t;
int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
***************
*** 5783,5802 ****
matchName = shortName;
match = (cm_stricmp(matchName, rockp->maskp) == 0);
}
if (match) {
- osi_Log1(smb_logp, "Removing directory %s",
- osi_LogSaveString(smb_logp, matchName));
- code = cm_RemoveDir(dscp, dep->name, rockp->userp, rockp->reqp);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
- dscp, dep->name, NULL, TRUE);
- if (code == 0)
rockp->any = 1;
}
- else code = 0;
! return code;
}
long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
--- 5807,5819 ----
matchName = shortName;
match = (cm_stricmp(matchName, rockp->maskp) == 0);
}
+
if (match) {
rockp->any = 1;
+ cm_DirEntryListAdd(dep->name, &rockp->matches);
}
! return 0;
}
long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
***************
*** 5867,5872 ****
--- 5884,5890 ----
rock.userp = userp;
rock.reqp = &req;
rock.dscp = dscp;
+ rock.matches = NULL;
/* First do a case sensitive match, and if that fails, do a case insensitive match */
code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
***************
*** 5877,5882 ****
--- 5895,5918 ----
code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
}
+ if (code == 0 && rock.matches) {
+ cm_dirEntryList_t * entry;
+
+ for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+ osi_Log1(smb_logp, "Removing directory %s",
+ osi_LogSaveString(smb_logp, entry->name));
+
+ code = cm_RemoveDir(dscp, entry->name, userp, &req);
+
+ if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ smb_NotifyChange(FILE_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
+ dscp, entry->name, NULL, TRUE);
+ }
+ }
+
+ cm_DirEntryListFree(&rock.matches);
+
cm_ReleaseUser(userp);
cm_ReleaseSCache(dscp);
***************
*** 6381,6391 ****
cm_scache_t *scp;
osi_hyper_t fileLength; /* file's length at start of write */
osi_hyper_t minLength; /* don't read past this */
! long nbytes; /* # of bytes to transfer this iteration */
cm_buf_t *bufferp;
osi_hyper_t thyper; /* hyper tmp variable */
osi_hyper_t bufferOffset;
! long bufIndex; /* index in buffer where our data is */
int doWriteBack;
osi_hyper_t writeBackOffset;/* offset of region to write back when
* I/O is done */
--- 6417,6427 ----
cm_scache_t *scp;
osi_hyper_t fileLength; /* file's length at start of write */
osi_hyper_t minLength; /* don't read past this */
! afs_uint32 nbytes; /* # of bytes to transfer this iteration */
cm_buf_t *bufferp;
osi_hyper_t thyper; /* hyper tmp variable */
osi_hyper_t bufferOffset;
! afs_uint32 bufIndex; /* index in buffer where our data is */
int doWriteBack;
osi_hyper_t writeBackOffset;/* offset of region to write back when
* I/O is done */
***************
*** 6572,6578 ****
else
#endif /* DJGPP */
memcpy(bufferp->datap + bufIndex, op, nbytes);
! buf_SetDirty(bufferp);
/* and record the last writer */
if (bufferp->userp != userp) {
--- 6608,6614 ----
else
#endif /* DJGPP */
memcpy(bufferp->datap + bufIndex, op, nbytes);
! buf_SetDirty(bufferp, bufIndex, nbytes);
/* and record the last writer */
if (bufferp->userp != userp) {
Index: openafs/src/WINNT/afsd/smb3.c
diff -c openafs/src/WINNT/afsd/smb3.c:1.95.2.38 openafs/src/WINNT/afsd/smb3.c:1.95.2.40
*** openafs/src/WINNT/afsd/smb3.c:1.95.2.38 Sat Jun 30 00:38:52 2007
--- openafs/src/WINNT/afsd/smb3.c Fri Jul 27 22:51:16 2007
***************
*** 4337,4343 ****
userp = smb_GetTran2User(vcp, p);
if (!userp) {
! osi_Log1(smb_logp, "T2 search dir unable to resolve user [%d]", p->uid);
smb_FreeTran2Packet(outp);
return CM_ERROR_BADSMB;
}
--- 4337,4343 ----
userp = smb_GetTran2User(vcp, p);
if (!userp) {
! osi_Log1(smb_logp, "T2SDSingle search dir unable to resolve user [%d]", p->uid);
smb_FreeTran2Packet(outp);
return CM_ERROR_BADSMB;
}
***************
*** 4378,4390 ****
return 0;
}
#endif /* DFS_SUPPORT */
! osi_Log1(smb_logp,"smb_ReceiveTran2SearchDir scp 0x%p", scp);
! lock_ObtainMutex(&scp->mx);
! if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0 &&
! LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
! scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
! }
! lock_ReleaseMutex(&scp->mx);
/* now do a single case sensitive lookup for the file in question */
code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE, userp, &req, &targetscp);
--- 4378,4384 ----
return 0;
}
#endif /* DFS_SUPPORT */
! osi_Log1(smb_logp,"T2SDSingle scp 0x%p", scp);
/* now do a single case sensitive lookup for the file in question */
code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE, userp, &req, &targetscp);
***************
*** 4984,4990 ****
LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
/* Don't bulk stat if risking timeout */
DWORD now = GetTickCount();
! if (now - req.startTime > RDRtimeout) {
scp->bulkStatProgress = thyper;
scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
--- 4978,4984 ----
LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
/* Don't bulk stat if risking timeout */
DWORD now = GetTickCount();
! if (now - req.startTime > RDRtimeout * 1000) {
scp->bulkStatProgress = thyper;
scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
Index: openafs/src/WINNT/aklog/aklog.c
diff -c openafs/src/WINNT/aklog/aklog.c:1.14.4.4 openafs/src/WINNT/aklog/aklog.c:1.14.4.5
*** openafs/src/WINNT/aklog/aklog.c:1.14.4.4 Tue May 15 23:34:58 2007
--- openafs/src/WINNT/aklog/aklog.c Thu Aug 9 18:54:07 2007
***************
*** 220,235 ****
}
/*
- * This is a crock, but it is Transarc's crock, so
- * we have to play along in order to get the
- * functionality. The way the afs id is stored is
- * as a string in the username field of the token.
- * Contrary to what you may think by looking at
- * the code for tokens, this hack (AFS ID %d) will
- * not work if you change %d to something else.
- */
-
- /*
* This code is taken from cklog -- it lets people
* automatically register with the ptserver in foreign cells
*/
--- 220,225 ----
***************
*** 266,272 ****
}
if ((*status = ktc_SetToken(aserver, atoken, aclient, 0))) {
! printf("%s: unable to obtain tokens for cell %s "
"(status: %d).\n", progname, cell_to_use, status);
*status = AKLOG_TOKEN;
return ;
--- 256,262 ----
}
if ((*status = ktc_SetToken(aserver, atoken, aclient, 0))) {
! printf("%s: unable to set tokens for cell %s "
"(status: %d).\n", progname, cell_to_use, status);
*status = AKLOG_TOKEN;
return ;
Index: openafs/src/WINNT/client_config/lang/en_US/afs_config.rc
diff -c openafs/src/WINNT/client_config/lang/en_US/afs_config.rc:1.7.6.3 openafs/src/WINNT/client_config/lang/en_US/afs_config.rc:1.7.6.4
*** openafs/src/WINNT/client_config/lang/en_US/afs_config.rc:1.7.6.3 Fri Feb 2 23:53:04 2007
--- openafs/src/WINNT/client_config/lang/en_US/afs_config.rc Fri Jul 27 11:41:53 2007
***************
*** 700,706 ****
IDS_SERVICE_FAIL_START "The AFS Client Service could not be started successfully. You might not have authorization to perform this operation.\n\nError 0x%1."
IDS_SERVICE_FAIL_STOP "The AFS Client Service could not be stopped successfully. You might not have authorization to perform this operation.\n\nError 0x%1."
IDS_WARN_STOPPED "The disabled controls cannot be changed because the AFS Client service is not running."
! IDS_WARN_ADMIN "The disabled controls cannot be changed because you are not logged in to Windows as an administrator."
IDS_CELL_UNKNOWN "(unknown)"
IDS_GATEWAY_UNKNOWN "(unknown)"
END
--- 700,706 ----
IDS_SERVICE_FAIL_START "The AFS Client Service could not be started successfully. You might not have authorization to perform this operation.\n\nError 0x%1."
IDS_SERVICE_FAIL_STOP "The AFS Client Service could not be stopped successfully. You might not have authorization to perform this operation.\n\nError 0x%1."
IDS_WARN_STOPPED "The disabled controls cannot be changed because the AFS Client service is not running."
! IDS_WARN_ADMIN "The disabled controls cannot be changed because you are not a member of the AFS Administrators Group."
IDS_CELL_UNKNOWN "(unknown)"
IDS_GATEWAY_UNKNOWN "(unknown)"
END
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm:1.5.4.16 openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm:1.5.4.17
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm:1.5.4.16 Fri Jun 22 10:40:12 2007
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/index.htm Thu Aug 9 11:46:17 2007
***************
*** 57,63 ****
OpenAFS for Windows
! Version 1.5.21
--- 57,63 ----
OpenAFS for Windows
! Version 1.5.22
***************
*** 80,86 ****
·
OpenAFS for Windows 1.5.21
Release Notes
--- 80,86 ----
·
OpenAFS for Windows 1.5.22
Release Notes
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm:1.1.6.16 openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm:1.1.6.17
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm:1.1.6.16 Fri Jun 22 10:18:39 2007
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/logo.htm Thu Aug 9 11:46:21 2007
***************
*** 18,24 ****
.shape {behavior:url(#default#VML);}
!
OpenAFS for Windows 1.5.21 Release Notes
! OpenAFS for Windows 1.5.22 Release Notes
! OpenAFS for Windows 1.5.21 Release Notes
! OpenAFS for Windows 1.5.22 Release Notes
! OpenAFS for Windows 1.5.21
Release Notes
The Andrew File System (AFS) is a location-independent
--- 586,592 ----
!
OpenAFS for Windows 1.5.22
Release Notes
The Andrew File System (AFS) is a location-independent
***************
*** 646,652 ****
Operational Notes. 2
!
4. How to
Debug Problems with OpenAFS for Windows: 11
--- 646,652 ----
Operational Notes
. 2
!
4. How to
Debug Problems with OpenAFS for Windows: 11
***************
*** 1160,1166 ****
Integrated Login supports the ability to obtain tokens for
multiple cells. For further information on how to configure this feature
! read about the TheseCells
value.
As of release 1.5.3, OpenAFS for Windows supports files
larger than 2GB. The maximum file size is now 16777216 terabytes when the
--- 1493,1499 ----
name="_Toc115416118">3.12.
! Large File (64-bit) Support
As of release 1.5.3, OpenAFS for Windows supports files
larger than 2GB. The maximum file size is now 16777216 terabytes when the
***************
*** 2100,2116 ****
name="_Toc115416144">3.38.
! AFS Client Universally Unique Identifiers
The OpenAFS Client implements Universally Unique Identifiers
! (UUIDs ). They are used to provide the server
with a method of identifying the client that is independent of IP
! address. The UUID is generated when the AFSCache
! file is created and is maintained as long as the contents of the AFSCache file are kept intact. The UUID is stored in
! the AFSCache file. When cloning machines
! that have Windows AFS client installed, the AFSCache
! files should be deleted as part of the cloning process.
3.38.
! AFS Client Universally Unique Identifiers (UUIDs) vs. System Cloning
The OpenAFS Client implements Universally Unique Identifiers
! (UUIDs ). They are used to provide the AFS file server
with a method of identifying the client that is independent of IP
! address. This permits the AFS file server to track mobile clients or those
! behind Network Address Translators when they move from address to address or port
! to port. Tracking the client improves client performance by permitting callback
! state to be maintained across location changes. The UUID is generated when the
! AFSCache file is created and is maintained as long as
! the contents of the AFSCache file are valid.
! The UUID is stored in the AFSCache file.
!
! When cloning machines that have Windows AFS client installed it is necessary
! to generate a new UUID for each client. This will be done automatically if
! the Windows Machine SID is re-generated using Microsoft SysPrep. If the SID is
! not being re-generated either the AFSCache file should
! be deleted or the command fs uuid -generate must be executed after the
! the clone is created. Multiple AFS clients reporting the same UUID will not
! only result in horrible AFS client performance and cache inconsistencies, but
! they will also put a tremendous strain on the AFS file servers.
!
For lab environments that wish to erase all cached data
! on each restart, the NonPersistentCaching option
! will disable the use of the persistent cache file. As a side effect, a new
! UUID will be generated for the AFS client service on each restart.
The CIFS session timeout defaults to 45 seconds and can be
! increased by modifying the registry .
The CIFS session timeout defaults to 45 seconds and can be
! increased by modifying the registry .
bug reports .
4.5. Microsoft MiniDumps bug reports .
4.5. Microsoft MiniDumps Value: ChunkSize
Type: DWORD
! Default: 17 (CM_CONFIGDEFAULT_CHUNKSIZE)
Variable: cm_logChunkSize (cm_chunkSize
= 1 << cm_logChunkSize )
Size of chunk for reading and writing. Actual chunk size
! is 2^cm_logChunkSize.
--- 4378,4388 ----
style='mso-bookmark:_Toc170268930'>Value: ChunkSize
Type: DWORD
! Default: 20 (CM_CONFIGDEFAULT_CHUNKSIZE)
Variable: cm_logChunkSize (cm_chunkSize
= 1 << cm_logChunkSize )
Size of chunk for reading and writing. Actual chunk size
! is 2^cm_logChunkSize. The default chunk size is therefore 1 MB.
***************
*** 4491,4500 ****
Variable: buf_CacheType
When this registry value is set to a non-zero value, the
CachePath value is ignored and the cache data is
! stored in the windows paging file. This prevents the use of persistent
! caching (when available) as well as the ability to alter the size of the
! cache at runtime using the "fs setcachesize " command.
--- 4508,4516 ----
Variable: buf_CacheType
When this registry value is set to a non-zero value, the
CachePath value is ignored and the cache data is
! stored in the windows paging file. This disables the use of persistent
! caching and the ability to maintain a single UUID for the AFS client service
! across restarts.
Index: openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm
diff -c openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm:1.2.6.15 openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm:1.2.6.16
*** openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm:1.2.6.15 Fri Jun 22 10:18:40 2007
--- openafs/src/WINNT/doc/install/Documentation/en_US/html/ReleaseNotes/toc.htm Thu Aug 9 11:46:24 2007
***************
*** 10,16 ****
! OpenAFS for Windows 1.5.21 Table of Contents