Changeset 1956

Show
Ignore:
Timestamp:
02/28/09 16:03:24 (3 years ago)
Author:
mwhitworth
Message:

Rework buffer flusher, keep per-device dirty count, add waitqueue so threads can wait for a flush to be done.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • Whitix/tags/0.2b/fs/vfs/bcache.c

    r1852 r1956  
    4141DWORD cacheSize=0; 
    4242extern struct DevClass storageClass; 
    43 int numDirty=0; 
    4443 
    4544static void _BufferWait(struct Buffer* buffer); 
     
    188187static void BlockBufferRemove(struct Buffer* buff) 
    189188{ 
    190 //      WaitForBuffer(buff); /* TODO: Have a wait parameter. */ 
     189        DWORD flags; 
     190         
    191191        MemFree(buff->data); 
     192         
     193        IrqSaveFlags(flags); 
    192194        ListRemove(&buff->list); 
     195        IrqRestoreFlags(flags); 
     196         
    193197        MemCacheFree(blockCache, buff); 
    194198} 
     
    210214        /* Sleep on the request wait queue, which wakes up all waiters when EndRequest is called */ 
    211215        WaitForBuffer(request->buffer); 
     216         
    212217        return request->ioStatus; 
    213218} 
     
    238243        { 
    239244                /* I/O error */ 
    240                 KePrint("BlockSendRequest: error (%d) reading %u\n",err,request->sector); 
     245                KePrint("BlockSendRequest: error (%d) reading %u\n", err, request->sector); 
    241246                err=-EIO; 
    242247        } 
     
    269274 
    270275        if (!request) 
    271                 return -EFAULT; 
     276        { 
     277                KePrint(KERN_ERROR "BlockSendRequest: could not build request for %u\n", buff->blockNum); 
     278                return -EIO; 
     279        } 
    272280 
    273281        /* Buffer should already be locked if we're coming from BlockRead */ 
    274282 
    275         err = BlockSendRequestRaw(device,request); 
     283        err = BlockSendRequestRaw(device, request); 
    276284 
    277285        MemCacheFree(requestCache, request); 
     
    293301                return buff; 
    294302 
    295         if (!(buff=BlockBufferAlloc(device,blockNum))) 
     303        if (!(buff=BlockBufferAlloc(device, blockNum))) 
    296304                return NULL; 
    297  
     305                 
    298306        if (BlockBufferRead(device,buff)) 
    299307        { 
     
    328336{ 
    329337        /* Just signal that the buffer is dirty, and let BufferFlusher write it to disk in the near future as an update */ 
     338                 
    330339        if (!BitTestAndSet(&buffer->flags, BUFFER_DIRTY)) 
    331                 numDirty++; 
    332  
    333         if (numDirty == 1) 
    334         { 
    335                 if (bufferFlusher) 
    336                         ThrResumeThread(bufferFlusher); 
    337         } 
     340                device->numDirty++; 
     341 
     342        if (bufferFlusher) 
     343                ThrResumeThread(bufferFlusher); 
    338344         
    339345        return 0; 
     
    346352        struct Buffer* curr,*curr2; 
    347353        DWORD i; 
    348  
     354         
     355        if (device->numDirty) 
     356        { 
     357                BlockSyncDevice(device); 
     358                WAIT_ON(&device->flushDone, !device->numDirty); 
     359        } 
     360         
    349361        /* If any buffers were dirty - they would have been done by BlockWrite, 
    350362           which also writes them to disk through buffer flusher. So no need 
     
    375387        if (sDevice->softBlockSize == blockSize) 
    376388                return 0; 
    377  
     389                 
    378390        /* Sync all buffers with the old size */ 
    379391        BlockDeviceFreeAll(sDevice); 
    380392 
    381         sDevice->softBlockSize=blockSize; 
     393        sDevice->softBlockSize = blockSize; 
     394                 
    382395        return 0; 
    383396} 
     
    392405        struct Buffer* buff, *buff2; 
    393406 
    394 //      KePrint("BlockSyncDevice(%s), numDirty = %d\n", KeObjGetName(&device->device.object), numDirty); 
    395  
     407//      KePrint("BlockSyncDevice(%s), numDirty = %d\n", KeObjGetName(&device->device.object), device->numDirty); 
     408 
     409        if (device->syncing || !device->numDirty) 
     410                return 0; 
     411                 
     412        device->syncing = 1; 
     413 
     414again: 
    396415        for (i=0; i<HASH_NUM_ENTRIES; i++) 
    397416        { 
    398                 struct ListHead* head=&device->hashLists[i]; 
     417                struct ListHead* head = &device->hashLists[i]; 
    399418 
    400419                /* Write all the blocks belonging to device to disk */ 
     
    403422                        if (BufferDirty(buff)) 
    404423                        { 
     424//                              KePrint("%#X: dirty(%u), %u\n", buff, buff->blockNum, device->numDirty); 
     425                                 
     426                                --device->numDirty; 
     427                                BitClear(&buff->flags, BUFFER_DIRTY); 
     428                                 
    405429                                /* For each block, call the respective StorageDevice write function */ 
    406430                                DoBlockWrite(buff->device, buff); 
    407                                 --numDirty; 
    408                                 BitClear(&buff->flags, BUFFER_DIRTY); 
     431                                 
     432//                              KePrint("%#X: done dirty(%u), %u\n", buff, buff->blockNum, device->numDirty); 
    409433                        } 
     434                         
     435                        if (!device->numDirty) 
     436                                goto out; 
    410437                } 
    411438        } 
    412  
     439         
     440out: 
     441        if (!device->numDirty) 
     442                WakeUpAll(&device->flushDone); 
     443        else 
     444                goto again; 
     445         
     446        device->syncing = 0; 
    413447        return 0; 
    414448} 
     
    459493        while (1) 
    460494        { 
    461                 if (!numDirty) 
    462                 { 
    463                         ThrSuspendThread(currThread); 
    464                         ThrSchedule(); 
    465                 } 
     495                ThrSuspendThread(currThread); 
     496                ThrSchedule(); 
    466497                 
    467498                BlockSyncAll(); 
     
    502533 
    503534        PreemptDisable(); 
    504  
     535         
    505536        ListForEachEntry(curr, head, list) 
    506537                if (curr->blockNum == blockNum)