From 500ffccfd66123c74a0d32c04801e5906f58e58a Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 2 Dec 2011 11:21:46 -0500 Subject: [PATCH] Windows: buf_GetNewLocked should use cleaned cm_buf 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 Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/cm_buf.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index c0130ac9c..ac402f5f8 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -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", -- 2.39.5