]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
windows-multi-fix-20061002
authorJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 3 Oct 2006 04:22:37 +0000 (04:22 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 3 Oct 2006 04:22:37 +0000 (04:22 +0000)
Fix the following problems:

it is possible for a file to be created, buffers to become dirty from
writes, the file to be deleted, the stat cache entry to be reused, and
the dirty buffers to remain dirty until the end of time.

stat cache entry starvation can occur because of large numbers of dirty
buffers which take too long to be written to the file server.  The
thread that writes dirty buffers in background writes/checks a small
number of buffers, SQRT(buf-count), and then sleeps for 5 seconds.
Writing all of the dirty buffers via this algorithm produces untimely
results.

threads can end up waiting for a callback on the same stat cache entry
even though there are no threads actually attempting to perform the
FetchStatus.

And:

Fix prototypes

Optimize cm_GetNewSCache to reuse scache entries for deleted files
and entries not in the hashtable before allocating a new one.  This
keeps the entries in the hashtable to a minimum and thereby improving
performance for all other operations which must lookup a scache entry
by FID.

Add support for Sequential and Random Access flags

16 files changed:
src/WINNT/afsd/cm_access.c
src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_buf.h
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_daemon.h
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_dcache.h
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/rawops.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c

index 8e1343451e3b1c2602f762b2224d752f2722395a..9b1d0b0e60103fec8e24b8b1b48b87406df5c2f4 100644 (file)
@@ -114,7 +114,7 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
 {
     long code;
     cm_fid_t tfid;
-    cm_scache_t *aclScp;
+    cm_scache_t *aclScp = NULL;
     int got_cb = 0;
 
     /* pretty easy: just force a pass through the fetch status code */
@@ -143,13 +143,17 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
         code = cm_GetSCache(&tfid, &aclScp, userp, reqp);
         if (code) {
             lock_ObtainMutex(&scp->mx);
-            return code;
+           goto _done;
         }       
                 
         osi_Log2(afsd_logp, "GetAccess parent scp %x user %x", aclScp, userp);
         lock_ObtainMutex(&aclScp->mx);
-
-       code = cm_GetCallback(aclScp, userp, reqp, 1);
+       code = cm_SyncOp(aclScp, NULL, userp, reqp, 0,
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+       if (!code) {
+           code = cm_GetCallback(aclScp, userp, reqp, 1);
+           cm_SyncOpDone(aclScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+       }
         lock_ReleaseMutex(&aclScp->mx);
         cm_ReleaseSCache(aclScp);
         lock_ObtainMutex(&scp->mx);
@@ -157,5 +161,9 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
        code = cm_GetCallback(scp, userp, reqp, 1);
     }
 
+  _done:
+    if (got_cb)
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     return code;
 }
index 768aef534d4e5ec7944b819c7d92fea8f32a6661..460bf8490be5ed9f08506de7d47c238210cc2aee 100644 (file)
@@ -106,7 +106,12 @@ void buf_ReleaseLocked(cm_buf_t *bp)
 {
     /* ensure that we're in the LRU queue if our ref count is 0 */
     osi_assert(bp->magic == CM_BUF_MAGIC);
+#ifdef DEBUG
+    if (bp->refCount == 0)
+       DebugBreak();
+#else
     osi_assert(bp->refCount > 0);
+#endif
     if (--bp->refCount == 0) {
         if (!(bp->flags & CM_BUF_INLRU)) {
             osi_QAdd((osi_queue_t **) &cm_data.buf_freeListp, &bp->q);
@@ -132,23 +137,28 @@ void buf_IncrSyncer(long parm)
 {
     cm_buf_t *bp;                      /* buffer we're hacking on; held */
     long i;                            /* counter */
-    long nAtOnce;                      /* how many to do at once */
+    long wasDirty;
     cm_req_t req;
 
     lock_ObtainWrite(&buf_globalLock);
     bp = cm_data.buf_allp;
     buf_HoldLocked(bp);
     lock_ReleaseWrite(&buf_globalLock);
-    nAtOnce = (long)sqrt((double)cm_data.buf_nbuffers);
+    wasDirty = 0;
+
     while (buf_ShutdownFlag == 0) {
-        i = SleepEx(5000, 1);
-        if (i != 0) continue;
-            
+        if (!wasDirty) {
+            i = SleepEx(5000, 1);
+            if (i != 0) continue;
+       }
+
         if (buf_ShutdownFlag == 1)
             return;
 
+       wasDirty = 0;
+
         /* now go through our percentage of the buffers */
-        for (i=0; i<nAtOnce; i++) {
+        for (i=0; i<cm_data.buf_nbuffers; i++) {
             /* don't want its identity changing while we're
              * messing with it, so must do all of this with
              * bp held.
@@ -159,8 +169,10 @@ void buf_IncrSyncer(long parm)
              * a log page at any given instant.
              */
             cm_InitReq(&req);
+#ifdef NO_BKG_RETRIES
             req.flags |= CM_REQ_NORETRY;
-            buf_CleanAsync(bp, &req);
+#endif
+           wasDirty |= buf_CleanAsync(bp, &req);
 
             /* now advance to the next buffer; the allp chain never changes,
              * and so can be followed even when holding no locks.
@@ -432,9 +444,9 @@ void buf_WaitIO(cm_scache_t * scp, cm_buf_t *bp)
         if ( bp->flags & CM_BUF_WAITING ) {
             bp->waitCount++;
             bp->waitRequests++;
-            osi_Log1(afsd_logp, "buf_WaitIO CM_BUF_WAITING already set for 0x%p", bp);
+            osi_Log1(buf_logp, "buf_WaitIO CM_BUF_WAITING already set for 0x%p", bp);
         } else {
-            osi_Log1(afsd_logp, "buf_WaitIO CM_BUF_WAITING set for 0x%p", bp);
+            osi_Log1(buf_logp, "buf_WaitIO CM_BUF_WAITING set for 0x%p", bp);
             bp->flags |= CM_BUF_WAITING;
             bp->waitCount = bp->waitRequests = 1;
         }
@@ -443,10 +455,10 @@ void buf_WaitIO(cm_scache_t * scp, cm_buf_t *bp)
        smb_UpdateServerPriority();
 
         lock_ObtainMutex(&bp->mx);
-        osi_Log1(afsd_logp, "buf_WaitIO conflict wait done for 0x%p", bp);
+        osi_Log1(buf_logp, "buf_WaitIO conflict wait done for 0x%p", bp);
         bp->waitCount--;
         if (bp->waitCount == 0) {
-            osi_Log1(afsd_logp, "buf_WaitIO CM_BUF_WAITING reset for 0x%p", bp);
+            osi_Log1(buf_logp, "buf_WaitIO CM_BUF_WAITING reset for 0x%p", bp);
             bp->flags &= ~CM_BUF_WAITING;
             bp->waitRequests = 0;
         }
@@ -457,7 +469,7 @@ void buf_WaitIO(cm_scache_t * scp, cm_buf_t *bp)
         if ( scp ) {
             lock_ObtainMutex(&scp->mx);
             if (scp->flags & CM_SCACHEFLAG_WAITING) {
-                osi_Log1(afsd_logp, "buf_WaitIO waking scp 0x%p", scp);
+                osi_Log1(buf_logp, "buf_WaitIO waking scp 0x%p", scp);
                 osi_Wakeup((LONG_PTR)&scp->flags);
             }
            lock_ReleaseMutex(&scp->mx);
@@ -468,10 +480,10 @@ void buf_WaitIO(cm_scache_t * scp, cm_buf_t *bp)
      * the I/O to complete.  Do so.
      */
     if (bp->flags & CM_BUF_WAITING) {
-        osi_Log1(afsd_logp, "buf_WaitIO Waking bp 0x%p", bp);
+        osi_Log1(buf_logp, "buf_WaitIO Waking bp 0x%p", bp);
         osi_Wakeup((LONG_PTR) bp);
     }
-    osi_Log1(afsd_logp, "WaitIO finished wait for bp 0x%p", bp);
+    osi_Log1(buf_logp, "WaitIO finished wait for bp 0x%p", bp);
 }
 
 /* find a buffer, if any, for a particular file ID and offset.  Assumes
@@ -516,25 +528,36 @@ cm_buf_t *buf_Find(struct cm_scache *scp, osi_hyper_t *offsetp)
  * Makes sure that there's only one person writing this block
  * at any given time, and also ensures that the log is forced sufficiently far,
  * if this buffer contains logged data.
+ *
+ * Returns one if the buffer was dirty.
  */
-void buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp)
+long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp)
 {
     long code = 0;
+    long isdirty = 0;
 
     osi_assert(bp->magic == CM_BUF_MAGIC);
 
     while ((bp->flags & CM_BUF_DIRTY) == CM_BUF_DIRTY) {
+       isdirty = 1;
         lock_ReleaseMutex(&bp->mx);
 
-       osi_Log1(afsd_logp, "buf_CleanAsyncLocked starts I/O on 0x%p", bp);
+       osi_Log1(buf_logp, "buf_CleanAsyncLocked starts I/O on 0x%p", bp);
         code = (*cm_buf_opsp->Writep)(&bp->fid, &bp->offset,
                                        cm_data.buf_blockSize, 0, bp->userp,
                                        reqp);
-       osi_Log2(afsd_logp, "buf_CleanAsyncLocked I/O on 0x%p, done=%d", bp, code);
+       osi_Log2(buf_logp, "buf_CleanAsyncLocked I/O on 0x%p, done=%d", bp, code);
                 
         lock_ObtainMutex(&bp->mx);
-        if (code) 
-            break;
+       /* if the Write routine returns No Such File, clear the dirty flag 
+        * because we aren't going to be able to write this data to the file
+        * server.
+        */
+       if (code == CM_ERROR_NOSUCHFILE){
+           bp->flags &= ~CM_BUF_DIRTY;
+           bp->flags |= CM_BUF_ERROR;
+           bp->error = CM_ERROR_NOSUCHFILE;
+       }
 
 #ifdef DISKCACHE95
         /* Disk cache support */
@@ -553,6 +576,7 @@ void buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp)
         osi_Log1(buf_logp, "buf_WaitIO Waking bp 0x%p", bp);
         osi_Wakeup((LONG_PTR) bp);
     }
+    return isdirty;
 }
 
 /* Called with a zero-ref count buffer and with the buf_globalLock write locked.
@@ -753,6 +777,9 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
             if (scp) {
                 bp->flags |= CM_BUF_INHASH;
                 bp->fid = scp->fid;
+#ifdef DEBUG
+               bp->scp = scp;
+#endif
                 bp->offset = *offsetp;
                 i = BUF_HASH(&scp->fid, offsetp);
                 bp->hashp = cm_data.buf_hashTablepp[i];
@@ -884,16 +911,17 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
         if (bp) {
             /* lock it and break out */
             lock_ObtainMutex(&bp->mx);
-            break;
 
 #ifdef DISKCACHE95
             /* touch disk chunk to update LRU info */
             diskcache_Touch(bp->dcp);
 #endif /* DISKCACHE95 */
+            break;
         }
 
         /* otherwise, we have to create a page */
         code = buf_GetNewLocked(scp, &pageOffset, &bp);
+       /* bp->mx is now held */
 
         /* check if the buffer was created in a race condition branch.
          * If so, go around so we can hold a reference to it. 
@@ -1026,13 +1054,16 @@ long buf_CountFreeList(void)
 }
 
 /* clean a buffer synchronously */
-void buf_CleanAsync(cm_buf_t *bp, cm_req_t *reqp)
+long buf_CleanAsync(cm_buf_t *bp, cm_req_t *reqp)
 {
+    long code;
     osi_assert(bp->magic == CM_BUF_MAGIC);
 
     lock_ObtainMutex(&bp->mx);
-    buf_CleanAsyncLocked(bp, reqp);
+    code = buf_CleanAsyncLocked(bp, reqp);
     lock_ReleaseMutex(&bp->mx);
+
+    return code;
 }       
 
 /* wait for a buffer's cleaning to finish */
@@ -1101,8 +1132,8 @@ long buf_CleanAndReset(void)
 
                 /* now no locks are held; clean buffer and go on */
                 cm_InitReq(&req);
-                buf_CleanAsync(bp, &req);
-                buf_CleanWait(NULL, bp);
+               buf_CleanAsync(bp, &req);
+               buf_CleanWait(NULL, bp);
 
                 /* relock and release buffer */
                 lock_ObtainWrite(&buf_globalLock);
@@ -1261,6 +1292,10 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
             }
         }
                
+       cm_SyncOpDone( scp, bufp, 
+                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS
+                      | CM_SCACHESYNC_SETSIZE | CM_SCACHESYNC_BUFLOCKED);
+
         lock_ReleaseMutex(&scp->mx);
         lock_ReleaseMutex(&bufp->mx);
     
@@ -1382,8 +1417,8 @@ long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
                 bp->userp = userp;
                 lock_ReleaseMutex(&bp->mx);
             }   
-            buf_CleanAsync(bp, reqp);
-            buf_CleanWait(scp, bp);
+            code = buf_CleanAsync(bp, reqp);
+           buf_CleanWait(scp, bp);
             lock_ObtainMutex(&bp->mx);
             if (bp->flags & CM_BUF_ERROR) {
                 if (code == 0 || code == -1) 
@@ -1509,3 +1544,43 @@ void buf_ForceTrace(BOOL flush)
         FlushFileBuffers(handle);
     CloseHandle(handle);
 }
+
+long buf_DirtyBuffersExist(cm_fid_t *fidp)
+{
+    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;
+    }
+    return 0;
+}
+
+long buf_CleanDirtyBuffers(cm_scache_t *scp)
+{
+    cm_buf_t *bp;
+    afs_uint32 bcount = 0;
+    cm_fid_t * fidp = &scp->fid;
+
+    for (bp = cm_data.buf_allp; bp; bp=bp->allp, bcount++) {
+       if (!cm_FidCmp(fidp, &bp->fid) && (bp->flags & CM_BUF_DIRTY)) {
+               buf_Hold(bp);
+           lock_ObtainMutex(&bp->mx);
+           bp->cmFlags &= ~CM_BUF_CMSTORING;
+           bp->flags &= ~CM_BUF_DIRTY;
+           bp->flags |= CM_BUF_ERROR;
+           bp->error = VNOVNODE;
+           bp->dataVersion = -1; /* bad */
+           bp->dirtyCounter++;
+           if (bp->flags & CM_BUF_WAITING) {
+               osi_Log2(buf_logp, "BUF CleanDirtyBuffers Waking [scp 0x%x] bp 0x%x", scp, bp);
+               osi_Wakeup((long) &bp);
+           }
+           lock_ReleaseMutex(&bp->mx);
+           buf_Release(bp);
+       }
+    }
+    return 0;
+}
+
index 22c227818acafc611c9a1be188c04d652cd29baa..99357aa74d3d2a251e1b6100f1d83995c739d089 100644 (file)
@@ -80,6 +80,10 @@ typedef struct cm_buf {
 #endif /* notdef */
     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 */
     long size;                 /* size in bytes of this buffer */
     char *datap;               /* data in this buffer */
@@ -111,7 +115,7 @@ typedef struct cm_softRef {
     long counter;              /* counter of changes to identity */
 } cm_softRef_t;
 
-#define CM_BUF_READING 1       /* now reading buffer to the disk */
+#define CM_BUF_READING 1       /* now reading buffer from the disk */
 #define CM_BUF_WRITING 2       /* now writing buffer to the disk */
 #define CM_BUF_INHASH  4       /* in the hash table */
 #define CM_BUF_DIRTY           8       /* buffer is dirty */
@@ -160,9 +164,9 @@ extern long buf_Get(struct cm_scache *, osi_hyper_t *, cm_buf_t **);
 
 extern long buf_GetNew(struct cm_scache *, osi_hyper_t *, cm_buf_t **);
 
-extern void buf_CleanAsyncLocked(cm_buf_t *, cm_req_t *);
+extern long buf_CleanAsyncLocked(cm_buf_t *, cm_req_t *);
 
-extern void buf_CleanAsync(cm_buf_t *, cm_req_t *);
+extern long buf_CleanAsync(cm_buf_t *, cm_req_t *);
 
 extern void buf_CleanWait(cm_scache_t *, cm_buf_t *);
 
@@ -197,6 +201,10 @@ extern long buf_ValidateBuffers(void);
 
 extern void buf_ForceTrace(BOOL flush);
 
+extern long buf_DirtyBuffersExist(cm_fid_t * fidp);
+
+extern long buf_CleanDirtyBuffers(cm_scache_t *scp);
+
 /* error codes */
 #define CM_BUF_EXISTS  1       /* buffer exists, and shouldn't */
 #endif /*  _BUF_H__ENV_ */
index df53cfdde14b8f97e256298642595a9876bcfa7b..5ead137c0d3ef2625bfcd45293677252c1f901d6 100644 (file)
@@ -1680,9 +1680,16 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
         /* turn off mustCall, since it has now forced us past the check above */
         mustCall = 0;
 
+#if 0
+       /* 20060929 jaltman - We are being called from within cm_SyncOp.
+        * if we call cm_SyncOp again and another thread has attempted
+        * to obtain current status CM_SCACHEFLAG_WAITING will be set
+        * and we will deadlock.  
+        */
         /* otherwise, we have to make an RPC to get the status */
         sflags = CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK;
         cm_SyncOp(scp, NULL, userp, reqp, 0, sflags);
+#endif /* deadlock */
         cm_StartCallbackGrantingCall(scp, &cbr);
         sfid = scp->fid;
         lock_ReleaseMutex(&scp->mx);
@@ -1717,7 +1724,10 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
         } else {
             cm_EndCallbackGrantingCall(NULL, &cbr, NULL, 0);
         }
+#if 0
+       /* 20060929 jaltman - don't deadlock */
         cm_SyncOpDone(scp, NULL, sflags);
+#endif
 
         /* now check to see if we got an error */
         if (code) {
index c923daf5cc716a633f0f769d8afbc0c72b9a21eb..5b1fe417da09ada201ba2afb87bf8902867c4458 100644 (file)
@@ -94,7 +94,7 @@ void cm_BkgDaemon(long parm)
     lock_ReleaseWrite(&cm_daemonLock);
 }
 
-void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, long p1, long p2, long p3, long p4,
+void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
        cm_user_t *userp)
 {
     cm_bkgRequest_t *rp;
index a5c25a65bcb58d5c60c8a62ee537eec28ddb3e55..5e614cafe7622d8901e23a5653bbe18fa253663d 100644 (file)
@@ -24,21 +24,21 @@ void cm_DaemonShutdown(void);
 
 void cm_InitDaemon(int nDaemons);
 
-typedef void (cm_bkgProc_t)(cm_scache_t *scp, long p1, long p2, long p3,
-       long p4, struct cm_user *up);
+typedef void (cm_bkgProc_t)(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3,
+       afs_uint32 p4, struct cm_user *up);
 
 typedef struct cm_bkgRequest {
        osi_queue_t q;
        cm_bkgProc_t *procp;
         cm_scache_t *scp;
-        long p1;
-        long p2;
-        long p3;
-        long p4;
+        afs_uint32 p1;
+        afs_uint32 p2;
+        afs_uint32 p3;
+        afs_uint32 p4;
         struct cm_user *userp;
 } cm_bkgRequest_t;
 
-extern void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, long p1,
-       long p2, long p3, long p4, cm_user_t *userp);
+extern void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, afs_uint32 p1,
+       afs_uint32 p2, afs_uint32 p3, afs_uint32 p4, cm_user_t *userp);
 
 #endif /*  __CM_DAEMON_H_ENV_ */
index 5e003196654d207456dae1acce81e49a436fab4c..89c5721acb89f660fa086cb89bdc4357a8fb41e9 100644 (file)
@@ -81,12 +81,18 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
      * buffer, although more likely it will just return a new, empty, buffer.
      */
     scp = cm_FindSCache(fidp);
-    if (scp == NULL)
+    if (scp == NULL) {
         return CM_ERROR_NOSUCHFILE;    /* shouldn't happen */
+    }
 
     cm_AFSFidFromFid(&tfid, fidp);
 
     lock_ObtainMutex(&scp->mx);
+    if (scp->flags & CM_SCACHEFLAG_DELETED) {
+       lock_ReleaseMutex(&scp->mx);
+        cm_ReleaseSCache(scp);
+       return CM_ERROR_NOSUCHFILE;
+    }
 
     code = cm_SetupStoreBIOD(scp, offsetp, length, &biod, userp, reqp);
     if (code) {
@@ -450,6 +456,8 @@ long cm_BufUnstabilize(void *parmp, cm_user_t *userp)
         
     scp = parmp;
         
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_SETSIZE);
+
     lock_ReleaseMutex(&scp->mx);
         
     /* always succeeds */
@@ -559,6 +567,7 @@ long cm_CheckFetchRange(cm_scache_t *scp, osi_hyper_t *startBasep, long length,
                  && bp->dataVersion != scp->dataVersion)
                 stop = 1;
             buf_Release(bp);
+           bp = NULL;
         }
         else 
             stop = 1;
@@ -592,15 +601,23 @@ long cm_CheckFetchRange(cm_scache_t *scp, osi_hyper_t *startBasep, long length,
     return code;
 }
 
-void cm_BkgStore(cm_scache_t *scp, long p1, long p2, long p3, long p4,
+void cm_BkgStore(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
                  cm_user_t *userp)
 {
     osi_hyper_t toffset;
     long length;
     cm_req_t req;
+    long code;
+
+    if (scp->flags & CM_SCACHEFLAG_DELETED) {
+       osi_Log4(afsd_logp, "Skipping BKG store - Deleted scp 0x%p, offset 0x%x:%08x, length 0x%x", scp, p2, p1, p3);
+       return;
+    }
 
     cm_InitReq(&req);
+#ifdef NO_BKG_RETRIES
     req.flags |= CM_REQ_NORETRY;
+#endif
 
     toffset.LowPart = p1;
     toffset.HighPart = p2;
@@ -608,7 +625,7 @@ void cm_BkgStore(cm_scache_t *scp, long p1, long p2, long p3, long p4,
 
     osi_Log4(afsd_logp, "Starting BKG store scp 0x%p, offset 0x%x:%08x, length 0x%x", scp, p2, p1, p3);
 
-    cm_BufWrite(&scp->fid, &toffset, length, /* flags */ 0, userp, &req);
+    code = cm_BufWrite(&scp->fid, &toffset, length, /* flags */ 0, userp, &req);
 
     lock_ObtainMutex(&scp->mx);
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_ASYNCSTORE);
@@ -753,7 +770,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
     lock_ObtainMutex(&scp->mx);
 
     bufp = NULL;
-    for (temp = 0; temp < inSize; temp += cm_data.buf_blockSize, bufp = NULL) {
+    for (temp = 0; temp < inSize; temp += cm_data.buf_blockSize) {
         thyper.HighPart = 0;
         thyper.LowPart = temp;
         tbase = LargeIntegerAdd(*inOffsetp, thyper);
@@ -789,6 +806,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
             cm_SyncOpDone(scp, bufp, flags);
             lock_ReleaseMutex(&bufp->mx);
             buf_Release(bufp);
+           bufp = NULL;
         }       
     }
 
@@ -814,6 +832,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
     biop->length = cm_data.buf_blockSize;
     firstModOffset = bufp->offset;
     biop->offset = firstModOffset;
+    bufp = NULL;       /* this buffer and reference added to the queue */
 
     /* compute the window surrounding *inOffsetp of size cm_chunkSize */
     scanStart = *inOffsetp;
@@ -844,6 +863,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
         lock_ObtainMutex(&scp->mx);
         if (code == 0) {
             buf_Release(bufp);
+           bufp = NULL;
             break;
         }
                 
@@ -851,6 +871,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
         if (code) {
             lock_ReleaseMutex(&bufp->mx);
             buf_Release(bufp);
+           bufp = NULL;
             break;
         }
                 
@@ -859,6 +880,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
             cm_SyncOpDone(scp, bufp, flags);
             lock_ReleaseMutex(&bufp->mx);
             buf_Release(bufp);
+           bufp = NULL;
             break;
         }
 
@@ -875,6 +897,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
         osi_QAddT((osi_queue_t **) &biop->bufListp,
                   (osi_queue_t **) &biop->bufListEndp,
                   &qdp->q);
+       bufp = NULL;            /* added to the queue */
 
         /* update biod info describing the transfer */
         biop->offset = LargeIntegerSubtract(biop->offset, thyper);
@@ -900,6 +923,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
         lock_ObtainMutex(&scp->mx);
         if (code == 0) {
             buf_Release(bufp);
+           bufp = NULL;
             break;
         }
 
@@ -907,6 +931,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
         if (code) {
             lock_ReleaseMutex(&bufp->mx);
             buf_Release(bufp);
+           bufp = NULL;
             break;
         }
                 
@@ -915,6 +940,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
             cm_SyncOpDone(scp, bufp, flags);
             lock_ReleaseMutex(&bufp->mx);
             buf_Release(bufp);
+           bufp = NULL;
             break;
         }
 
@@ -931,6 +957,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
         osi_QAddH((osi_queue_t **) &biop->bufListp,
                   (osi_queue_t **) &biop->bufListEndp,
                   &qdp->q);
+       bufp = NULL;
 
         /* update biod info describing the transfer */
         biop->length += cm_data.buf_blockSize;
@@ -1224,6 +1251,7 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore)
         lock_ReleaseMutex(&scp->mx);
         lock_ReleaseMutex(&bufp->mx);
         buf_Release(bufp);
+       bufp = NULL;
     }
 
     /* clean things out */
@@ -1409,7 +1437,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
                     nbytes_hi = ntohl(nbytes_hi);
                 } else {
                     nbytes_hi = 0;
-                                       code = callp->error;
+                   code = callp->error;
                     rx_EndCall(callp, code);
                     callp = NULL;
                 }
index 99513343d46c847f375d2331a918c5b0ce43e022..1969cfc1ffb72daf727d8f6b2aa58c5fc936f08d 100644 (file)
@@ -42,10 +42,10 @@ extern void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore);
 extern long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp,
        long inSize, cm_bulkIO_t *biop, cm_user_t *userp, cm_req_t *reqp);
 
-extern void cm_BkgPrefetch(cm_scache_t *scp, long p1, long p2, long p3, long p4,
+extern void cm_BkgPrefetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
        struct cm_user *userp);
 
-extern void cm_BkgStore(cm_scache_t *scp, long p1, long p2, long p3, long p4,
+extern void cm_BkgStore(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
        struct cm_user *userp);
 
 extern void cm_ConsiderPrefetch(cm_scache_t *scp, osi_hyper_t *offsetp,
index e552564c6492a3639aaa9371803b85fcf62bc149..dd27ea0f2cd8b3cdc2a62936667f7b4177a0828a 100644 (file)
@@ -987,7 +987,7 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
         
     /* if something went wrong, bail out now */
     if (code) {
-        goto done;
+        goto done2;
     }
         
     lock_ObtainMutex(&scp->mx);
@@ -996,7 +996,7 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
     if (code) {     
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
-        goto done;
+        goto done2;
     }
 
     /* now check that this is a real mount point */
@@ -1004,7 +1004,7 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
         code = CM_ERROR_INVAL;
-        goto done;
+        goto done1;
     }
 
     /* time to make the RPC, so drop the lock */
@@ -1018,7 +1018,10 @@ long cm_IoctlDeleteMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
                           FILE_NOTIFY_CHANGE_DIR_NAME,
                           dscp, cp, NULL, TRUE);
 
-  done:
+  done1:
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+  done2:
     cm_ReleaseSCache(dscp);
     return code;
 }
@@ -1841,7 +1844,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
         
     /* if something went wrong, bail out now */
     if (code) {
-        goto done;
+        goto done2;
     }
         
     lock_ObtainMutex(&scp->mx);
@@ -1850,7 +1853,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
     if (code) {     
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
-        goto done;
+        goto done2;
     }
        
     /* now check that this is a real symlink */
@@ -1860,7 +1863,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
         lock_ReleaseMutex(&scp->mx);
         cm_ReleaseSCache(scp);
         code = CM_ERROR_INVAL;
-        goto done;
+        goto done1;
     }
        
     /* time to make the RPC, so drop the lock */
@@ -1875,7 +1878,10 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
                           | FILE_NOTIFY_CHANGE_DIR_NAME,
                           dscp, cp, NULL, TRUE);
 
-  done:
+  done1:
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+  done2:
     cm_ReleaseSCache(dscp);
     return code;
 }
index 9d1de18bf57b50584e08a67cd3bf308b30d76ea3..fa427077cb6376db5541f562afaa5fada3297962 100644 (file)
@@ -84,6 +84,8 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
                lock_ObtainMutex(&bufp->mx);
                bufp->cmFlags &= ~CM_BUF_CMSTORING;
                bufp->flags &= ~CM_BUF_DIRTY;
+               bufp->flags |= CM_BUF_ERROR;
+               bufp->error = VNOVNODE;
                bufp->dataVersion = -1; /* bad */
                bufp->dirtyCounter++;
                if (bufp->flags & CM_BUF_WAITING) {
@@ -102,6 +104,8 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
                lock_ObtainMutex(&bufp->mx);
                bufp->cmFlags &= ~CM_BUF_CMFETCHING;
                bufp->flags &= ~CM_BUF_DIRTY;
+               bufp->flags |= CM_BUF_ERROR;
+               bufp->error = VNOVNODE;
                bufp->dataVersion = -1; /* bad */
                bufp->dirtyCounter++;
                if (bufp->flags & CM_BUF_WAITING) {
@@ -112,6 +116,7 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
                buf_Release(bufp);
            }
         }
+       buf_CleanDirtyBuffers(scp); 
     } else {
        /* look for things that shouldn't still be set */
        osi_assert(scp->bufWritesp == NULL);
@@ -121,6 +126,7 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
     /* invalidate so next merge works fine;
      * also initialize some flags */
     scp->flags &= ~(CM_SCACHEFLAG_STATD
+                    | CM_SCACHEFLAG_DELETED
                     | CM_SCACHEFLAG_RO
                     | CM_SCACHEFLAG_PURERO
                     | CM_SCACHEFLAG_OVERQUOTA
@@ -183,34 +189,86 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
 cm_scache_t *cm_GetNewSCache(void)
 {
     cm_scache_t *scp;
+    int retry = 0;
 
-  start:
-    if (cm_data.currentSCaches >= cm_data.maxSCaches) {
-        for (scp = cm_data.scacheLRULastp;
-              scp;
-              scp = (cm_scache_t *) osi_QPrev(&scp->q)) {
-            if (scp->refCount == 0) 
-                break;
-        }
-                
-        if (scp) {
-            osi_assert(scp >= cm_data.scacheBaseAddress && scp < (cm_scache_t *)cm_data.hashTablep);
-
-           if (!cm_RecycleSCache(scp, 0)) {
-           
+    /* first pass - look for deleted objects */
+    for ( scp = cm_data.scacheLRULastp;
+         scp;
+         scp = (cm_scache_t *) osi_QPrev(&scp->q)) 
+    {
+       osi_assert(scp >= cm_data.scacheBaseAddress && scp < (cm_scache_t *)cm_data.hashTablep);
+
+       if (scp->refCount == 0) {
+           if (scp->flags & CM_SCACHEFLAG_DELETED) {
+               osi_Log1(afsd_logp, "GetNewSCache attempting to recycle deleted scp 0x%x", scp);
+               if (!cm_RecycleSCache(scp, CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS)) {
+
+                   /* we found an entry, so return it */
+                   /* now remove from the LRU queue and put it back at the
+                    * head of the LRU queue.
+                    */
+                   cm_AdjustLRU(scp);
+
+                   /* and we're done */
+                   return scp;
+               } 
+               osi_Log1(afsd_logp, "GetNewSCache recycled failed scp 0x%x", scp);
+           } else if (!(scp->flags & CM_SCACHEFLAG_INHASH)) {
                /* we found an entry, so return it */
                /* now remove from the LRU queue and put it back at the
-                * head of the LRU queue.
-                */
+               * head of the LRU queue.
+               */
                cm_AdjustLRU(scp);
 
                /* and we're done */
                return scp;
+           }
+       }       
+    }  
+    osi_Log0(afsd_logp, "GetNewSCache no deleted or recycled entries available for reuse");
+
+    if (cm_data.currentSCaches >= cm_data.maxSCaches) {
+       /* There were no deleted scache objects that we could use.  Try to find
+        * one that simply hasn't been used in a while.
+        */
+       while (1) {
+           for ( scp = cm_data.scacheLRULastp;
+                 scp;
+                 scp = (cm_scache_t *) osi_QPrev(&scp->q)) 
+           {
+               /* It is possible for the refCount to be zero and for there still
+                * to be outstanding dirty buffers.  If there are dirty buffers,
+                * we must not recycle the scp. */
+               if (scp->refCount == 0 && scp->bufReadsp == NULL && scp->bufWritesp == NULL) {
+                   if (!buf_DirtyBuffersExist(&scp->fid)) {
+                       if (!cm_RecycleSCache(scp, 0)) {
+                           /* we found an entry, so return it */
+                           /* now remove from the LRU queue and put it back at the
+                            * head of the LRU queue.
+                            */
+                           cm_AdjustLRU(scp);
+
+                           /* and we're done */
+                           return scp;
+                       }
+                   } else {
+                       osi_Log1(afsd_logp,"GetNewSCache dirty buffers exist scp 0x%x", scp);
+                   }
+               }       
+           }
+           osi_Log1(afsd_logp, "GetNewSCache all scache entries in use (retry = %d)", retry);
+           
+           /* If get here it means that every scache is either in use or has dirty buffers.
+            * We used to panic.  Now we will give up our lock and wait.
+            */
+           if (++retry < 10) {
+               lock_ReleaseWrite(&cm_scacheLock);
+               Sleep(1000);
+               lock_ObtainWrite(&cm_scacheLock);
            } else {
-               /* We don't like this entry, choose another one. */
-               goto start;
+               return NULL;
            }
-        }
+       } /* forever */
     }
         
     /* if we get here, we should allocate a new scache entry.  We either are below
@@ -443,8 +501,13 @@ cm_scache_t *cm_FindSCache(cm_fid_t *fidp)
     cm_scache_t *scp;
 
     hash = CM_SCACHE_HASH(fidp);
-        
-    osi_assert(fidp->cell != 0);
+
+    if (fidp->cell == 0) {
+#ifdef DEBUG
+       DebugBreak();
+#endif
+       return NULL;
+    }
 
     lock_ObtainWrite(&cm_scacheLock);
     for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
@@ -529,7 +592,12 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
             mp = "";
         }
         scp = cm_GetNewSCache();
-         
+       if (scp == NULL) {
+           osi_Log0(afsd_logp,"cm_getSCache unable to obtain *new* scache entry");
+            lock_ReleaseWrite(&cm_scacheLock);
+           return CM_ERROR_WOULDBLOCK;
+       }
+
        lock_ObtainMutex(&scp->mx);
         scp->fid = *fidp;
         scp->volp = cm_data.rootSCachep->volp;
@@ -602,6 +670,12 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
         
     /* now, if we don't have the fid, recycle something */
     scp = cm_GetNewSCache();
+    if (scp == NULL) {
+       osi_Log0(afsd_logp,"cm_getSCache unable to obtain *new* scache entry");
+       lock_ReleaseWrite(&cm_scacheLock);
+       return CM_ERROR_WOULDBLOCK;
+    }
+
     osi_assert(!(scp->flags & CM_SCACHEFLAG_INHASH));
     lock_ObtainMutex(&scp->mx);
     scp->fid = *fidp;
@@ -898,7 +972,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req
         // yj: modified this so that callback only checked if we're
         // not checking something on /afs
         /* fix the conditional to match the one in cm_HaveCallback */
-        if (  (flags & CM_SCACHESYNC_NEEDCALLBACK)
+        if ((flags & CM_SCACHESYNC_NEEDCALLBACK)
 #ifdef AFS_FREELANCE_CLIENT
              && (!cm_freelanceEnabled || 
                   !(scp->fid.vnode==0x1 && scp->fid.unique==0x1) ||
@@ -912,7 +986,7 @@ long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *userp, cm_req_t *req
                           scp);
                 if (bufLocked) 
                    lock_ReleaseMutex(&bufp->mx);
-                code = cm_GetCallback(scp, userp, reqp, 0);
+                code = cm_GetCallback(scp, userp, reqp, (flags & CM_SCACHESYNC_FORCECB)?1:0);
                 if (bufLocked) {
                     lock_ReleaseMutex(&scp->mx);
                     lock_ObtainMutex(&bufp->mx);
@@ -1086,12 +1160,16 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags)
            osi_QDFree(qdp);
        }
         if (bufp) {
+           int release = 0;
+           if (bufp->cmFlags & CM_BUF_CMFETCHING)
+               release = 1;
             bufp->cmFlags &= ~(CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED);
             if (bufp->flags & CM_BUF_WAITING) {
                 osi_Log2(afsd_logp, "CM SyncOpDone Waking [scp 0x%p] bufp 0x%p", scp, bufp);
                 osi_Wakeup((LONG_PTR) &bufp);
             }
-            buf_Release(bufp);
+           if (release)
+               buf_Release(bufp);
         }
     }
 
@@ -1108,12 +1186,16 @@ void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags)
            osi_QDFree(qdp);
        }
         if (bufp) {
+           int release = 0;
+           if (bufp->cmFlags & CM_BUF_CMSTORING)
+               release = 1;
             bufp->cmFlags &= ~CM_BUF_CMSTORING;
             if (bufp->flags & CM_BUF_WAITING) {
                 osi_Log2(afsd_logp, "CM SyncOpDone Waking [scp 0x%p] bufp 0x%p", scp, bufp);
                 osi_Wakeup((LONG_PTR) &bufp);
             }
-            buf_Release(bufp);
+           if (release)
+               buf_Release(bufp);
         }
     }
 
index 7cb07bc52850110629c35bc2adeac721f51e7bf3..724a62d9e04ab9df08d12ecc870230a9d4e685f7 100644 (file)
@@ -276,6 +276,8 @@ typedef struct cm_scache {
 #define CM_SCACHESYNC_BUFLOCKED                0x80000 /* the buffer is locked */
 #define CM_SCACHESYNC_NOWAIT           0x100000/* don't wait for the state,
                                                 * just fail */
+#define CM_SCACHESYNC_FORCECB          0x200000/* when calling cm_GetCallback()
+                                                 * set the force flag */
 
 /* flags for cm_RecycleSCache  */
 #define CM_SCACHE_RECYCLEFLAG_DESTROY_BUFFERS  0x1
index ee8127cb1d7438c190877a1535756bbe40c694c0..afcc46fa63e6dcf0ba527494566b20371ad41363 100644 (file)
@@ -450,8 +450,8 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp,
     /* First check permissions */
     lock_ObtainMutex(&dscp->mx);
     code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_DELETE,
-                      CM_SCACHESYNC_GETSTATUS
-                      | CM_SCACHESYNC_NEEDCALLBACK);
+                      CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
+    cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     lock_ReleaseMutex(&dscp->mx);
     if (code)
         return code;
@@ -487,6 +487,7 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp,
         lock_ReleaseMutex(&scp->mx);
         lock_ObtainMutex(&bufferp->mx);
         lock_ObtainMutex(&scp->mx);
+       cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ | CM_SCACHESYNC_BUFLOCKED);
         if (code)
             break;
     }
@@ -693,6 +694,7 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
                     lock_ReleaseMutex(&scp->mx);
                     break;
                 }
+               cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ | CM_SCACHESYNC_BUFLOCKED);
                                 
                 if (cm_HaveBuffer(scp, bufferp, 1)) {
                     lock_ReleaseMutex(&scp->mx);
@@ -911,6 +913,8 @@ long cm_ReadMountPoint(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
         if (code) {
             goto done;
         }
+       cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
 
         if (cm_HaveBuffer(scp, bufp, 0)) 
             break;
@@ -1185,6 +1189,7 @@ long cm_LookupInternal(cm_scache_t *dscp, char *namep, long flags, cm_user_t *us
         cm_ReleaseSCache(tscp);
         return code;
     }
+    cm_SyncOpDone(tscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     /* tscp is now locked */
 
     if (!(flags & CM_FLAG_NOMOUNTCHASE)
@@ -1383,6 +1388,8 @@ long cm_HandleLink(cm_scache_t *linkScp, cm_user_t *userp, cm_req_t *reqp)
                 buf_Release(bufp);
                 return code;
             }
+           cm_SyncOpDone(linkScp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
             if (cm_HaveBuffer(linkScp, bufp, 0)) 
                 break;
 
@@ -1636,6 +1643,8 @@ long cm_NameI(cm_scache_t *rootSCachep, char *pathp, long flags,
                     }
                     break;
                 }
+               cm_SyncOpDone(tscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
                 if (tscp->fileType == CM_SCACHETYPE_SYMLINK) {
                     /* this is a symlink; assemble a new buffer */
                     lock_ReleaseMutex(&tscp->mx);
@@ -2105,7 +2114,8 @@ long cm_SetLength(cm_scache_t *scp, osi_hyper_t *sizep, cm_user_t *userp,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code) 
         goto done;
-        
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     if (scp->fileType != CM_SCACHETYPE_FILE) {
         code = CM_ERROR_ISDIR;
         goto done;
@@ -2164,6 +2174,10 @@ long cm_SetLength(cm_scache_t *scp, osi_hyper_t *sizep, cm_user_t *userp,
     /* done successfully */
     code = 0;
 
+    cm_SyncOpDone(scp, NULL, 
+                  CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS
+                  | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_SETSIZE);
+
   done:
     lock_ReleaseMutex(&scp->mx);
     lock_ReleaseWrite(&scp->bufCreateLock);
@@ -2176,7 +2190,6 @@ long cm_SetAttr(cm_scache_t *scp, cm_attr_t *attrp, cm_user_t *userp,
                 cm_req_t *reqp)
 {
     long code;
-    int flags;
     AFSFetchStatus afsOutStatus;
     AFSVolSync volSync;
     cm_conn_t *connp;
@@ -2188,8 +2201,6 @@ long cm_SetAttr(cm_scache_t *scp, cm_attr_t *attrp, cm_user_t *userp,
     if (attrp->mask & CM_ATTRMASK_LENGTH)
         return cm_SetLength(scp, &attrp->length, userp, reqp);
 
-    flags = CM_SCACHESYNC_STORESTATUS;
-
     lock_ObtainMutex(&scp->mx);
     /* otherwise, we have to make an RPC to get the status */
     code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_STORESTATUS);
@@ -3511,6 +3522,8 @@ long cm_LockCheckPerms(cm_scache_t * scp,
            osi_Log0(afsd_logp, "cm_LockCheckPerms user is creator but has no INSERT bits for scp");
     }
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     osi_Log1(afsd_logp, "cm_LockCheckPerms returning code %d", code);
 
     return code;
index bf19b0291a4f8f9c69e852f8ac4bfc1cdf0bec44..800e811bcf385ce8b5dbea3bcb6d5de6fd380bd0 100644 (file)
@@ -41,6 +41,8 @@ long ReadData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
     if (code) 
         goto done;
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     /* now we have the entry locked, look up the length */
     fileLength = scp->length;
 
@@ -98,6 +100,8 @@ long ReadData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
                 if (code) 
                     goto done;
 
+               cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
                 if (cm_HaveBuffer(scp, bufferp, 0)) break;
 
                 /* otherwise, load the buffer and try again */
@@ -177,6 +181,8 @@ long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
     if (code) 
         goto done;
     
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS);
+
 #if 0
     /* make sure we have a writable FD */
     if (!(fidp->flags & SMB_FID_OPENWRITE)) {
@@ -260,7 +266,12 @@ long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
                                   | CM_SCACHESYNC_BUFLOCKED);
                 if (code) 
                     goto done;
-                                
+                       
+               cm_SyncOpDone(scp, bufferp, 
+                              CM_SCACHESYNC_NEEDCALLBACK 
+                              | CM_SCACHESYNC_WRITE 
+                              | CM_SCACHESYNC_BUFLOCKED);
+
                 /* If we're overwriting the entire buffer, or
                  * if we're writing at or past EOF, mark the
                  * buffer as current so we don't call
@@ -358,8 +369,9 @@ long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
         lock_ReleaseMutex(&scp->mx);
         cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
                             writeBackOffset.HighPart, cm_chunkSize, 0, userp);
-    }       
+    }   
 
+    /* cm_SyncOpDone is called when cm_BkgStore completes */
     return code;
 }
 
index fddf723595f95970b3c085af8ad2d78234cbd9d4..c1742eb8cad01457137f55a6e40fe3c38b7eb3e3 100644 (file)
@@ -184,7 +184,9 @@ void smb_ResetServerPriority()
 
 void smb_SetRequestStartTime()
 {
-    time_t * tp = malloc(sizeof(time_t));
+    time_t * tp = TlsGetValue(smb_TlsRequestSlot);
+    if (!tp)
+       tp = malloc(sizeof(time_t));
     if (tp) {
        *tp = osi_Time();
 
@@ -1051,7 +1053,16 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
     smb_tid_t *tidp;
 
     lock_ObtainWrite(&smb_rctLock);
+  retry:
     for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+       if (tidp->refCount == 0 && tidp->delete) {
+           tidp->refCount++;
+           lock_ReleaseWrite(&smb_rctLock);
+           smb_ReleaseTID(tidp);
+           lock_ObtainWrite(&smb_rctLock);
+           goto retry;
+       }
+
         if (tid == tidp->tid) {
             tidp->refCount++;
             break;
@@ -1356,6 +1367,13 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
 
   retry:
     for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+       if (fidp->refCount == 0 && fidp->delete) {
+           fidp->refCount++;
+           lock_ReleaseWrite(&smb_rctLock);
+           smb_ReleaseFID(fidp);
+           lock_ObtainWrite(&smb_rctLock);
+           goto retry;
+       }
         if (fid == fidp->fid) {
             if (newFid) {
                 fid++;
@@ -3683,6 +3701,8 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
             continue;
         }
 
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
         attr = smb_Attributes(scp);
         /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
         if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
@@ -3931,6 +3951,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         return code;
     }
         
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     dirLength = scp->length;
     bufferp = NULL;
     bufferOffset.LowPart = bufferOffset.HighPart = 0;
@@ -4037,6 +4059,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                     break;
                 }
                                 
+               cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
                 if (cm_HaveBuffer(scp, bufferp, 0)) {
                     osi_Log2(smb_logp, "SMB search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
                     break;
@@ -4212,7 +4236,10 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
     /* release the mutex */
     lock_ReleaseMutex(&scp->mx);
-    if (bufferp) buf_Release(bufferp);
+    if (bufferp) {
+       buf_Release(bufferp);
+       bufferp = NULL;
+    }
 
     /* apply and free last set of patches; if not doing a star match, this
      * will be empty, but better safe (and freeing everything) than sorry.
@@ -4317,11 +4344,15 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     lock_ObtainMutex(&newScp->mx);
     code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
                      CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
-    if (code && code != CM_ERROR_NOACCESS) {
-        lock_ReleaseMutex(&newScp->mx);
-        cm_ReleaseSCache(newScp);
-        cm_ReleaseUser(userp);
-        return code;
+    if (code) {
+       if (code != CM_ERROR_NOACCESS) {
+           lock_ReleaseMutex(&newScp->mx);
+           cm_ReleaseSCache(newScp);
+           cm_ReleaseUser(userp);
+           return code;
+       }
+    } else {
+       cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     }
 
     attrs = smb_Attributes(newScp);
@@ -4410,6 +4441,8 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         return code;
     }
 
+    cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     /* Check for RO volume */
     if (newScp->flags & CM_SCACHEFLAG_RO) {
         lock_ReleaseMutex(&newScp->mx);
@@ -4529,9 +4562,10 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                 code = CM_ERROR_NOSUCHFILE;
             else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
                 cm_buf_t *bp = buf_Find(dscp, &hzero);
-                if (bp)
+                if (bp) {
                     buf_Release(bp);
-                else
+                   bp = NULL;
+               } else
                     code = CM_ERROR_NOSUCHFILE;
             }
             cm_ReleaseSCache(dscp);
@@ -4572,6 +4606,8 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         return code;
     }
 
+    cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
 #ifdef undef
     /* use smb_Attributes instead.   Also the fact that a file is 
      * in a readonly volume doesn't mean it shojuld be marked as RO 
@@ -5652,7 +5688,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
 
         cm_UnlockByKey(scp, key, CM_UNLOCK_BY_FID, userp, &req);
 
-        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
 
     post_syncopdone:
 
@@ -5667,16 +5703,22 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
         smb_FullName(dscp, scp, pathp, &fullPathp, userp, &req);
         if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
             code = cm_RemoveDir(dscp, fullPathp, userp, &req);
-            if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                smb_NotifyChange(FILE_ACTION_REMOVED,
-                                 FILE_NOTIFY_CHANGE_DIR_NAME,
-                                 dscp, fullPathp, NULL, TRUE);
+           if (code == 0) {
+               scp->flags |= CM_SCACHEFLAG_DELETED;
+               if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+                   smb_NotifyChange(FILE_ACTION_REMOVED,
+                                     FILE_NOTIFY_CHANGE_DIR_NAME,
+                                     dscp, fullPathp, NULL, TRUE);
+           }
         } else {
             code = cm_Unlink(dscp, fullPathp, userp, &req);
-            if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                smb_NotifyChange(FILE_ACTION_REMOVED,
-                                 FILE_NOTIFY_CHANGE_FILE_NAME,
-                                 dscp, fullPathp, NULL, TRUE);
+           if (code == 0) {                            
+               scp->flags |= CM_SCACHEFLAG_DELETED;
+               if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+                   smb_NotifyChange(FILE_ACTION_REMOVED,
+                                     FILE_NOTIFY_CHANGE_FILE_NAME,
+                                     dscp, fullPathp, NULL, TRUE);
+           }
         }
         free(fullPathp);
        lock_ObtainMutex(&fidp->mx);
@@ -5760,7 +5802,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     osi_hyper_t bufferOffset;
     long bufIndex, nbytes;
     int chunk;
-    int sequential = 0;
+    int sequential = (fidp->flags & SMB_FID_SEQUENTIAL);
     cm_req_t req;
 
     cm_InitReq(&req);
@@ -5778,7 +5820,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
             fidp->prev_chunk = fidp->curr_chunk;
             fidp->curr_chunk = chunk;
         }
-        if (fidp->curr_chunk == fidp->prev_chunk + 1)
+        if (!(fidp->flags & SMB_FID_RANDOM) && (fidp->curr_chunk == fidp->prev_chunk + 1))
             sequential = 1;
     }
     lock_ReleaseMutex(&fidp->mx);
@@ -5786,7 +5828,10 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     /* start by looking up the file's end */
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-    if (code) goto done;
+    if (code) 
+       goto done;
+
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
     /* now we have the entry locked, look up the length */
     fileLength = scp->length;
@@ -5842,8 +5887,11 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 code = cm_SyncOp(scp, bufferp, userp, &req, 0,
                                  CM_SCACHESYNC_NEEDCALLBACK |
                                  CM_SCACHESYNC_READ);
-                if (code) goto done;
-                                
+                if (code) 
+                   goto done;
+                    
+               cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
                 if (cm_HaveBuffer(scp, bufferp, 0)) break;
 
                 /* otherwise, load the buffer and try again */
@@ -5879,7 +5927,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
   done:
     lock_ReleaseMutex(&scp->mx);
-    if (bufferp) 
+    if (bufferp)
         buf_Release(bufferp);
 
     if (code == 0 && sequential)
@@ -5945,6 +5993,8 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     if (code) 
         goto done;
         
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS);
+
     /* now we have the entry locked, look up the length */
     fileLength = scp->length;
     minLength = fileLength;
@@ -6022,6 +6072,11 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 if (code) 
                     goto done;
 
+               cm_SyncOpDone(scp, bufferp, 
+                              CM_SCACHESYNC_NEEDCALLBACK 
+                              | CM_SCACHESYNC_WRITE 
+                              | CM_SCACHESYNC_BUFLOCKED);
+
                 /* If we're overwriting the entire buffer, or
                  * if we're writing at or past EOF, mark the
                  * buffer as current so we don't call
@@ -6126,6 +6181,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
         lock_ReleaseMutex(&scp->mx);
         cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
                             writeBackOffset.HighPart, cm_chunkSize, 0, userp);
+       /* cm_SyncOpDone is called at the completion of cm_BkgStore */
     }
 
     cm_ReleaseSCache(scp);
@@ -6940,6 +6996,7 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code == 0) {
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         if (whence == 1) {
             /* offset from current offset */
             new_offset = LargeIntegerAdd(fidp->offset,
index b14053965d01413da8b3a1cb062dbec755de163f..60cadfe59a84a9cdd0661fd5c39ffae40a6c1dd0 100644 (file)
@@ -385,6 +385,8 @@ typedef struct smb_fid {
 #define SMB_FID_MTIMESETDONE           0x80    /* have set modtime via Tr2 */
 #define SMB_FID_LOOKSLIKECOPY  (SMB_FID_LENGTHSETDONE | SMB_FID_MTIMESETDONE)
 #define SMB_FID_NTOPEN                 0x100   /* have dscp and pathp */
+#define SMB_FID_SEQUENTIAL             0x200
+#define SMB_FID_RANDOM                 0x400
 
 #define SMB_FID_SHARE_READ              0x1000
 #define SMB_FID_SHARE_WRITE             0x2000
index 01c86e4524b81d00eeb8521f62d8686d76241270..74f28601087243297afec493f0a2d8570c379f5a 100644 (file)
@@ -2806,6 +2806,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code) goto done;
+
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         
     /* now we have the status in the cache entry, and everything is locked.
      * Marshall the output data.
@@ -3081,11 +3083,13 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
                           CM_SCACHESYNC_GETSTATUS
                          | CM_SCACHESYNC_NEEDCALLBACK);
-       lock_ReleaseMutex(&scp->mx);
         if (code) {
+           lock_ReleaseMutex(&scp->mx);
             goto done;
         }
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
+       lock_ReleaseMutex(&scp->mx);
        lock_ObtainMutex(&fidp->mx);
        lock_ObtainMutex(&scp->mx);
 
@@ -3212,6 +3216,8 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     if (code) 
         goto done;
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     /* now we have the status in the cache entry, and everything is locked.
      * Marshall the output data.
      */
@@ -3350,10 +3356,14 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
                           CM_SCACHESYNC_GETSTATUS
                          | CM_SCACHESYNC_NEEDCALLBACK);
-       lock_ReleaseMutex(&scp->mx);
-        if (code)
+        if (code) {
+           lock_ReleaseMutex(&scp->mx);
             goto done;
+       }
+
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
+       lock_ReleaseMutex(&scp->mx);
        lock_ObtainMutex(&fidp->mx);
        lock_ObtainMutex(&scp->mx);
 
@@ -3710,7 +3720,9 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
             }
             continue;
         }
-                
+        
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
         /* now watch for a symlink */
         code = 0;
         while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
@@ -4367,6 +4379,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         return code;
     }
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
   startsearch:
     dirLength = scp->length;
     bufferp = NULL;
@@ -4484,7 +4498,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                     osi_Log2(smb_logp, "T2 search dir cm_SyncOp scp %x failed %d", scp, code);
                     break;
                 }
-                                
+                       
+               cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
                 if (cm_HaveBuffer(scp, bufferp, 0)) {
                     osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
                     break;
@@ -4750,8 +4766,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     /* release the mutex */
     lock_ReleaseMutex(&scp->mx);
-    if (bufferp) 
+    if (bufferp) {
         buf_Release(bufferp);
+       bufferp = NULL;
+    }
 
     /* apply and free last set of patches; if not doing a star match, this
      * will be empty, but better safe (and freeing everything) than sorry.
@@ -5471,6 +5489,8 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     if (code) 
        goto done;
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     /* decode times.  We need a search time, but the response to this
      * call provides the date first, not the time, as returned in the
      * searchTime variable.  So we take the high-order bits first.
@@ -6044,6 +6064,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         fidflags |= SMB_FID_OPENWRITE;
     if (createOptions & FILE_DELETE_ON_CLOSE)
         fidflags |= SMB_FID_DELONCLOSE;
+    if (createOptions & FILE_SEQUENTIAL_ONLY && !(createOptions & FILE_RANDOM_ACCESS))
+       fidflags | SMB_FID_SEQUENTIAL;
+    if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
+       fidflags & SMB_FID_RANDOM;
 
     /* and the share mode */
     if (shareAccess & FILE_SHARE_READ)
@@ -6788,6 +6812,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         fidflags |= SMB_FID_OPENWRITE;
     if (createOptions & FILE_DELETE_ON_CLOSE)
         fidflags |= SMB_FID_DELONCLOSE;
+    if (createOptions & FILE_SEQUENTIAL_ONLY && !(createOptions & FILE_RANDOM_ACCESS))
+       fidflags | SMB_FID_SEQUENTIAL;
+    if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
+       fidflags & SMB_FID_RANDOM;
 
     /* And the share mode */
     if (shareAccess & FILE_SHARE_READ)