osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */
DWORD filter = 0;
cm_req_t req;
+ int needSyncOpDone = 0;
osi_Log3(smb_logp, "smb_WriteData fid %d, off 0x%x, size 0x%x",
fidp->fid, offsetp->LowPart, count);
/* now, copy the data one buffer at a time, until we've filled the
* request packet */
- while (1) {
- /* if we've copied all the data requested, we're done */
- if (count <= 0)
- break;
+ while (count != 0) {
/* handle over quota or out of space */
if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
if (bufferp) {
+ if (needSyncOpDone) {
+ cm_SyncOpDone(scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ needSyncOpDone = 0;
+ }
lock_ReleaseMutex(&bufferp->mx);
buf_Release(bufferp);
bufferp = NULL;
bufferOffset = thyper;
/* now get the data in the cache */
- while (1) {
- code = cm_SyncOp(scp, bufferp, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK
- | CM_SCACHESYNC_WRITE
- | CM_SCACHESYNC_BUFLOCKED);
- if (code)
- goto done;
-
- cm_SyncOpDone(scp, bufferp,
- CM_SCACHESYNC_NEEDCALLBACK
- | CM_SCACHESYNC_WRITE
- | CM_SCACHESYNC_BUFLOCKED);
+ while (code == 0) {
+ if (!needSyncOpDone) {
+ code = cm_SyncOp(scp, bufferp, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ if (code)
+ goto done;
+
+ needSyncOpDone = 1;
+ }
/* If we're overwriting the entire buffer, or
* if we're writing at or past EOF, mark the
* Use minLength instead of scp->length, since
* the latter has already been updated by this
* call.
+ *
+ * The scp lock has been dropped multiple times
+ * so the minLength must be refreshed before it
+ * is used.
*/
+
+ minLength = scp->length;
+ if (LargeIntegerGreaterThan(minLength, scp->serverLength))
+ minLength = scp->serverLength;
+
if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength)
|| LargeIntegerEqualTo(offset, bufferp->offset)
&& (count >= cm_data.buf_blockSize
if (cm_HaveBuffer(scp, bufferp, 1)) break;
/* otherwise, load the buffer and try again */
+ cm_SyncOpDone(scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ needSyncOpDone = 0;
+
lock_ReleaseMutex(&bufferp->mx);
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&bufferp->mx);
lock_ObtainWrite(&scp->rw);
- if (code) break;
}
- if (code) {
- lock_ReleaseMutex(&bufferp->mx);
- buf_Release(bufferp);
- bufferp = NULL;
+ if (code)
goto done;
- }
} /* if (wrong buffer) ... */
/* now we have the right buffer loaded. Copy out the
op += nbytes;
count -= nbytes;
written += nbytes;
- thyper.LowPart = nbytes;
- thyper.HighPart = 0;
- offset = LargeIntegerAdd(thyper, offset);
- } /* while 1 */
+ offset = LargeIntegerAdd(offset, ConvertLongToLargeInteger(nbytes));
+ } /* while count != 0 */
done:
+ if (bufferp && needSyncOpDone) {
+ cm_SyncOpDone(scp, bufferp,
+ CM_SCACHESYNC_NEEDCALLBACK
+ | CM_SCACHESYNC_WRITE
+ | CM_SCACHESYNC_BUFLOCKED);
+ }
+
lock_ReleaseWrite(&scp->rw);
if (bufferp) {