Windows: buf_GetNewLocked should use cleaned cm_buf
authorJeffrey Altman <jaltman@your-file-system.com>
Fri, 2 Dec 2011 16:21:46 +0000 (11:21 -0500)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 2 Dec 2011 23:53:39 +0000 (15:53 -0800)
buf_GetNewLocked() searches the free buffer list for a buffer
that has a 0 refcnt, is not in the chunk that is being populated,
is not actively having I/O performed on it and is not dirty.
If it comes across a dirty buffer, it calls buf_Clean() with
the assumption that buf_CleanAsync() (as it was previously called)
was in fact asynchronous and would return immediately.  Instead
buf_Clean() is synchronous and when it completes the buffer will
in most cases be clean.  buf_GetNewLocked() should use the newly
cleaned buffer if it is still available and not continue the
search from the next entry in the free buffer list.

Change-Id: Iae629df57b9d27a813f7f4c6740be23bd33fe039
Reviewed-on: http://gerrit.openafs.org/6174
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@secure-endpoints.com>
Tested-by: Jeffrey Altman <jaltman@secure-endpoints.com>

src/WINNT/afsd/cm_buf.c

index c0130ac..ac402f5 100644 (file)
@@ -1321,8 +1321,11 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
          * a clean buffer, we rehash it, lock it and return it.
          */
         for (bp = cm_data.buf_freeListEndp; bp; bp=(cm_buf_t *) osi_QPrev(&bp->q)) {
+            int cleaned = 0;
+
             n_bufs++;
 
+          retry_2:
             /* check to see if it really has zero ref count.  This
              * code can bump refcounts, at least, so it may not be
              * zero.
@@ -1366,6 +1369,10 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
                 if (bp->qFlags & CM_BUF_QREDIR)
                     continue;
 
+                /* protect against cleaning the same buffer more than once. */
+                if (cleaned)
+                    continue;
+
                 /* if the buffer is dirty, start cleaning it and
                  * move on to the next buffer.  We do this with
                  * just the lock required to minimize contention
@@ -1405,7 +1412,16 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_req_t *req
                     lock_ReleaseRead(&scp->bufCreateLock);
                     return CM_BUF_EXISTS;
                 }
-                continue;
+
+                /*
+                 * We just cleaned this buffer so we need to
+                 * restart the loop with this buffer so it
+                 * can be retested.  Set 'cleaned' so we
+                 * do not attempt another call to buf_Clean()
+                 * if the prior attempt failed.
+                 */
+                cleaned = 1;
+                goto retry_2;
             }
 
             osi_Log3(afsd_logp, "buf_GetNewLocked: scp 0x%p examined %u buffers before recycling bufp 0x%p",