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