Show
Ignore:
Timestamp:
07/13/08 20:45:14 (5 months ago)
Author:
mwhitworth
Message:

Add to commit support, including waking up shadow block waiters when the metadata has been committed to disk.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • Whitix/branches/fs/fs/journal/commit.c

    r775 r788  
    2020#include <fs/bcache.h> 
    2121#include <fs/journal.h> 
     22#include <llist.h> 
    2223#include <module.h> 
    2324#include <print.h> 
     
    4445                WakeUp(&journal->commitWait); 
    4546                WaitAddToQueue(&journal->commitWaitDone, &waitEntry); 
     47                KePrint("%d %d\n", id, journal->commitSequence); 
    4648                ThrSuspendThread(currThread); 
    4749                ThrSchedule(); 
     
    5254} 
    5355 
     56SYMBOL_EXPORT(JournalWaitCommit); 
     57 
    5458struct JournalHead* JournalCommitMetadata(struct Journal* journal, struct JournalTrans* commitTrans) 
    5559{ 
    56         struct JournalHead* curr, *newHead; 
     60        struct JournalHead* curr, *curr2, *newHead; 
    5761        struct JournalHead* descriptor=NULL; /* On-disk structure. */ 
    5862        struct JournalHeader* dHeader; 
     
    6569        DWORD blockNo; 
    6670 
    67         ListForEachEntry(curr, &commitTrans->metaDataList, next) 
    68         { 
     71        ListForEachEntrySafe(curr, curr2, &commitTrans->metaDataList, next) 
     72        { 
     73                int tagFlags=0; 
     74 
    6975                if (!descriptor) 
    7076                { 
     
    9298 
    9399                JournalWriteMetadataBuffer(commitTrans, curr, &newHead, blockNo); 
     100 
     101                /* We get a copy of curr, newHead, that points at the journal block 
     102                 * to write to. The real write of metadata to the disk takes place 
     103                 * in the checkpoint. 
     104                 */ 
     105 
     106                if (!firstTag) 
     107                        tagFlags |= JOURN_FLAG_SAME_UUID; 
     108 
     109                tag=(struct JournalBlockTag*)tagPointer; 
     110                tag->blockNum=CpuToBe32(JournHeadToBuffer(curr)->blockNum); 
     111                tag->flags=CpuToBe32(tagFlags); 
     112 
     113                tagPointer+=sizeof(struct JournalBlockTag); 
     114                spaceLeft-=sizeof(struct JournalBlockTag); 
     115 
     116                if (firstTag) 
     117                { 
     118                        memcpy(tagPointer, journal->uuid, 16); 
     119                        tagPointer+=16; 
     120                        spaceLeft-=16; 
     121                        firstTag=0; 
     122                } 
     123                 
     124                buffers[bufIndex++]=JournHeadToBuffer(newHead); 
     125                 
     126                /* Are we at the end of the list, or has the descriptor block run out of 
     127                 * space?  
     128                 */ 
     129                if (bufIndex == 64 || curr2->next.next == &commitTrans->metaDataList || 
     130                        spaceLeft < sizeof(struct JournalBlockTag)+16) 
     131                { 
     132                        int i; 
     133                         
     134                        KePrint("Submitting %d buffers\n", bufIndex); 
     135                        tag->flags|=CpuToBe32(JOURN_FLAG_LAST_TAG); 
     136                         
     137                        JournalUnlock(journal); 
     138                         
     139                        for (i=0; i<bufIndex; i++) 
     140                        { 
     141                                BlockWrite(buffers[i]->device, buffers[i]); 
     142                        } 
     143                         
     144                        JournalLock(journal); 
     145                } 
    94146                 
    95147        } 
     
    98150} 
    99151 
    100 SYMBOL_EXPORT(JournalWaitCommit); 
     152int JournalWaitForIO(struct Journal* journal, struct JournalTrans* commitTrans) 
     153{ 
     154        struct JournalHead* curr, *curr2; 
     155        struct JournalHead* shadow=ListEntry(commitTrans->shadowList.next, struct JournalHead, next), *shadow2; 
     156         
     157        /* Go through the journal I/O list. */ 
     158        ListForEachEntrySafe(curr, curr2, &commitTrans->ioList, next) 
     159        { 
     160                struct Buffer* buffer; 
     161                 
     162                buffer=JournHeadToBuffer(curr); 
     163                WaitForBuffer(buffer); 
     164                JournalUnfileBuffer(curr); 
     165                 
     166                /* Get the corresponding shadow buffer, and file that to a checkpoint list. */ 
     167                shadow2=ListEntry(shadow->next.next, struct JournalHead, next); 
     168                KePrint("Filing %u\n", JournHeadToBuffer(shadow)->blockNum);             
     169                JournalFileBuffer(shadow, commitTrans, JOURN_FORGET); 
     170                WakeUp(&shadow->wait); 
     171                shadow=shadow2; 
     172        } 
     173         
     174        return 0; 
     175} 
     176 
     177int JournalWriteCommitRecord(struct Journal* journal, struct JournalTrans* commitTrans) 
     178{ 
     179        struct JournalHead* head; 
     180        struct Buffer* buffer; 
     181        DWORD i; 
     182         
     183        head=JournalGetDescriptorBuffer(journal); 
     184        buffer=JournHeadToBuffer(head); 
     185         
     186        for (i=0; i<journal->sectorSize; i+=512) 
     187        { 
     188                struct JournalHeader* header=(struct JournalHeader*)(buffer->data+i); 
     189                header->magic=CpuToBe32(JFS_MAGIC); 
     190                header->blockType=CpuToBe32(JFS_COMMIT_BLOCK); 
     191                header->sequence=CpuToBe32(commitTrans->transId); 
     192        } 
     193         
     194        JournalUnlock(journal); 
     195         
     196        BlockWrite(buffer->device, buffer); 
     197        WaitForBuffer(buffer); 
     198        BufferRelease(buffer); 
     199         
     200        return 0; 
     201} 
    101202 
    102203int JournalCommitTransaction(struct Journal* journal) 
     
    108209        commitTrans=journal->currTransaction; 
    109210 
    110         KePrint(KERN_DEBUG "Committing %d\n", commitTrans->transId); 
     211        KePrint(KERN_DEBUG "Committing %d, %d\n", commitTrans->transId, commitTrans->updates); 
     212         
     213        commitTrans->state=JTRANS_COMMIT; 
    111214 
    112215        while (commitTrans->updates) 
    113216        { 
    114                 KePrint("commitTrans = %u\n", commitTrans->updates); 
     217                JournalUnlock(journal); 
     218                KePrint("wait: %u ", commitTrans->updates); 
     219                WAIT_ON(journal->waitUpdates, !commitTrans->updates); 
     220                JournalLock(journal); 
    115221        } 
    116222 
     
    120226        journal->committingTrans=commitTrans; 
    121227        journal->currTransaction=NULL; 
     228         
     229        commitTrans->logStart=journal->head; 
    122230 
    123231        /* Phase 2 */ 
     
    127235        /* Write out metadata to the journal. */ 
    128236        JournalCommitMetadata(journal, commitTrans); 
    129  
    130         JournalUnlock(journal); 
     237         
     238        /* Make sure the data is written to disk, and the metadata is written to the 
     239         * journal. 
     240         */ 
     241        JournalWaitForIO(journal, commitTrans); 
     242         
     243        /* Make sure the descriptor records are written to disk */ 
     244 
     245        ListAddTail(&commitTrans->next, &journal->checkpointTrans); 
     246         
     247        /* Write the commit record. */ 
     248        JournalWriteCommitRecord(journal, commitTrans); 
     249 
     250        /* TEST: Checkpoint the transaction. */ 
     251        JournalCheckpoint(journal); 
     252 
    131253        WakeUp(&journal->commitWaitDone); 
    132254