uboot/fs/ext4/ext4_journal.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2011 - 2012 Samsung Electronics
   3 * EXT4 filesystem implementation in Uboot by
   4 * Uma Shankar <uma.shankar@samsung.com>
   5 * Manjunatha C Achar <a.manjunatha@samsung.com>
   6 *
   7 * Journal data structures and headers for Journaling feature of ext4
   8 * have been referred from JBD2 (Journaling Block device 2)
   9 * implementation in Linux Kernel.
  10 * Written by Stephen C. Tweedie <sct@redhat.com>
  11 *
  12 * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
  13 * SPDX-License-Identifier:     GPL-2.0+
  14 */
  15
  16#include <common.h>
  17#include <ext4fs.h>
  18#include <malloc.h>
  19#include <ext_common.h>
  20#include "ext4_common.h"
  21
  22static struct revoke_blk_list *revk_blk_list;
  23static struct revoke_blk_list *prev_node;
  24static int first_node = true;
  25
  26int gindex;
  27int gd_index;
  28int jrnl_blk_idx;
  29struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
  30struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
  31
  32int ext4fs_init_journal(void)
  33{
  34        int i;
  35        char *temp = NULL;
  36        struct ext_filesystem *fs = get_fs();
  37
  38        /* init globals */
  39        revk_blk_list = NULL;
  40        prev_node = NULL;
  41        gindex = 0;
  42        gd_index = 0;
  43        jrnl_blk_idx = 1;
  44
  45        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
  46                journal_ptr[i] = zalloc(sizeof(struct journal_log));
  47                if (!journal_ptr[i])
  48                        goto fail;
  49                dirty_block_ptr[i] = zalloc(sizeof(struct dirty_blocks));
  50                if (!dirty_block_ptr[i])
  51                        goto fail;
  52                journal_ptr[i]->buf = NULL;
  53                journal_ptr[i]->blknr = -1;
  54
  55                dirty_block_ptr[i]->buf = NULL;
  56                dirty_block_ptr[i]->blknr = -1;
  57        }
  58
  59        if (fs->blksz == 4096) {
  60                temp = zalloc(fs->blksz);
  61                if (!temp)
  62                        goto fail;
  63                journal_ptr[gindex]->buf = zalloc(fs->blksz);
  64                if (!journal_ptr[gindex]->buf)
  65                        goto fail;
  66                ext4fs_devread(0, 0, fs->blksz, temp);
  67                memcpy(temp + SUPERBLOCK_SIZE, fs->sb, SUPERBLOCK_SIZE);
  68                memcpy(journal_ptr[gindex]->buf, temp, fs->blksz);
  69                journal_ptr[gindex++]->blknr = 0;
  70                free(temp);
  71        } else {
  72                journal_ptr[gindex]->buf = zalloc(fs->blksz);
  73                if (!journal_ptr[gindex]->buf)
  74                        goto fail;
  75                memcpy(journal_ptr[gindex]->buf, fs->sb, SUPERBLOCK_SIZE);
  76                journal_ptr[gindex++]->blknr = 1;
  77        }
  78
  79        /* Check the file system state using journal super block */
  80        if (ext4fs_check_journal_state(SCAN))
  81                goto fail;
  82        /* Check the file system state using journal super block */
  83        if (ext4fs_check_journal_state(RECOVER))
  84                goto fail;
  85
  86        return 0;
  87fail:
  88        return -1;
  89}
  90
  91void ext4fs_dump_metadata(void)
  92{
  93        struct ext_filesystem *fs = get_fs();
  94        int i;
  95        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
  96                if (dirty_block_ptr[i]->blknr == -1)
  97                        break;
  98                put_ext4((uint64_t) ((uint64_t)dirty_block_ptr[i]->blknr *
  99                                (uint64_t)fs->blksz), dirty_block_ptr[i]->buf,
 100                                                                fs->blksz);
 101        }
 102}
 103
 104void ext4fs_free_journal(void)
 105{
 106        int i;
 107        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 108                if (dirty_block_ptr[i]->blknr == -1)
 109                        break;
 110                if (dirty_block_ptr[i]->buf)
 111                        free(dirty_block_ptr[i]->buf);
 112        }
 113
 114        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 115                if (journal_ptr[i]->blknr == -1)
 116                        break;
 117                if (journal_ptr[i]->buf)
 118                        free(journal_ptr[i]->buf);
 119        }
 120
 121        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 122                if (journal_ptr[i])
 123                        free(journal_ptr[i]);
 124                if (dirty_block_ptr[i])
 125                        free(dirty_block_ptr[i]);
 126        }
 127        gindex = 0;
 128        gd_index = 0;
 129        jrnl_blk_idx = 1;
 130}
 131
 132int ext4fs_log_gdt(char *gd_table)
 133{
 134        struct ext_filesystem *fs = get_fs();
 135        short i;
 136        long int var = fs->gdtable_blkno;
 137        for (i = 0; i < fs->no_blk_pergdt; i++) {
 138                journal_ptr[gindex]->buf = zalloc(fs->blksz);
 139                if (!journal_ptr[gindex]->buf)
 140                        return -ENOMEM;
 141                memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
 142                gd_table += fs->blksz;
 143                journal_ptr[gindex++]->blknr = var++;
 144        }
 145
 146        return 0;
 147}
 148
 149/*
 150 * This function stores the backup copy of meta data in RAM
 151 * journal_buffer -- Buffer containing meta data
 152 * blknr -- Block number on disk of the meta data buffer
 153 */
 154int ext4fs_log_journal(char *journal_buffer, long int blknr)
 155{
 156        struct ext_filesystem *fs = get_fs();
 157        short i;
 158
 159        if (!journal_buffer) {
 160                printf("Invalid input arguments %s\n", __func__);
 161                return -EINVAL;
 162        }
 163
 164        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 165                if (journal_ptr[i]->blknr == -1)
 166                        break;
 167                if (journal_ptr[i]->blknr == blknr)
 168                        return 0;
 169        }
 170
 171        journal_ptr[gindex]->buf = zalloc(fs->blksz);
 172        if (!journal_ptr[gindex]->buf)
 173                return -ENOMEM;
 174
 175        memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
 176        journal_ptr[gindex++]->blknr = blknr;
 177
 178        return 0;
 179}
 180
 181/*
 182 * This function stores the modified meta data in RAM
 183 * metadata_buffer -- Buffer containing meta data
 184 * blknr -- Block number on disk of the meta data buffer
 185 */
 186int ext4fs_put_metadata(char *metadata_buffer, long int blknr)
 187{
 188        struct ext_filesystem *fs = get_fs();
 189        if (!metadata_buffer) {
 190                printf("Invalid input arguments %s\n", __func__);
 191                return -EINVAL;
 192        }
 193        dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
 194        if (!dirty_block_ptr[gd_index]->buf)
 195                return -ENOMEM;
 196        memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
 197        dirty_block_ptr[gd_index++]->blknr = blknr;
 198
 199        return 0;
 200}
 201
 202void print_revoke_blks(char *revk_blk)
 203{
 204        int offset;
 205        int max;
 206        long int blocknr;
 207        struct journal_revoke_header_t *header;
 208
 209        if (revk_blk == NULL)
 210                return;
 211
 212        header = (struct journal_revoke_header_t *) revk_blk;
 213        offset = sizeof(struct journal_revoke_header_t);
 214        max = be32_to_cpu(header->r_count);
 215        printf("total bytes %d\n", max);
 216
 217        while (offset < max) {
 218                blocknr = be32_to_cpu(*((long int *)(revk_blk + offset)));
 219                printf("revoke blknr is %ld\n", blocknr);
 220                offset += 4;
 221        }
 222}
 223
 224static struct revoke_blk_list *_get_node(void)
 225{
 226        struct revoke_blk_list *tmp_node;
 227        tmp_node = zalloc(sizeof(struct revoke_blk_list));
 228        if (tmp_node == NULL)
 229                return NULL;
 230        tmp_node->content = NULL;
 231        tmp_node->next = NULL;
 232
 233        return tmp_node;
 234}
 235
 236void ext4fs_push_revoke_blk(char *buffer)
 237{
 238        struct revoke_blk_list *node = NULL;
 239        struct ext_filesystem *fs = get_fs();
 240        if (buffer == NULL) {
 241                printf("buffer ptr is NULL\n");
 242                return;
 243        }
 244        node = _get_node();
 245        if (!node) {
 246                printf("_get_node: malloc failed\n");
 247                return;
 248        }
 249
 250        node->content = zalloc(fs->blksz);
 251        if (node->content == NULL)
 252                return;
 253        memcpy(node->content, buffer, fs->blksz);
 254
 255        if (first_node == true) {
 256                revk_blk_list = node;
 257                prev_node = node;
 258                 first_node = false;
 259        } else {
 260                prev_node->next = node;
 261                prev_node = node;
 262        }
 263}
 264
 265void ext4fs_free_revoke_blks(void)
 266{
 267        struct revoke_blk_list *tmp_node = revk_blk_list;
 268        struct revoke_blk_list *next_node = NULL;
 269
 270        while (tmp_node != NULL) {
 271                if (tmp_node->content)
 272                        free(tmp_node->content);
 273                tmp_node = tmp_node->next;
 274        }
 275
 276        tmp_node = revk_blk_list;
 277        while (tmp_node != NULL) {
 278                next_node = tmp_node->next;
 279                free(tmp_node);
 280                tmp_node = next_node;
 281        }
 282
 283        revk_blk_list = NULL;
 284        prev_node = NULL;
 285        first_node = true;
 286}
 287
 288int check_blknr_for_revoke(long int blknr, int sequence_no)
 289{
 290        struct journal_revoke_header_t *header;
 291        int offset;
 292        int max;
 293        long int blocknr;
 294        char *revk_blk;
 295        struct revoke_blk_list *tmp_revk_node = revk_blk_list;
 296        while (tmp_revk_node != NULL) {
 297                revk_blk = tmp_revk_node->content;
 298
 299                header = (struct journal_revoke_header_t *) revk_blk;
 300                if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
 301                        offset = sizeof(struct journal_revoke_header_t);
 302                        max = be32_to_cpu(header->r_count);
 303
 304                        while (offset < max) {
 305                                blocknr = be32_to_cpu(*((long int *)
 306                                                  (revk_blk + offset)));
 307                                if (blocknr == blknr)
 308                                        goto found;
 309                                offset += 4;
 310                        }
 311                }
 312                tmp_revk_node = tmp_revk_node->next;
 313        }
 314
 315        return -1;
 316
 317found:
 318        return 0;
 319}
 320
 321/*
 322 * This function parses the journal blocks and replays the
 323 * suceessful transactions. A transaction is successfull
 324 * if commit block is found for a descriptor block
 325 * The tags in descriptor block contain the disk block
 326 * numbers of the metadata  to be replayed
 327 */
 328void recover_transaction(int prev_desc_logical_no)
 329{
 330        struct ext2_inode inode_journal;
 331        struct ext_filesystem *fs = get_fs();
 332        struct journal_header_t *jdb;
 333        long int blknr;
 334        char *p_jdb;
 335        int ofs, flags;
 336        int i;
 337        struct ext3_journal_block_tag *tag;
 338        char *temp_buff = zalloc(fs->blksz);
 339        char *metadata_buff = zalloc(fs->blksz);
 340        if (!temp_buff || !metadata_buff)
 341                goto fail;
 342        i = prev_desc_logical_no;
 343        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
 344                          (struct ext2_inode *)&inode_journal);
 345        blknr = read_allocated_block((struct ext2_inode *)
 346                                     &inode_journal, i);
 347        ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
 348                       temp_buff);
 349        p_jdb = (char *)temp_buff;
 350        jdb = (struct journal_header_t *) temp_buff;
 351        ofs = sizeof(struct journal_header_t);
 352
 353        do {
 354                tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
 355                ofs += sizeof(struct ext3_journal_block_tag);
 356
 357                if (ofs > fs->blksz)
 358                        break;
 359
 360                flags = be32_to_cpu(tag->flags);
 361                if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
 362                        ofs += 16;
 363
 364                i++;
 365                debug("\t\ttag %u\n", be32_to_cpu(tag->block));
 366                if (revk_blk_list != NULL) {
 367                        if (check_blknr_for_revoke(be32_to_cpu(tag->block),
 368                                be32_to_cpu(jdb->h_sequence)) == 0)
 369                                continue;
 370                }
 371                blknr = read_allocated_block(&inode_journal, i);
 372                ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
 373                               fs->blksz, metadata_buff);
 374                put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
 375                         metadata_buff, (uint32_t) fs->blksz);
 376        } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
 377fail:
 378        free(temp_buff);
 379        free(metadata_buff);
 380}
 381
 382void print_jrnl_status(int recovery_flag)
 383{
 384        if (recovery_flag == RECOVER)
 385                printf("Journal Recovery Completed\n");
 386        else
 387                printf("Journal Scan Completed\n");
 388}
 389
 390int ext4fs_check_journal_state(int recovery_flag)
 391{
 392        int i;
 393        int DB_FOUND = NO;
 394        long int blknr;
 395        int transaction_state = TRANSACTION_COMPLETE;
 396        int prev_desc_logical_no = 0;
 397        int curr_desc_logical_no = 0;
 398        int ofs, flags;
 399        struct ext2_inode inode_journal;
 400        struct journal_superblock_t *jsb = NULL;
 401        struct journal_header_t *jdb = NULL;
 402        char *p_jdb = NULL;
 403        struct ext3_journal_block_tag *tag = NULL;
 404        char *temp_buff = NULL;
 405        char *temp_buff1 = NULL;
 406        struct ext_filesystem *fs = get_fs();
 407
 408        temp_buff = zalloc(fs->blksz);
 409        if (!temp_buff)
 410                return -ENOMEM;
 411        temp_buff1 = zalloc(fs->blksz);
 412        if (!temp_buff1) {
 413                free(temp_buff);
 414                return -ENOMEM;
 415        }
 416
 417        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
 418        blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
 419        ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
 420                       temp_buff);
 421        jsb = (struct journal_superblock_t *) temp_buff;
 422
 423        if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
 424                if (recovery_flag == RECOVER)
 425                        printf("Recovery required\n");
 426        } else {
 427                if (recovery_flag == RECOVER)
 428                        printf("File System is consistent\n");
 429                goto end;
 430        }
 431
 432        if (be32_to_cpu(jsb->s_start) == 0)
 433                goto end;
 434
 435        if (!(jsb->s_feature_compat &
 436                                cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
 437                jsb->s_feature_compat |=
 438                                cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
 439
 440        i = be32_to_cpu(jsb->s_first);
 441        while (1) {
 442                blknr = read_allocated_block(&inode_journal, i);
 443                memset(temp_buff1, '\0', fs->blksz);
 444                ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
 445                               0, fs->blksz, temp_buff1);
 446                jdb = (struct journal_header_t *) temp_buff1;
 447
 448                if (be32_to_cpu(jdb->h_blocktype) ==
 449                    EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
 450                        if (be32_to_cpu(jdb->h_sequence) !=
 451                            be32_to_cpu(jsb->s_sequence)) {
 452                                print_jrnl_status(recovery_flag);
 453                                break;
 454                        }
 455
 456                        curr_desc_logical_no = i;
 457                        if (transaction_state == TRANSACTION_COMPLETE)
 458                                transaction_state = TRANSACTION_RUNNING;
 459                        else
 460                                return -1;
 461                        p_jdb = (char *)temp_buff1;
 462                        ofs = sizeof(struct journal_header_t);
 463                        do {
 464                                tag = (struct ext3_journal_block_tag *)
 465                                    &p_jdb[ofs];
 466                                ofs += sizeof(struct ext3_journal_block_tag);
 467                                if (ofs > fs->blksz)
 468                                        break;
 469                                flags = be32_to_cpu(tag->flags);
 470                                if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
 471                                        ofs += 16;
 472                                i++;
 473                                debug("\t\ttag %u\n", be32_to_cpu(tag->block));
 474                        } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
 475                        i++;
 476                        DB_FOUND = YES;
 477                } else if (be32_to_cpu(jdb->h_blocktype) ==
 478                                EXT3_JOURNAL_COMMIT_BLOCK) {
 479                        if (be32_to_cpu(jdb->h_sequence) !=
 480                             be32_to_cpu(jsb->s_sequence)) {
 481                                print_jrnl_status(recovery_flag);
 482                                break;
 483                        }
 484
 485                        if (transaction_state == TRANSACTION_RUNNING ||
 486                                        (DB_FOUND == NO)) {
 487                                transaction_state = TRANSACTION_COMPLETE;
 488                                i++;
 489                                jsb->s_sequence =
 490                                        cpu_to_be32(be32_to_cpu(
 491                                                jsb->s_sequence) + 1);
 492                        }
 493                        prev_desc_logical_no = curr_desc_logical_no;
 494                        if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
 495                                recover_transaction(prev_desc_logical_no);
 496
 497                        DB_FOUND = NO;
 498                } else if (be32_to_cpu(jdb->h_blocktype) ==
 499                                EXT3_JOURNAL_REVOKE_BLOCK) {
 500                        if (be32_to_cpu(jdb->h_sequence) !=
 501                            be32_to_cpu(jsb->s_sequence)) {
 502                                print_jrnl_status(recovery_flag);
 503                                break;
 504                        }
 505                        if (recovery_flag == SCAN)
 506                                ext4fs_push_revoke_blk((char *)jdb);
 507                        i++;
 508                } else {
 509                        debug("Else Case\n");
 510                        if (be32_to_cpu(jdb->h_sequence) !=
 511                            be32_to_cpu(jsb->s_sequence)) {
 512                                print_jrnl_status(recovery_flag);
 513                                break;
 514                        }
 515                }
 516        }
 517
 518end:
 519        if (recovery_flag == RECOVER) {
 520                jsb->s_start = cpu_to_be32(1);
 521                jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
 522                /* get the superblock */
 523                ext4_read_superblock((char *)fs->sb);
 524                fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
 525
 526                /* Update the super block */
 527                put_ext4((uint64_t) (SUPERBLOCK_SIZE),
 528                         (struct ext2_sblock *)fs->sb,
 529                         (uint32_t) SUPERBLOCK_SIZE);
 530                ext4_read_superblock((char *)fs->sb);
 531
 532                blknr = read_allocated_block(&inode_journal,
 533                                         EXT2_JOURNAL_SUPERBLOCK);
 534                put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
 535                         (struct journal_superblock_t *)temp_buff,
 536                         (uint32_t) fs->blksz);
 537                ext4fs_free_revoke_blks();
 538        }
 539        free(temp_buff);
 540        free(temp_buff1);
 541
 542        return 0;
 543}
 544
 545static void update_descriptor_block(long int blknr)
 546{
 547        int i;
 548        long int jsb_blknr;
 549        struct journal_header_t jdb;
 550        struct ext3_journal_block_tag tag;
 551        struct ext2_inode inode_journal;
 552        struct journal_superblock_t *jsb = NULL;
 553        char *buf = NULL;
 554        char *temp = NULL;
 555        struct ext_filesystem *fs = get_fs();
 556        char *temp_buff = zalloc(fs->blksz);
 557        if (!temp_buff)
 558                return;
 559
 560        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
 561        jsb_blknr = read_allocated_block(&inode_journal,
 562                                         EXT2_JOURNAL_SUPERBLOCK);
 563        ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
 564                       temp_buff);
 565        jsb = (struct journal_superblock_t *) temp_buff;
 566
 567        jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
 568        jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
 569        jdb.h_sequence = jsb->s_sequence;
 570        buf = zalloc(fs->blksz);
 571        if (!buf) {
 572                free(temp_buff);
 573                return;
 574        }
 575        temp = buf;
 576        memcpy(buf, &jdb, sizeof(struct journal_header_t));
 577        temp += sizeof(struct journal_header_t);
 578
 579        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 580                if (journal_ptr[i]->blknr == -1)
 581                        break;
 582
 583                tag.block = cpu_to_be32(journal_ptr[i]->blknr);
 584                tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
 585                memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
 586                temp = temp + sizeof(struct ext3_journal_block_tag);
 587        }
 588
 589        tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
 590        tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
 591        memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
 592               sizeof(struct ext3_journal_block_tag));
 593        put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
 594
 595        free(temp_buff);
 596        free(buf);
 597}
 598
 599static void update_commit_block(long int blknr)
 600{
 601        struct journal_header_t jdb;
 602        struct ext_filesystem *fs = get_fs();
 603        char *buf = NULL;
 604        struct ext2_inode inode_journal;
 605        struct journal_superblock_t *jsb;
 606        long int jsb_blknr;
 607        char *temp_buff = zalloc(fs->blksz);
 608        if (!temp_buff)
 609                return;
 610
 611        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
 612                          &inode_journal);
 613        jsb_blknr = read_allocated_block(&inode_journal,
 614                                         EXT2_JOURNAL_SUPERBLOCK);
 615        ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
 616                       temp_buff);
 617        jsb = (struct journal_superblock_t *) temp_buff;
 618
 619        jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
 620        jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
 621        jdb.h_sequence = jsb->s_sequence;
 622        buf = zalloc(fs->blksz);
 623        if (!buf) {
 624                free(temp_buff);
 625                return;
 626        }
 627        memcpy(buf, &jdb, sizeof(struct journal_header_t));
 628        put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
 629
 630        free(temp_buff);
 631        free(buf);
 632}
 633
 634void ext4fs_update_journal(void)
 635{
 636        struct ext2_inode inode_journal;
 637        struct ext_filesystem *fs = get_fs();
 638        long int blknr;
 639        int i;
 640        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
 641        blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
 642        update_descriptor_block(blknr);
 643        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 644                if (journal_ptr[i]->blknr == -1)
 645                        break;
 646                blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
 647                put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
 648                         journal_ptr[i]->buf, fs->blksz);
 649        }
 650        blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
 651        update_commit_block(blknr);
 652        printf("update journal finished\n");
 653}
 654