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, uint32_t 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, uint32_t 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        if (dirty_block_ptr[gd_index]->buf)
 194                assert(dirty_block_ptr[gd_index]->blknr == blknr);
 195        else
 196                dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
 197
 198        if (!dirty_block_ptr[gd_index]->buf)
 199                return -ENOMEM;
 200        memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
 201        dirty_block_ptr[gd_index++]->blknr = blknr;
 202
 203        return 0;
 204}
 205
 206void print_revoke_blks(char *revk_blk)
 207{
 208        int offset;
 209        int max;
 210        long int blocknr;
 211        struct journal_revoke_header_t *header;
 212
 213        if (revk_blk == NULL)
 214                return;
 215
 216        header = (struct journal_revoke_header_t *) revk_blk;
 217        offset = sizeof(struct journal_revoke_header_t);
 218        max = be32_to_cpu(header->r_count);
 219        printf("total bytes %d\n", max);
 220
 221        while (offset < max) {
 222                blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
 223                printf("revoke blknr is %ld\n", blocknr);
 224                offset += 4;
 225        }
 226}
 227
 228static struct revoke_blk_list *_get_node(void)
 229{
 230        struct revoke_blk_list *tmp_node;
 231        tmp_node = zalloc(sizeof(struct revoke_blk_list));
 232        if (tmp_node == NULL)
 233                return NULL;
 234        tmp_node->content = NULL;
 235        tmp_node->next = NULL;
 236
 237        return tmp_node;
 238}
 239
 240void ext4fs_push_revoke_blk(char *buffer)
 241{
 242        struct revoke_blk_list *node = NULL;
 243        struct ext_filesystem *fs = get_fs();
 244        if (buffer == NULL) {
 245                printf("buffer ptr is NULL\n");
 246                return;
 247        }
 248        node = _get_node();
 249        if (!node) {
 250                printf("_get_node: malloc failed\n");
 251                return;
 252        }
 253
 254        node->content = zalloc(fs->blksz);
 255        if (node->content == NULL)
 256                return;
 257        memcpy(node->content, buffer, fs->blksz);
 258
 259        if (first_node == true) {
 260                revk_blk_list = node;
 261                prev_node = node;
 262                 first_node = false;
 263        } else {
 264                prev_node->next = node;
 265                prev_node = node;
 266        }
 267}
 268
 269void ext4fs_free_revoke_blks(void)
 270{
 271        struct revoke_blk_list *tmp_node = revk_blk_list;
 272        struct revoke_blk_list *next_node = NULL;
 273
 274        while (tmp_node != NULL) {
 275                if (tmp_node->content)
 276                        free(tmp_node->content);
 277                tmp_node = tmp_node->next;
 278        }
 279
 280        tmp_node = revk_blk_list;
 281        while (tmp_node != NULL) {
 282                next_node = tmp_node->next;
 283                free(tmp_node);
 284                tmp_node = next_node;
 285        }
 286
 287        revk_blk_list = NULL;
 288        prev_node = NULL;
 289        first_node = true;
 290}
 291
 292int check_blknr_for_revoke(long int blknr, int sequence_no)
 293{
 294        struct journal_revoke_header_t *header;
 295        int offset;
 296        int max;
 297        long int blocknr;
 298        char *revk_blk;
 299        struct revoke_blk_list *tmp_revk_node = revk_blk_list;
 300        while (tmp_revk_node != NULL) {
 301                revk_blk = tmp_revk_node->content;
 302
 303                header = (struct journal_revoke_header_t *) revk_blk;
 304                if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
 305                        offset = sizeof(struct journal_revoke_header_t);
 306                        max = be32_to_cpu(header->r_count);
 307
 308                        while (offset < max) {
 309                                blocknr = be32_to_cpu(*((__be32 *)
 310                                                  (revk_blk + offset)));
 311                                if (blocknr == blknr)
 312                                        goto found;
 313                                offset += 4;
 314                        }
 315                }
 316                tmp_revk_node = tmp_revk_node->next;
 317        }
 318
 319        return -1;
 320
 321found:
 322        return 0;
 323}
 324
 325/*
 326 * This function parses the journal blocks and replays the
 327 * suceessful transactions. A transaction is successfull
 328 * if commit block is found for a descriptor block
 329 * The tags in descriptor block contain the disk block
 330 * numbers of the metadata  to be replayed
 331 */
 332void recover_transaction(int prev_desc_logical_no)
 333{
 334        struct ext2_inode inode_journal;
 335        struct ext_filesystem *fs = get_fs();
 336        struct journal_header_t *jdb;
 337        long int blknr;
 338        char *p_jdb;
 339        int ofs, flags;
 340        int i;
 341        struct ext3_journal_block_tag *tag;
 342        char *temp_buff = zalloc(fs->blksz);
 343        char *metadata_buff = zalloc(fs->blksz);
 344        if (!temp_buff || !metadata_buff)
 345                goto fail;
 346        i = prev_desc_logical_no;
 347        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
 348                          (struct ext2_inode *)&inode_journal);
 349        blknr = read_allocated_block((struct ext2_inode *)
 350                                     &inode_journal, i);
 351        ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
 352                       temp_buff);
 353        p_jdb = (char *)temp_buff;
 354        jdb = (struct journal_header_t *) temp_buff;
 355        ofs = sizeof(struct journal_header_t);
 356
 357        do {
 358                tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
 359                ofs += sizeof(struct ext3_journal_block_tag);
 360
 361                if (ofs > fs->blksz)
 362                        break;
 363
 364                flags = be32_to_cpu(tag->flags);
 365                if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
 366                        ofs += 16;
 367
 368                i++;
 369                debug("\t\ttag %u\n", be32_to_cpu(tag->block));
 370                if (revk_blk_list != NULL) {
 371                        if (check_blknr_for_revoke(be32_to_cpu(tag->block),
 372                                be32_to_cpu(jdb->h_sequence)) == 0)
 373                                continue;
 374                }
 375                blknr = read_allocated_block(&inode_journal, i);
 376                ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
 377                               fs->blksz, metadata_buff);
 378                put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
 379                         metadata_buff, (uint32_t) fs->blksz);
 380        } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
 381fail:
 382        free(temp_buff);
 383        free(metadata_buff);
 384}
 385
 386void print_jrnl_status(int recovery_flag)
 387{
 388        if (recovery_flag == RECOVER)
 389                printf("Journal Recovery Completed\n");
 390        else
 391                printf("Journal Scan Completed\n");
 392}
 393
 394int ext4fs_check_journal_state(int recovery_flag)
 395{
 396        int i;
 397        int DB_FOUND = NO;
 398        long int blknr;
 399        int transaction_state = TRANSACTION_COMPLETE;
 400        int prev_desc_logical_no = 0;
 401        int curr_desc_logical_no = 0;
 402        int ofs, flags;
 403        struct ext2_inode inode_journal;
 404        struct journal_superblock_t *jsb = NULL;
 405        struct journal_header_t *jdb = NULL;
 406        char *p_jdb = NULL;
 407        struct ext3_journal_block_tag *tag = NULL;
 408        char *temp_buff = NULL;
 409        char *temp_buff1 = NULL;
 410        struct ext_filesystem *fs = get_fs();
 411
 412        temp_buff = zalloc(fs->blksz);
 413        if (!temp_buff)
 414                return -ENOMEM;
 415        temp_buff1 = zalloc(fs->blksz);
 416        if (!temp_buff1) {
 417                free(temp_buff);
 418                return -ENOMEM;
 419        }
 420
 421        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
 422        blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
 423        ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
 424                       temp_buff);
 425        jsb = (struct journal_superblock_t *) temp_buff;
 426
 427        if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
 428                if (recovery_flag == RECOVER)
 429                        printf("Recovery required\n");
 430        } else {
 431                if (recovery_flag == RECOVER)
 432                        printf("File System is consistent\n");
 433                goto end;
 434        }
 435
 436        if (be32_to_cpu(jsb->s_start) == 0)
 437                goto end;
 438
 439        if (!(jsb->s_feature_compat &
 440                                cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
 441                jsb->s_feature_compat |=
 442                                cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
 443
 444        i = be32_to_cpu(jsb->s_first);
 445        while (1) {
 446                blknr = read_allocated_block(&inode_journal, i);
 447                memset(temp_buff1, '\0', fs->blksz);
 448                ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
 449                               0, fs->blksz, temp_buff1);
 450                jdb = (struct journal_header_t *) temp_buff1;
 451
 452                if (be32_to_cpu(jdb->h_blocktype) ==
 453                    EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
 454                        if (be32_to_cpu(jdb->h_sequence) !=
 455                            be32_to_cpu(jsb->s_sequence)) {
 456                                print_jrnl_status(recovery_flag);
 457                                break;
 458                        }
 459
 460                        curr_desc_logical_no = i;
 461                        if (transaction_state == TRANSACTION_COMPLETE)
 462                                transaction_state = TRANSACTION_RUNNING;
 463                        else
 464                                return -1;
 465                        p_jdb = (char *)temp_buff1;
 466                        ofs = sizeof(struct journal_header_t);
 467                        do {
 468                                tag = (struct ext3_journal_block_tag *)
 469                                    &p_jdb[ofs];
 470                                ofs += sizeof(struct ext3_journal_block_tag);
 471                                if (ofs > fs->blksz)
 472                                        break;
 473                                flags = be32_to_cpu(tag->flags);
 474                                if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
 475                                        ofs += 16;
 476                                i++;
 477                                debug("\t\ttag %u\n", be32_to_cpu(tag->block));
 478                        } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
 479                        i++;
 480                        DB_FOUND = YES;
 481                } else if (be32_to_cpu(jdb->h_blocktype) ==
 482                                EXT3_JOURNAL_COMMIT_BLOCK) {
 483                        if (be32_to_cpu(jdb->h_sequence) !=
 484                             be32_to_cpu(jsb->s_sequence)) {
 485                                print_jrnl_status(recovery_flag);
 486                                break;
 487                        }
 488
 489                        if (transaction_state == TRANSACTION_RUNNING ||
 490                                        (DB_FOUND == NO)) {
 491                                transaction_state = TRANSACTION_COMPLETE;
 492                                i++;
 493                                jsb->s_sequence =
 494                                        cpu_to_be32(be32_to_cpu(
 495                                                jsb->s_sequence) + 1);
 496                        }
 497                        prev_desc_logical_no = curr_desc_logical_no;
 498                        if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
 499                                recover_transaction(prev_desc_logical_no);
 500
 501                        DB_FOUND = NO;
 502                } else if (be32_to_cpu(jdb->h_blocktype) ==
 503                                EXT3_JOURNAL_REVOKE_BLOCK) {
 504                        if (be32_to_cpu(jdb->h_sequence) !=
 505                            be32_to_cpu(jsb->s_sequence)) {
 506                                print_jrnl_status(recovery_flag);
 507                                break;
 508                        }
 509                        if (recovery_flag == SCAN)
 510                                ext4fs_push_revoke_blk((char *)jdb);
 511                        i++;
 512                } else {
 513                        debug("Else Case\n");
 514                        if (be32_to_cpu(jdb->h_sequence) !=
 515                            be32_to_cpu(jsb->s_sequence)) {
 516                                print_jrnl_status(recovery_flag);
 517                                break;
 518                        }
 519                }
 520        }
 521
 522end:
 523        if (recovery_flag == RECOVER) {
 524                uint32_t new_feature_incompat;
 525                jsb->s_start = cpu_to_be32(1);
 526                jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
 527                /* get the superblock */
 528                ext4_read_superblock((char *)fs->sb);
 529                new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
 530                new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
 531                fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
 532
 533                /* Update the super block */
 534                put_ext4((uint64_t) (SUPERBLOCK_SIZE),
 535                         (struct ext2_sblock *)fs->sb,
 536                         (uint32_t) SUPERBLOCK_SIZE);
 537                ext4_read_superblock((char *)fs->sb);
 538
 539                blknr = read_allocated_block(&inode_journal,
 540                                         EXT2_JOURNAL_SUPERBLOCK);
 541                put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
 542                         (struct journal_superblock_t *)temp_buff,
 543                         (uint32_t) fs->blksz);
 544                ext4fs_free_revoke_blks();
 545        }
 546        free(temp_buff);
 547        free(temp_buff1);
 548
 549        return 0;
 550}
 551
 552static void update_descriptor_block(long int blknr)
 553{
 554        int i;
 555        long int jsb_blknr;
 556        struct journal_header_t jdb;
 557        struct ext3_journal_block_tag tag;
 558        struct ext2_inode inode_journal;
 559        struct journal_superblock_t *jsb = NULL;
 560        char *buf = NULL;
 561        char *temp = NULL;
 562        struct ext_filesystem *fs = get_fs();
 563        char *temp_buff = zalloc(fs->blksz);
 564        if (!temp_buff)
 565                return;
 566
 567        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
 568        jsb_blknr = read_allocated_block(&inode_journal,
 569                                         EXT2_JOURNAL_SUPERBLOCK);
 570        ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
 571                       temp_buff);
 572        jsb = (struct journal_superblock_t *) temp_buff;
 573
 574        jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
 575        jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
 576        jdb.h_sequence = jsb->s_sequence;
 577        buf = zalloc(fs->blksz);
 578        if (!buf) {
 579                free(temp_buff);
 580                return;
 581        }
 582        temp = buf;
 583        memcpy(buf, &jdb, sizeof(struct journal_header_t));
 584        temp += sizeof(struct journal_header_t);
 585
 586        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 587                if (journal_ptr[i]->blknr == -1)
 588                        break;
 589
 590                tag.block = cpu_to_be32(journal_ptr[i]->blknr);
 591                tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
 592                memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
 593                temp = temp + sizeof(struct ext3_journal_block_tag);
 594        }
 595
 596        tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
 597        tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
 598        memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
 599               sizeof(struct ext3_journal_block_tag));
 600        put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
 601
 602        free(temp_buff);
 603        free(buf);
 604}
 605
 606static void update_commit_block(long int blknr)
 607{
 608        struct journal_header_t jdb;
 609        struct ext_filesystem *fs = get_fs();
 610        char *buf = NULL;
 611        struct ext2_inode inode_journal;
 612        struct journal_superblock_t *jsb;
 613        long int jsb_blknr;
 614        char *temp_buff = zalloc(fs->blksz);
 615        if (!temp_buff)
 616                return;
 617
 618        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
 619                          &inode_journal);
 620        jsb_blknr = read_allocated_block(&inode_journal,
 621                                         EXT2_JOURNAL_SUPERBLOCK);
 622        ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
 623                       temp_buff);
 624        jsb = (struct journal_superblock_t *) temp_buff;
 625
 626        jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
 627        jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
 628        jdb.h_sequence = jsb->s_sequence;
 629        buf = zalloc(fs->blksz);
 630        if (!buf) {
 631                free(temp_buff);
 632                return;
 633        }
 634        memcpy(buf, &jdb, sizeof(struct journal_header_t));
 635        put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
 636
 637        free(temp_buff);
 638        free(buf);
 639}
 640
 641void ext4fs_update_journal(void)
 642{
 643        struct ext2_inode inode_journal;
 644        struct ext_filesystem *fs = get_fs();
 645        long int blknr;
 646        int i;
 647        ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
 648        blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
 649        update_descriptor_block(blknr);
 650        for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
 651                if (journal_ptr[i]->blknr == -1)
 652                        break;
 653                blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
 654                put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
 655                         journal_ptr[i]->buf, fs->blksz);
 656        }
 657        blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
 658        update_commit_block(blknr);
 659        printf("update journal finished\n");
 660}
 661