Windows: buf_CleanLocked protect against NULL bp->userp
[openafs.git] / src / WINNT / afsd / cm_buf.c
index dd8b8ba..04573d0 100644 (file)
@@ -816,6 +816,23 @@ afs_uint32 buf_CleanLocked(cm_scache_t *scp, cm_buf_t *bp, cm_req_t *reqp,
                      reqp) == 0)
     {
         release_scp = 1;
+
+        lock_ObtainWrite(&scp->rw);
+        code = cm_SyncOp(scp, NULL, bp->userp ? bp->userp : cm_rootUserp, reqp, 0,
+                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        if (code == 0) {
+            cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        }
+        lock_ReleaseWrite(&scp->rw);
+    }
+
+    if (scp && (scp->flags & CM_SCACHEFLAG_DELETED)) {
+        _InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
+        _InterlockedOr(&bp->flags, CM_BUF_ERROR);
+        bp->dirty_length = 0;
+        bp->error = code;
+        bp->dataVersion = CM_BUF_VERSION_BAD;
+        bp->dirtyCounter++;
     }
 
     while ((bp->flags & CM_BUF_DIRTY) == CM_BUF_DIRTY) {
@@ -843,9 +860,8 @@ afs_uint32 buf_CleanLocked(cm_scache_t *scp, cm_buf_t *bp, cm_req_t *reqp,
              * to determine if it is appropriate to fill a full chunk of data
              * when storing to the file server.
              */
-            code = (*cm_buf_opsp->Writep)(scp, &offset,
-                                          bp->dirty_length,
-                                          flags, bp->userp, reqp);
+            code = (*cm_buf_opsp->Writep)(scp, &offset, bp->dirty_length, flags,
+                                          bp->userp ? bp->userp : cm_rootUserp, reqp);
             osi_Log3(buf_logp, "buf_CleanLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
         }
         lock_ObtainMutex(&bp->mx);
@@ -855,10 +871,9 @@ afs_uint32 buf_CleanLocked(cm_scache_t *scp, cm_buf_t *bp, cm_req_t *reqp,
         */
        if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BADFD || code == CM_ERROR_NOACCESS ||
             code == CM_ERROR_QUOTA || code == CM_ERROR_SPACE || code == CM_ERROR_TOOBIG ||
-            code == CM_ERROR_READONLY || code == CM_ERROR_NOSUCHPATH){
+            code == CM_ERROR_READONLY || code == CM_ERROR_NOSUCHPATH || code == EIO){
            _InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
            _InterlockedOr(&bp->flags, CM_BUF_ERROR);
-            bp->dirty_offset = 0;
             bp->dirty_length = 0;
            bp->error = code;
            bp->dataVersion = CM_BUF_VERSION_BAD;
@@ -1686,6 +1701,7 @@ void buf_SetDirty(cm_buf_t *bp, cm_req_t *reqp, afs_uint32 offset, afs_uint32 le
 {
     osi_assertx(bp->magic == CM_BUF_MAGIC, "invalid cm_buf_t magic");
     osi_assertx(bp->refCount > 0, "cm_buf_t refcount 0");
+    osi_assertx(userp != NULL, "userp is NULL");
 
     if (length == 0)
         return;
@@ -1968,7 +1984,6 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
                 }
                 _InterlockedAnd(&bufp->flags, ~CM_BUF_DIRTY);
                 bufp->error = 0;
-                bufp->dirty_offset = 0;
                 bufp->dirty_length = 0;
                 bufp->dataVersion = CM_BUF_VERSION_BAD;        /* known bad */
                 bufp->dirtyCounter++;
@@ -2066,7 +2081,6 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
                 _InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
                 _InterlockedOr(&bp->flags, CM_BUF_ERROR);
                 bp->error = CM_ERROR_BADFD;
-                bp->dirty_offset = 0;
                 bp->dirty_length = 0;
                 bp->dataVersion = CM_BUF_VERSION_BAD;  /* known bad */
                 bp->dirtyCounter++;
@@ -2237,6 +2251,7 @@ long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
                 case CM_ERROR_TOOBIG:
                 case CM_ERROR_READONLY:
                 case CM_ERROR_NOSUCHPATH:
+                case EIO:
                     /*
                      * Apply the previous fatal error to this buffer.
                      * Do not waste the time attempting to store to
@@ -2244,7 +2259,6 @@ long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
                      */
                     _InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
                     _InterlockedOr(&bp->flags, CM_BUF_ERROR);
-                    bp->dirty_offset = 0;
                     bp->dirty_length = 0;
                     bp->error = code;
                     bp->dataVersion = CM_BUF_VERSION_BAD;
@@ -2439,7 +2453,7 @@ long buf_DirtyBuffersExist(cm_fid_t *fidp)
         }
     }
     lock_ReleaseRead(&buf_globalLock);
-    return 0;
+    return found;
 }
 
 long buf_RDRBuffersExist(cm_fid_t *fidp)
@@ -2521,7 +2535,6 @@ long buf_CleanDirtyBuffers(cm_scache_t *scp)
            lock_ObtainMutex(&bp->mx);
            _InterlockedAnd(&bp->cmFlags, ~CM_BUF_CMSTORING);
            _InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
-            bp->dirty_offset = 0;
             bp->dirty_length = 0;
            _InterlockedOr(&bp->flags, CM_BUF_ERROR);
            bp->error = VNOVNODE;