Windows: Add flag BUF_GET_FLAG_BUFCREATE_LOCKED
authorJeffrey Altman <jaltman@your-file-system.com>
Fri, 25 Jan 2013 07:21:27 +0000 (02:21 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Sat, 23 Feb 2013 08:21:34 +0000 (00:21 -0800)
Modify the buf_Get() and buf_GetNewLocked() interfaces to
permit the cm_scache.bufCreateLocked lock to be held prior to
calling to buf_Get().  Holding the cm_scache.bufCreateLocked lock
before the buf_Get() call prevents a race with another thread
that attempts to set the file size.

Change-Id: I54b13c83801a4d9a2078552d5be7ada6f4607850
Reviewed-on: http://gerrit.openafs.org/9209
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_buf.h
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_dir.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/rawops.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb3.c
src/WINNT/afsrdr/user/RDRFunction.c

index bea6608..0a5a3d2 100644 (file)
@@ -1258,12 +1258,14 @@ buf_ExistsLocked(struct cm_scache *scp, osi_hyper_t *offsetp)
  * space from the buffer pool.  In that case, the buffer will be returned
  * without being hashed into the hash table.
  */
-long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, cm_buf_t **bufpp)
+long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp,
+                      afs_uint32 flags, cm_buf_t **bufpp)
 {
     cm_buf_t *bp;      /* buffer we're dealing with */
     cm_buf_t *nextBp;  /* next buffer in file hash chain */
     afs_uint32 i;      /* temp */
     afs_uint64 n_bufs, n_nonzero, n_busy, n_dirty, n_own, n_redir;
+    int bufCreateLocked = !!(flags & BUF_GET_FLAG_BUFCREATE_LOCKED);
 
 #ifdef TESTING
     buf_ValidateBufQueues();
@@ -1278,12 +1280,14 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
         n_dirty = 0;
         n_redir = 0;
 
-        lock_ObtainRead(&scp->bufCreateLock);
+        if (!bufCreateLocked)
+            lock_ObtainRead(&scp->bufCreateLock);
         lock_ObtainWrite(&buf_globalLock);
         /* check to see if we lost the race */
         if (buf_ExistsLocked(scp, offsetp)) {
             lock_ReleaseWrite(&buf_globalLock);
-            lock_ReleaseRead(&scp->bufCreateLock);
+            if (!bufCreateLocked)
+                lock_ReleaseRead(&scp->bufCreateLock);
             return CM_BUF_EXISTS;
         }
 
@@ -1291,7 +1295,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
        if (!cm_data.buf_freeListEndp)
        {
            lock_ReleaseWrite(&buf_globalLock);
-            lock_ReleaseRead(&scp->bufCreateLock);
+            if (!bufCreateLocked)
+                lock_ReleaseRead(&scp->bufCreateLock);
 
             if ( RDR_Initialized )
                 goto rdr_release;
@@ -1375,7 +1380,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
                  */
                 buf_HoldLocked(bp);
                 lock_ReleaseWrite(&buf_globalLock);
-                lock_ReleaseRead(&scp->bufCreateLock);
+                if (!bufCreateLocked)
+                    lock_ReleaseRead(&scp->bufCreateLock);
 
                 /*
                  * grab required lock and clean.
@@ -1395,7 +1401,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
 
                 /* but first obtain the locks we gave up
                  * before the buf_CleanAsync() call */
-                lock_ObtainRead(&scp->bufCreateLock);
+                if (!bufCreateLocked)
+                    lock_ObtainRead(&scp->bufCreateLock);
                 lock_ObtainWrite(&buf_globalLock);
 
                 /*
@@ -1404,7 +1411,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
                  */
                 if (buf_ExistsLocked(scp, offsetp)) {
                     lock_ReleaseWrite(&buf_globalLock);
-                    lock_ReleaseRead(&scp->bufCreateLock);
+                    if (!bufCreateLocked)
+                        lock_ReleaseRead(&scp->bufCreateLock);
                     return CM_BUF_EXISTS;
                 }
 
@@ -1488,7 +1496,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
                 buf_IncrementUsedCount();
 
             lock_ReleaseWrite(&buf_globalLock);
-            lock_ReleaseRead(&scp->bufCreateLock);
+            if (!bufCreateLocked)
+                lock_ReleaseRead(&scp->bufCreateLock);
 
             *bufpp = bp;
 
@@ -1498,7 +1507,8 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
             return 0;
         } /* for all buffers in lru queue */
         lock_ReleaseWrite(&buf_globalLock);
-        lock_ReleaseRead(&scp->bufCreateLock);
+        if (!bufCreateLocked)
+            lock_ReleaseRead(&scp->bufCreateLock);
 
        osi_Log2(afsd_logp, "buf_GetNewLocked: Free Buffer List has %u buffers none free; redir %u", n_bufs, n_redir);
         osi_Log4(afsd_logp, "... nonzero %u; own %u; busy %u; dirty %u", n_nonzero, n_own, n_busy, n_dirty);
@@ -1527,7 +1537,7 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
  *
  * The scp must be unlocked when passed in unlocked.
  */
-long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, cm_buf_t **bufpp)
+long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, afs_uint32 flags, cm_buf_t **bufpp)
 {
     cm_buf_t *bp;
     long code;
@@ -1561,7 +1571,7 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *reqp, cm_buf
         }
 
         /* otherwise, we have to create a page */
-        code = buf_GetNewLocked(scp, &pageOffset, reqp, &bp);
+        code = buf_GetNewLocked(scp, &pageOffset, reqp, flags, &bp);
         switch (code) {
         case 0:
             /* the requested buffer was created */
index 1243c22..a316cb1 100644 (file)
@@ -170,9 +170,11 @@ extern cm_buf_t *buf_FindAllLocked(struct cm_fid *, osi_hyper_t *, afs_uint32 fl
 
 extern cm_buf_t *buf_FindAll(struct cm_fid *, osi_hyper_t *, afs_uint32 flags);
 
-extern long buf_GetNewLocked(struct cm_scache *, osi_hyper_t *, cm_req_t *, cm_buf_t **);
+extern long buf_GetNewLocked(struct cm_scache *, osi_hyper_t *, cm_req_t *, afs_uint32, cm_buf_t **);
 
-extern long buf_Get(struct cm_scache *, osi_hyper_t *, cm_req_t *, cm_buf_t **);
+extern long buf_Get(struct cm_scache *, osi_hyper_t *, cm_req_t *, afs_uint32, cm_buf_t **);
+
+#define BUF_GET_FLAG_BUFCREATE_LOCKED   1
 
 extern afs_uint32 buf_CleanLocked(cm_scache_t *, cm_buf_t *, cm_req_t *, afs_uint32 flags, afs_uint32 *);
 
index 873e792..aff45e5 100644 (file)
@@ -879,7 +879,7 @@ cm_BkgPrefetch(cm_scache_t *scp, void *rockp, cm_user_t *userp, cm_req_t *reqp)
             rxheld = 0;
         }
 
-        code = buf_Get(scp, &offset, reqp, &bp);
+        code = buf_Get(scp, &offset, reqp, 0, &bp);
         if (code)
             break;
 
@@ -1324,7 +1324,7 @@ long cm_SetupFetchBIOD(cm_scache_t *scp, osi_hyper_t *offsetp,
         if (LargeIntegerGreaterThanOrEqualTo(pageBase, fileSize))
             break;
 
-        code = buf_Get(scp, &pageBase, reqp, &tbp);
+        code = buf_Get(scp, &pageBase, reqp, 0, &tbp);
         if (code) {
             lock_ObtainWrite(&scp->rw);
             cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
index 534b85f..7430bd4 100644 (file)
@@ -1538,7 +1538,7 @@ cm_DirPrefetchBuffers(cm_dirOp_t * op)
                  offset.HighPart, offset.LowPart);
         lock_ReleaseWrite(&op->scp->rw);
 
-        code = buf_Get(op->scp, &offset, &op->req, &bufferp);
+        code = buf_Get(op->scp, &offset, &op->req, 0, &bufferp);
 
         lock_ObtainWrite(&op->scp->rw);
 
@@ -1685,7 +1685,7 @@ cm_DirGetPage(cm_dirOp_t * op,
             goto _has_buffer;
         }
 
-        code = buf_Get(op->scp, &bufferOffset, &op->req, &bufferp);
+        code = buf_Get(op->scp, &bufferOffset, &op->req, 0, &bufferp);
         if (code) {
             osi_Log1(afsd_logp, "    buf_Get returned code 0x%x", code);
             bufferp = NULL;
index 84446ee..5122894 100644 (file)
@@ -360,7 +360,7 @@ long cm_CheckNTDelete(cm_scache_t *dscp, cm_scache_t *scp, cm_user_t *userp,
         return code;
 
     thyper.HighPart = 0; thyper.LowPart = 0;
-    code = buf_Get(scp, &thyper, reqp, &bufferp);
+    code = buf_Get(scp, &thyper, reqp, 0, &bufferp);
     if (code)
         return code;
 
@@ -603,7 +603,7 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
                 bufferp = NULL;
             }
 
-            code = buf_Get(scp, &thyper, reqp, &bufferp);
+            code = buf_Get(scp, &thyper, reqp, 0, &bufferp);
             if (code) {
                 /* if buf_Get() fails we do not have a buffer object to lock */
                 bufferp = NULL;
index 14f672e..882082e 100644 (file)
@@ -80,7 +80,7 @@ raw_ReadData( cm_scache_t *scp, osi_hyper_t *offsetp,
             }
             lock_ReleaseWrite(&scp->rw);
 
-            code = buf_Get(scp, &thyper, reqp, &bufp);
+            code = buf_Get(scp, &thyper, reqp, 0, &bufp);
 
             lock_ObtainWrite(&scp->rw);
             if (code) goto done;
@@ -211,7 +211,7 @@ raw_WriteData( cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 length, char *
             }
             lock_ReleaseWrite(&scp->rw);
 
-            code = buf_Get(scp, &thyper, reqp, &bufp);
+            code = buf_Get(scp, &thyper, reqp, 0, &bufp);
             if (bufp)
                 lock_ObtainMutex(&bufp->mx);
 
index 31a49a8..651f8ac 100644 (file)
@@ -5124,7 +5124,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                 bufferp = NULL;
             }
             lock_ReleaseWrite(&scp->rw);
-            code = buf_Get(scp, &thyper, &req, &bufferp);
+            code = buf_Get(scp, &thyper, &req, 0, &bufferp);
             lock_ObtainMutex(&dsp->mx);
 
             /* now, if we're doing a star match, do bulk fetching of all of
@@ -7249,7 +7249,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
             }
             lock_ReleaseWrite(&scp->rw);
 
-            code = buf_Get(scp, &thyper, &req, &bufferp);
+            code = buf_Get(scp, &thyper, &req, 0, &bufferp);
 
             lock_ObtainWrite(&scp->rw);
             if (code) goto done;
@@ -7439,7 +7439,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
             }
             lock_ReleaseWrite(&scp->rw);
 
-            code = buf_Get(scp, &thyper, &req, &bufferp);
+            code = buf_Get(scp, &thyper, &req, 0, &bufferp);
 
             lock_ObtainMutex(&bufferp->mx);
             lock_ObtainWrite(&scp->rw);
index d8a956b..290b1e7 100644 (file)
@@ -5903,7 +5903,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 bufferp = NULL;
             }
             lock_ReleaseWrite(&scp->rw);
-            code = buf_Get(scp, &thyper, &req, &bufferp);
+            code = buf_Get(scp, &thyper, &req, 0, &bufferp);
             lock_ObtainWrite(&scp->rw);
             if (code) {
                 osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
index 36894c1..fcc26af 100644 (file)
@@ -3420,7 +3420,7 @@ RDR_BkgFetch(cm_scache_t *scp, void *rockp, cm_user_t *userp, cm_req_t *reqp)
             rwheld = 0;
         }
 
-        code = buf_Get(scp, &offset, reqp, &bufp);
+        code = buf_Get(scp, &offset, reqp, 0, &bufp);
         if (code) {
             /*
              * any error from buf_Get() is non-fatal.
@@ -3657,7 +3657,7 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
         QueueLength = 0;
         thyper.QuadPart = ByteOffset.QuadPart;
 
-        code = buf_Get(scp, &thyper, &req, &bufp);
+        code = buf_Get(scp, &thyper, &req, 0,  &bufp);
         if (code == 0) {
             lock_ObtainMutex(&bufp->mx);
             bBufRelease = TRUE;