ext4_journal: keep track of blocks added to a transaction.
authorngkaho1234 <ngkaho1234@gmail.com>
Fri, 25 Dec 2015 17:16:44 +0000 (01:16 +0800)
committerngkaho1234 <ngkaho1234@gmail.com>
Fri, 25 Dec 2015 18:27:41 +0000 (02:27 +0800)
lwext4/ext4_journal.c
lwext4/ext4_types.h

index 059606bab723f677de8255102c36656896eaeed7..6692c9d1b3c2c81980a072640820e67306ce59ed 100644 (file)
@@ -101,8 +101,20 @@ jbd_revoke_entry_cmp(struct revoke_entry *a, struct revoke_entry *b)
        return 0;
 }
 
+static int
+jbd_block_rec_cmp(struct jbd_block_rec *a, struct jbd_block_rec *b)
+{
+       if (a->lba > b->lba)
+               return 1;
+       else if (a->lba < b->lba)
+               return -1;
+       return 0;
+}
+
 RB_GENERATE_INTERNAL(jbd_revoke, revoke_entry, revoke_node,
                     jbd_revoke_entry_cmp, static inline)
+RB_GENERATE_INTERNAL(jbd_block, jbd_block_rec, block_rec_node,
+                    jbd_block_rec_cmp, static inline)
 
 #define jbd_alloc_revoke_entry() calloc(1, sizeof(struct revoke_entry))
 #define jbd_free_revoke_entry(addr) free(addr)
@@ -1080,6 +1092,8 @@ jbd_journal_new_trans(struct jbd_journal *journal)
        if (!trans)
                return NULL;
 
+       RB_INIT(&trans->block_rec_root);
+
        /* We will assign a trans_id to this transaction,
         * once it has been committed.*/
        trans->journal = journal;
@@ -1114,6 +1128,46 @@ int jbd_trans_get_access(struct jbd_journal *journal,
        return r;
 }
 
+static inline int
+jbd_trans_insert_block_rec(struct jbd_trans *trans,
+                          ext4_fsblk_t lba)
+{
+       struct jbd_block_rec *block_rec;
+       block_rec = calloc(1, sizeof(struct jbd_block_rec));
+       if (!block_rec)
+               return ENOMEM;
+
+       block_rec->lba = lba;
+       RB_INSERT(jbd_block, &trans->block_rec_root, block_rec);
+       return EOK;
+}
+
+static struct jbd_block_rec *
+jbd_trans_block_rec_lookup(struct jbd_trans *trans,
+                          ext4_fsblk_t lba)
+{
+       struct jbd_block_rec tmp = {
+               .lba = lba
+       };
+
+       return RB_FIND(jbd_block, &trans->block_rec_root, &tmp);
+}
+
+static inline void
+jbd_trans_remove_block_recs(struct jbd_trans *trans)
+{
+       struct jbd_block_rec *block_rec, *tmp;
+       RB_FOREACH_SAFE(block_rec,
+                       jbd_block,
+                       &trans->block_rec_root,
+                       tmp) {
+               RB_REMOVE(jbd_block,
+                         &trans->block_rec_root,
+                         block_rec);
+               free(block_rec);
+       }
+}
+
 /**@brief  Add block to a transaction and mark it dirty.
  * @param  trans transaction
  * @param  block block descriptor
@@ -1129,6 +1183,11 @@ int jbd_trans_set_block_dirty(struct jbd_trans *trans,
                if (!buf)
                        return ENOMEM;
 
+               if (jbd_trans_insert_block_rec(trans, block->lb_id) != EOK) {
+                       free(buf);
+                       return ENOMEM;
+               }
+
                buf->trans = trans;
                buf->block = *block;
                ext4_bcache_inc_ref(block->buf);
@@ -1193,6 +1252,7 @@ void jbd_journal_free_trans(struct jbd_journal *journal,
                free(rec);
        }
 
+       jbd_trans_remove_block_recs(trans);
        free(trans);
 }
 
index ade50a334caf47dbd0465f519fefe5c914c59eaa..9220b291caca4116112a8ac296c34cd48fa5e705 100644 (file)
@@ -1104,6 +1104,11 @@ struct jbd_revoke_rec {
        LIST_ENTRY(jbd_revoke_rec) revoke_node;
 };
 
+struct jbd_block_rec {
+       ext4_fsblk_t lba;
+       RB_ENTRY(jbd_block_rec) block_rec_node;
+};
+
 struct jbd_trans {
        uint32_t trans_id;
 
@@ -1117,6 +1122,7 @@ struct jbd_trans {
 
        LIST_HEAD(jbd_trans_buf, jbd_buf) buf_list;
        LIST_HEAD(jbd_revoke_list, jbd_revoke_rec) revoke_list;
+       RB_HEAD(jbd_block, jbd_block_rec) block_rec_root;
        TAILQ_ENTRY(jbd_trans) trans_node;
 };