Changeset 759 for Whitix/branches

Show
Ignore:
Timestamp:
07/09/08 15:26:36 (5 months ago)
Author:
mwhitworth
Message:

Add to journal code. Support for per-journal threads, flushing of metadata, and start of commit code.

Location:
Whitix/branches/fs/fs/journal
Files:
3 modified

Legend:

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

    r756 r759  
    2828struct Cache* journalCache=NULL, *journHandleCache=NULL, *journTransCache=NULL; 
    2929 
    30 static void JournalCommitter() 
    31 { 
    32         ThrSetPriority(currThread, 1); 
    33  
    34         while (1) 
    35         { 
    36                 ThrSuspendThread(currThread); 
    37                 ThrSchedule(); 
    38  
    39                 KePrint("JournalCommitter was woken up\n"); 
    40         } 
    41 } 
    42  
    4330int JournalInit() 
    4431{ 
     
    5037                sizeof(struct JournalTrans), NULL, NULL, 0); 
    5138 
    52         journalCommitter=ThrCreateKernelThread(JournalCommitter); 
    53  
    5439        return 0; 
    5540} 
  • Whitix/branches/fs/fs/journal/journals.c

    r756 r759  
    4444} 
    4545 
     46struct JournalHead* JournalAllocHeader() 
     47{ 
     48        return malloc(sizeof(struct JournalHead)); 
     49} 
     50 
     51struct JournalHead* JournalAddHeader(struct Buffer* buffer) 
     52{ 
     53        struct JournalHead* ret; 
     54 
     55        if (BufferJournal(buffer)) 
     56        { 
     57                ret=BufferToJournHead(buffer); 
     58        }else{ 
     59                ret=JournalAllocHeader(); 
     60 
     61                buffer->flags |= 1 << BUFFER_JOURNAL; 
     62                buffer->privData=ret; 
     63                ret->buffer=buffer; 
     64                BufferGet(buffer); 
     65        } 
     66 
     67        return buffer->privData; 
     68} 
     69 
     70extern void SleepWakeup(void* data); 
     71 
     72void JournalCommitSetTimer(struct Timer* commitTimer, struct Journal* journal) 
     73{ 
     74        /* Set up timer. */ 
     75        commitTimer->func=SleepWakeup; 
     76        commitTimer->expires=journal->commitInterval*100000; 
     77        commitTimer->data=currThread; 
     78 
     79        TimerAdd(commitTimer); 
     80} 
     81 
     82/* Journal commit thread. */ 
     83 
     84/* TODO: Move to commit.c */ 
     85void JournalCommitter(void* arg) 
     86{ 
     87        struct Journal* journal=(struct Journal*)arg; 
     88        struct Timer commitTimer; 
     89        INIT_WAITQUEUE_ENTRY(commitWait); 
     90 
     91        INIT_WAITQUEUE_HEAD(&journal->commitWait); 
     92        INIT_WAITQUEUE_HEAD(&journal->commitWaitDone); 
     93 
     94        KePrint(KERN_INFO "JournalCommitter: started journal with commit interval of %d" 
     95                " seconds\n", journal->commitInterval); 
     96 
     97        while (1) 
     98        { 
     99                /* There should be a transaction to commit. */ 
     100                if (journal->commitSequence != journal->commitRequest) 
     101                { 
     102                        TimerRemove(&commitTimer); 
     103 
     104                        JournalCommitTransaction(journal); 
     105                } 
     106 
     107                /* May not always want timer running, esp. if we are waiting for commits. */ 
     108                JournalCommitSetTimer(&commitTimer, journal); 
     109 
     110                WaitAddToQueue(&journal->commitWait, &commitWait); 
     111 
     112                ThrSuspendThread(currThread); 
     113                ThrSchedule(); /* Will return here when the thread is scheduled again */ 
     114                WaitRemoveFromQueue(&journal->commitWait, &commitWait); 
     115                 
     116                /* Get the running transaction, if we timed out, and commit that. Check expires. */ 
     117                if (journal->currTransaction && currTime.seconds >= journal->currTransaction->expires) 
     118                        journal->commitRequest=journal->currTransaction->transId; 
     119        } 
     120} 
     121 
     122int JournalNextLogBlock(struct Journal* journal, DWORD* ret) 
     123{ 
     124        DWORD blockNum; 
     125 
     126        blockNum=journal->head; 
     127 
     128        journal->head++; 
     129        journal->free--; 
     130         
     131        /* Check for wraparound! */ 
     132 
     133        return JournalBlockMap(journal, blockNum, ret); 
     134} 
     135 
     136struct JournalHead* JournalGetDescriptorBuffer(struct Journal* journal) 
     137{ 
     138        int err; 
     139        DWORD blockNum; 
     140        struct Buffer* buffer; 
     141 
     142        err=JournalNextLogBlock(journal, &blockNum); 
     143 
     144        if (err) 
     145                return NULL; 
     146 
     147        buffer=JournalBlockRead(journal, blockNum); 
     148 
     149        if (!buffer) 
     150                return NULL; 
     151 
     152        memset(buffer->data, 0, journal->sectorSize); 
     153 
     154        return JournalAddHeader(buffer); 
     155} 
     156 
    46157struct Journal* JournalCreate(struct VNode* vNode) 
    47158{ 
    48         struct Journal* journal=JournalAllocate(); 
     159        struct Journal* journal; 
    49160        DWORD blockNo; 
    50161        struct Buffer* headerBuf; 
     
    52163        struct VfsSuperBlock* superBlock=vNode->superBlock; 
    53164 
     165        journal=JournalAllocate(); 
     166 
    54167        if (!journal) 
    55168                return NULL; 
     
    100213                journal->version, journal->maxLength); 
    101214 
     215        /* Start the per-journal commit kernel thread. */ 
     216        journal->commitThread=ThrCreateKernelThreadArg(JournalCommitter, journal); 
     217        journal->commitInterval=JOURN_COMMIT_INTERVAL; 
     218 
     219        JournalRecover(journal, jSb); 
     220 
     221        /* Set up transaction sequence numbers. */ 
     222        journal->commitSequence=journal->transSequence-1; 
     223        journal->commitRequest=journal->commitSequence; 
     224 
     225        journal->head=BeToCpu32(jSb->first); 
     226        journal->free=BeToCpu32(jSb->maxLen)-journal->head; 
     227 
     228        ThrStartThread(journal->commitThread); 
     229 
    102230        return journal; 
    103231} 
  • Whitix/branches/fs/fs/journal/transaction.c

    r756 r759  
    1818 
    1919#include <fs/journal.h> 
     20#include <fs/vfs.h> 
    2021#include <module.h> 
    2122#include <print.h> 
     
    5152        ret->state=JTRANS_RUNNING; 
    5253        ret->transId=journal->transSequence++; 
     54        ret->expires=currTime.seconds+JOURN_COMMIT_INTERVAL; 
     55 
     56        /* TODO: Move to constructor. */ 
     57        INIT_LIST_HEAD(&ret->reservedList); 
     58        INIT_LIST_HEAD(&ret->metaDataList); 
    5359 
    5460        /* TODO: Set up timer. */ 
     
    148154SYMBOL_EXPORT(JournalStart); 
    149155 
     156int JournalStop(struct JournalHandle* handle) 
     157{ 
     158        struct JournalTrans* trans=handle->transaction; 
     159        struct Journal* journal=trans->journal; 
     160 
     161        currThread->currHandle=NULL; 
     162 
     163        trans->updates--; 
     164        trans->outstandingBlocks-=handle->numBlocks; 
     165 
     166        if (!trans->updates) 
     167        { 
     168                /* Wake up waiters. */ 
     169        } 
     170 
     171        if (handle->sync == 1 || currTime.seconds >= trans->expires) 
     172        { 
     173                int id=trans->transId; 
     174 
     175                JournalStartCommit(journal, trans); 
     176 
     177                if (handle->sync == 1) 
     178                        JournalWaitCommit(journal, id); 
     179        } 
     180 
     181        MemCacheFree(journHandleCache, handle); 
     182 
     183        return 0; 
     184} 
     185 
     186SYMBOL_EXPORT(JournalStop); 
     187 
     188void JournalFileBuffer(struct JournalHead* head, struct JournalTrans* trans, int type) 
     189{ 
     190        struct ListHead* list; 
     191 
     192        /* Already filed? */ 
     193        if (head->transaction && head->list == type) 
     194                return; 
     195 
     196        /*  
     197         * It's already in this transaction, but on a different list, so we remove it 
     198         * before adding it to the other list. 
     199         */ 
     200 
     201        if (head->transaction == trans && head->list > 0 && head->list != type) 
     202                ListRemove(&head->next); 
     203 
     204        switch (type) 
     205        { 
     206                case JOURN_RESERVED: 
     207                        list=&trans->reservedList; 
     208                        break; 
     209 
     210                case JOURN_METADATA: 
     211                        list=&trans->metaDataList; 
     212                        break; 
     213 
     214                default: 
     215                        KePrint("FileBuffer: handle %d!\n", type); 
     216                        return; 
     217        } 
     218 
     219        ListAddTail(&head->next, list); 
     220        head->list=type; 
     221} 
     222 
    150223/* Intent to modify a buffer for metadata update. */ 
    151224 
     
    158231        head=JournalAddHeader(buffer); 
    159232 
     233        JournalLock(journal); 
     234 
     235        /* Check if buffer is locked. */ 
     236 
     237        if (!head->transaction) 
     238        { 
     239                head->transaction=trans; 
     240                JournalFileBuffer(head, trans, JOURN_RESERVED); 
     241        } 
     242 
     243        JournalUnlock(journal); 
     244 
    160245        return 0; 
    161246} 
    162247 
    163248SYMBOL_EXPORT(JournalGetWriteAccess); 
     249 
     250int JournalDirtyMetadata(struct JournalHandle* handle, struct Buffer* buffer) 
     251{ 
     252        struct JournalTrans* trans=handle->transaction; 
     253        struct Journal* journal=trans->journal; 
     254        struct JournalHead* head=BufferToJournHead(buffer); 
     255 
     256        JournalLock(journal); 
     257 
     258        JournalFileBuffer(head, trans, JOURN_METADATA); 
     259 
     260        JournalUnlock(journal); 
     261 
     262        return 0; 
     263} 
     264 
     265SYMBOL_EXPORT(JournalDirtyMetadata); 
     266 
     267int JournalForceCommit(struct Journal* journal) 
     268{ 
     269        struct JournalHandle* handle; 
     270 
     271        handle=JournalStart(journal, 1); 
     272 
     273        handle->sync=1; 
     274 
     275        /* The sync forces the commit to disk. */ 
     276        JournalStop(handle); 
     277 
     278        return 0; 
     279} 
     280 
     281SYMBOL_EXPORT(JournalForceCommit);