return 0;
}
-/* stabilize scache entry, and return with it locked so
- * it stays stable.
+/*
+ * stabilize scache entry with CM_SCACHESYNC_SETSIZE. This prevents any new
+ * data buffers to be allocated, new data to be fetched from the file server,
+ * and writes to be accepted from the application but permits dirty buffers
+ * to be written to the file server.
+ *
+ * Stabilize uses cm_SyncOp to maintain the cm_scache_t in this stable state
+ * instead of holding the rwlock exclusively. This permits background stores
+ * to be performed in parallel and in particular allow FlushFile to be
+ * implemented without violating the locking hierarchy.
*/
long cm_BufStabilize(void *vscp, cm_user_t *userp, cm_req_t *reqp)
{
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_SETSIZE);
- if (code) {
- lock_ReleaseWrite(&scp->rw);
- return code;
- }
-
- return 0;
+ lock_ReleaseWrite(&scp->rw);
+
+ return code;
}
/* undoes the work that cm_BufStabilize does: releases lock so things can change again */
{
cm_scache_t *scp = vscp;
+ lock_ObtainWrite(&scp->rw);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_SETSIZE);
lock_ReleaseWrite(&scp->rw);
* operation ran first, or even which order a read and
* a write occurred in.
*/
- if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING
- | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) {
- osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING|GETCALLBACK want FETCHSTATUS", scp);
+ if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING | CM_SCACHEFLAG_SIZESETTING |
+ CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) {
+ osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESETTING|SIZESTORING|GETCALLBACK want FETCHSTATUS", scp);
goto sleep;
}
}
/* if we're going to make an RPC to change the status, make sure
* that no one is bringing in or sending out the status.
*/
- if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING |
+ if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING | CM_SCACHEFLAG_SIZESETTING |
CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) {
- osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING|GETCALLBACK want STORESIZE|STORESTATUS|SETSIZE|GETCALLBACK", scp);
+ osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESETTING|SIZESTORING|GETCALLBACK want STORESIZE|STORESTATUS|SETSIZE|GETCALLBACK", scp);
goto sleep;
}
if ((!bufp || bufp && scp->fileType == CM_SCACHETYPE_FILE) &&
* nothing is happening to that chunk, and that we aren't
* changing the basic file status info, either.
*/
- if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING
- | CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) {
- osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING|GETCALLBACK want FETCHDATA", scp);
+ if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING | CM_SCACHEFLAG_SIZESETTING |
+ CM_SCACHEFLAG_SIZESTORING | CM_SCACHEFLAG_GETCALLBACK)) {
+ osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESETTING|SIZESTORING|GETCALLBACK want FETCHDATA", scp);
goto sleep;
}
if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING | CM_BUF_CMWRITING))) {
* operations don't change any of the data that we're
* changing here.
*/
- if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING | CM_SCACHEFLAG_SIZESTORING)) {
- osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING want SETSTATUS", scp);
+ if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING |
+ CM_SCACHEFLAG_SIZESETTING | CM_SCACHEFLAG_SIZESTORING)) {
+ osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESETTING|SIZESTORING want SETSTATUS", scp);
goto sleep;
}
}
/* don't write unless the status is stable and the chunk
* is stable.
*/
- if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING
- | CM_SCACHEFLAG_SIZESTORING)) {
- osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESTORING want WRITE", scp);
+ if (scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING | CM_SCACHEFLAG_SIZESETTING |
+ CM_SCACHEFLAG_SIZESTORING)) {
+ osi_Log1(afsd_logp, "CM SyncOp scp 0x%p is FETCHING|STORING|SIZESETTING|SIZESTORING want WRITE", scp);
goto sleep;
}
if (bufp && (bufp->cmFlags & (CM_BUF_CMFETCHING |
scp->flags |= CM_SCACHEFLAG_FETCHING;
if (flags & CM_SCACHESYNC_STORESTATUS)
scp->flags |= CM_SCACHEFLAG_STORING;
+ if (flags & CM_SCACHESYNC_SETSIZE)
+ scp->flags |= CM_SCACHEFLAG_SIZESETTING;
if (flags & CM_SCACHESYNC_STORESIZE)
scp->flags |= CM_SCACHEFLAG_SIZESTORING;
if (flags & CM_SCACHESYNC_GETCALLBACK)
scp->flags &= ~CM_SCACHEFLAG_FETCHING;
if (flags & CM_SCACHESYNC_STORESTATUS)
scp->flags &= ~CM_SCACHEFLAG_STORING;
+ if (flags & CM_SCACHESYNC_SETSIZE)
+ scp->flags &= ~CM_SCACHEFLAG_SIZESETTING;
if (flags & CM_SCACHESYNC_STORESIZE)
scp->flags &= ~CM_SCACHEFLAG_SIZESTORING;
if (flags & CM_SCACHESYNC_GETCALLBACK)