Skip to content
Snippets Groups Projects
ext4_journal.c 16.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Uma Shankar's avatar
    Uma Shankar committed
    /*
     * (C) Copyright 2011 - 2012 Samsung Electronics
     * EXT4 filesystem implementation in Uboot by
     * Uma Shankar <uma.shankar@samsung.com>
     * Manjunatha C Achar <a.manjunatha@samsung.com>
     *
     * Journal data structures and headers for Journaling feature of ext4
     * have been referred from JBD2 (Journaling Block device 2)
     * implementation in Linux Kernel.
     * Written by Stephen C. Tweedie <sct@redhat.com>
     *
     * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
    
     * SPDX-License-Identifier:	GPL-2.0+
    
    Uma Shankar's avatar
    Uma Shankar committed
     */
    
    #include <common.h>
    #include <ext4fs.h>
    #include <malloc.h>
    #include <ext_common.h>
    #include "ext4_common.h"
    
    static struct revoke_blk_list *revk_blk_list;
    static struct revoke_blk_list *prev_node;
    
    York Sun's avatar
    York Sun committed
    static int first_node = true;
    
    Uma Shankar's avatar
    Uma Shankar committed
    
    int gindex;
    int gd_index;
    int jrnl_blk_idx;
    struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
    struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
    
    int ext4fs_init_journal(void)
    {
    	int i;
    	char *temp = NULL;
    	struct ext_filesystem *fs = get_fs();
    
    	/* init globals */
    	revk_blk_list = NULL;
    	prev_node = NULL;
    	gindex = 0;
    	gd_index = 0;
    	jrnl_blk_idx = 1;
    
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		journal_ptr[i] = zalloc(sizeof(struct journal_log));
    		if (!journal_ptr[i])
    			goto fail;
    		dirty_block_ptr[i] = zalloc(sizeof(struct dirty_blocks));
    		if (!dirty_block_ptr[i])
    			goto fail;
    		journal_ptr[i]->buf = NULL;
    		journal_ptr[i]->blknr = -1;
    
    		dirty_block_ptr[i]->buf = NULL;
    		dirty_block_ptr[i]->blknr = -1;
    	}
    
    	if (fs->blksz == 4096) {
    		temp = zalloc(fs->blksz);
    		if (!temp)
    			goto fail;
    		journal_ptr[gindex]->buf = zalloc(fs->blksz);
    		if (!journal_ptr[gindex]->buf)
    			goto fail;
    		ext4fs_devread(0, 0, fs->blksz, temp);
    		memcpy(temp + SUPERBLOCK_SIZE, fs->sb, SUPERBLOCK_SIZE);
    		memcpy(journal_ptr[gindex]->buf, temp, fs->blksz);
    		journal_ptr[gindex++]->blknr = 0;
    		free(temp);
    	} else {
    		journal_ptr[gindex]->buf = zalloc(fs->blksz);
    		if (!journal_ptr[gindex]->buf)
    			goto fail;
    		memcpy(journal_ptr[gindex]->buf, fs->sb, SUPERBLOCK_SIZE);
    		journal_ptr[gindex++]->blknr = 1;
    	}
    
    	/* Check the file system state using journal super block */
    	if (ext4fs_check_journal_state(SCAN))
    		goto fail;
    	/* Check the file system state using journal super block */
    	if (ext4fs_check_journal_state(RECOVER))
    		goto fail;
    
    	return 0;
    fail:
    	return -1;
    }
    
    void ext4fs_dump_metadata(void)
    {
    	struct ext_filesystem *fs = get_fs();
    	int i;
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		if (dirty_block_ptr[i]->blknr == -1)
    			break;
    		put_ext4((uint64_t) ((uint64_t)dirty_block_ptr[i]->blknr *
    				(uint64_t)fs->blksz), dirty_block_ptr[i]->buf,
    								fs->blksz);
    	}
    }
    
    void ext4fs_free_journal(void)
    {
    	int i;
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		if (dirty_block_ptr[i]->blknr == -1)
    			break;
    		if (dirty_block_ptr[i]->buf)
    			free(dirty_block_ptr[i]->buf);
    	}
    
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		if (journal_ptr[i]->blknr == -1)
    			break;
    		if (journal_ptr[i]->buf)
    			free(journal_ptr[i]->buf);
    	}
    
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		if (journal_ptr[i])
    			free(journal_ptr[i]);
    		if (dirty_block_ptr[i])
    			free(dirty_block_ptr[i]);
    	}
    	gindex = 0;
    	gd_index = 0;
    	jrnl_blk_idx = 1;
    }
    
    int ext4fs_log_gdt(char *gd_table)
    {
    	struct ext_filesystem *fs = get_fs();
    	short i;
    	long int var = fs->gdtable_blkno;
    	for (i = 0; i < fs->no_blk_pergdt; i++) {
    		journal_ptr[gindex]->buf = zalloc(fs->blksz);
    		if (!journal_ptr[gindex]->buf)
    			return -ENOMEM;
    		memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
    		gd_table += fs->blksz;
    		journal_ptr[gindex++]->blknr = var++;
    	}
    
    	return 0;
    }
    
    /*
     * This function stores the backup copy of meta data in RAM
     * journal_buffer -- Buffer containing meta data
     * blknr -- Block number on disk of the meta data buffer
     */
    
    int ext4fs_log_journal(char *journal_buffer, uint32_t blknr)
    
    Uma Shankar's avatar
    Uma Shankar committed
    {
    	struct ext_filesystem *fs = get_fs();
    	short i;
    
    	if (!journal_buffer) {
    		printf("Invalid input arguments %s\n", __func__);
    		return -EINVAL;
    	}
    
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		if (journal_ptr[i]->blknr == -1)
    			break;
    		if (journal_ptr[i]->blknr == blknr)
    			return 0;
    	}
    
    	journal_ptr[gindex]->buf = zalloc(fs->blksz);
    	if (!journal_ptr[gindex]->buf)
    		return -ENOMEM;
    
    	memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
    	journal_ptr[gindex++]->blknr = blknr;
    
    	return 0;
    }
    
    /*
     * This function stores the modified meta data in RAM
     * metadata_buffer -- Buffer containing meta data
     * blknr -- Block number on disk of the meta data buffer
     */
    
    int ext4fs_put_metadata(char *metadata_buffer, uint32_t blknr)
    
    Uma Shankar's avatar
    Uma Shankar committed
    {
    	struct ext_filesystem *fs = get_fs();
    	if (!metadata_buffer) {
    		printf("Invalid input arguments %s\n", __func__);
    		return -EINVAL;
    	}
    
    	if (dirty_block_ptr[gd_index]->buf)
    		assert(dirty_block_ptr[gd_index]->blknr == blknr);
    	else
    		dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
    
    
    Uma Shankar's avatar
    Uma Shankar committed
    	if (!dirty_block_ptr[gd_index]->buf)
    		return -ENOMEM;
    	memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
    	dirty_block_ptr[gd_index++]->blknr = blknr;
    
    	return 0;
    }
    
    void print_revoke_blks(char *revk_blk)
    {
    	int offset;
    	int max;
    	long int blocknr;
    	struct journal_revoke_header_t *header;
    
    	if (revk_blk == NULL)
    		return;
    
    	header = (struct journal_revoke_header_t *) revk_blk;
    	offset = sizeof(struct journal_revoke_header_t);
    	max = be32_to_cpu(header->r_count);
    	printf("total bytes %d\n", max);
    
    	while (offset < max) {
    
    		blocknr = be32_to_cpu(*((__be32 *)(revk_blk + offset)));
    
    Uma Shankar's avatar
    Uma Shankar committed
    		printf("revoke blknr is %ld\n", blocknr);
    		offset += 4;
    	}
    }
    
    static struct revoke_blk_list *_get_node(void)
    {
    	struct revoke_blk_list *tmp_node;
    	tmp_node = zalloc(sizeof(struct revoke_blk_list));
    	if (tmp_node == NULL)
    		return NULL;
    	tmp_node->content = NULL;
    	tmp_node->next = NULL;
    
    	return tmp_node;
    }
    
    void ext4fs_push_revoke_blk(char *buffer)
    {
    	struct revoke_blk_list *node = NULL;
    	struct ext_filesystem *fs = get_fs();
    	if (buffer == NULL) {
    		printf("buffer ptr is NULL\n");
    		return;
    	}
    	node = _get_node();
    	if (!node) {
    		printf("_get_node: malloc failed\n");
    		return;
    	}
    
    	node->content = zalloc(fs->blksz);
    	if (node->content == NULL)
    		return;
    	memcpy(node->content, buffer, fs->blksz);
    
    
    York Sun's avatar
    York Sun committed
    	if (first_node == true) {
    
    Uma Shankar's avatar
    Uma Shankar committed
    		revk_blk_list = node;
    		prev_node = node;
    
    York Sun's avatar
    York Sun committed
    		 first_node = false;
    
    Uma Shankar's avatar
    Uma Shankar committed
    	} else {
    		prev_node->next = node;
    		prev_node = node;
    	}
    }
    
    void ext4fs_free_revoke_blks(void)
    {
    	struct revoke_blk_list *tmp_node = revk_blk_list;
    	struct revoke_blk_list *next_node = NULL;
    
    	while (tmp_node != NULL) {
    		if (tmp_node->content)
    			free(tmp_node->content);
    		tmp_node = tmp_node->next;
    	}
    
    	tmp_node = revk_blk_list;
    	while (tmp_node != NULL) {
    		next_node = tmp_node->next;
    		free(tmp_node);
    		tmp_node = next_node;
    	}
    
    	revk_blk_list = NULL;
    	prev_node = NULL;
    
    York Sun's avatar
    York Sun committed
    	first_node = true;
    
    Uma Shankar's avatar
    Uma Shankar committed
    }
    
    int check_blknr_for_revoke(long int blknr, int sequence_no)
    {
    	struct journal_revoke_header_t *header;
    	int offset;
    	int max;
    	long int blocknr;
    	char *revk_blk;
    	struct revoke_blk_list *tmp_revk_node = revk_blk_list;
    	while (tmp_revk_node != NULL) {
    		revk_blk = tmp_revk_node->content;
    
    		header = (struct journal_revoke_header_t *) revk_blk;
    		if (sequence_no < be32_to_cpu(header->r_header.h_sequence)) {
    			offset = sizeof(struct journal_revoke_header_t);
    			max = be32_to_cpu(header->r_count);
    
    			while (offset < max) {
    
    				blocknr = be32_to_cpu(*((__be32 *)
    
    Uma Shankar's avatar
    Uma Shankar committed
    						  (revk_blk + offset)));
    				if (blocknr == blknr)
    					goto found;
    				offset += 4;
    			}
    		}
    		tmp_revk_node = tmp_revk_node->next;
    	}
    
    	return -1;
    
    found:
    	return 0;
    }
    
    /*
     * This function parses the journal blocks and replays the
     * suceessful transactions. A transaction is successfull
     * if commit block is found for a descriptor block
     * The tags in descriptor block contain the disk block
     * numbers of the metadata  to be replayed
     */
    void recover_transaction(int prev_desc_logical_no)
    {
    	struct ext2_inode inode_journal;
    	struct ext_filesystem *fs = get_fs();
    	struct journal_header_t *jdb;
    	long int blknr;
    	char *p_jdb;
    	int ofs, flags;
    	int i;
    	struct ext3_journal_block_tag *tag;
    	char *temp_buff = zalloc(fs->blksz);
    	char *metadata_buff = zalloc(fs->blksz);
    	if (!temp_buff || !metadata_buff)
    		goto fail;
    	i = prev_desc_logical_no;
    	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
    			  (struct ext2_inode *)&inode_journal);
    	blknr = read_allocated_block((struct ext2_inode *)
    				     &inode_journal, i);
    
    	ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
    		       temp_buff);
    
    Uma Shankar's avatar
    Uma Shankar committed
    	p_jdb = (char *)temp_buff;
    	jdb = (struct journal_header_t *) temp_buff;
    	ofs = sizeof(struct journal_header_t);
    
    	do {
    		tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
    		ofs += sizeof(struct ext3_journal_block_tag);
    
    		if (ofs > fs->blksz)
    			break;
    
    		flags = be32_to_cpu(tag->flags);
    		if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
    			ofs += 16;
    
    		i++;
    		debug("\t\ttag %u\n", be32_to_cpu(tag->block));
    		if (revk_blk_list != NULL) {
    			if (check_blknr_for_revoke(be32_to_cpu(tag->block),
    				be32_to_cpu(jdb->h_sequence)) == 0)
    				continue;
    		}
    		blknr = read_allocated_block(&inode_journal, i);
    
    		ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
    
    Uma Shankar's avatar
    Uma Shankar committed
    			       fs->blksz, metadata_buff);
    
    		put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
    
    Uma Shankar's avatar
    Uma Shankar committed
    			 metadata_buff, (uint32_t) fs->blksz);
    	} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
    fail:
    	free(temp_buff);
    	free(metadata_buff);
    }
    
    void print_jrnl_status(int recovery_flag)
    {
    	if (recovery_flag == RECOVER)
    		printf("Journal Recovery Completed\n");
    	else
    		printf("Journal Scan Completed\n");
    }
    
    int ext4fs_check_journal_state(int recovery_flag)
    {
    	int i;
    	int DB_FOUND = NO;
    	long int blknr;
    	int transaction_state = TRANSACTION_COMPLETE;
    	int prev_desc_logical_no = 0;
    	int curr_desc_logical_no = 0;
    
    Uma Shankar's avatar
    Uma Shankar committed
    	struct ext2_inode inode_journal;
    	struct journal_superblock_t *jsb = NULL;
    	struct journal_header_t *jdb = NULL;
    	char *p_jdb = NULL;
    	struct ext3_journal_block_tag *tag = NULL;
    	char *temp_buff = NULL;
    	char *temp_buff1 = NULL;
    	struct ext_filesystem *fs = get_fs();
    
    	temp_buff = zalloc(fs->blksz);
    	if (!temp_buff)
    		return -ENOMEM;
    	temp_buff1 = zalloc(fs->blksz);
    	if (!temp_buff1) {
    		free(temp_buff);
    		return -ENOMEM;
    	}
    
    	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
    	blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
    
    	ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
    		       temp_buff);
    
    Uma Shankar's avatar
    Uma Shankar committed
    	jsb = (struct journal_superblock_t *) temp_buff;
    
    
    	if (le32_to_cpu(fs->sb->feature_incompat) & EXT3_FEATURE_INCOMPAT_RECOVER) {
    
    Uma Shankar's avatar
    Uma Shankar committed
    		if (recovery_flag == RECOVER)
    			printf("Recovery required\n");
    	} else {
    		if (recovery_flag == RECOVER)
    			printf("File System is consistent\n");
    		goto end;
    	}
    
    	if (be32_to_cpu(jsb->s_start) == 0)
    		goto end;
    
    	if (!(jsb->s_feature_compat &
    				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM)))
    		jsb->s_feature_compat |=
    				cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
    
    	i = be32_to_cpu(jsb->s_first);
    	while (1) {
    		blknr = read_allocated_block(&inode_journal, i);
    		memset(temp_buff1, '\0', fs->blksz);
    
    		ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
    
    Uma Shankar's avatar
    Uma Shankar committed
    			       0, fs->blksz, temp_buff1);
    		jdb = (struct journal_header_t *) temp_buff1;
    
    		if (be32_to_cpu(jdb->h_blocktype) ==
    		    EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
    			if (be32_to_cpu(jdb->h_sequence) !=
    			    be32_to_cpu(jsb->s_sequence)) {
    				print_jrnl_status(recovery_flag);
    				break;
    			}
    
    			curr_desc_logical_no = i;
    			if (transaction_state == TRANSACTION_COMPLETE)
    				transaction_state = TRANSACTION_RUNNING;
    			else
    				return -1;
    			p_jdb = (char *)temp_buff1;
    			ofs = sizeof(struct journal_header_t);
    			do {
    				tag = (struct ext3_journal_block_tag *)
    				    &p_jdb[ofs];
    				ofs += sizeof(struct ext3_journal_block_tag);
    				if (ofs > fs->blksz)
    					break;
    				flags = be32_to_cpu(tag->flags);
    				if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
    					ofs += 16;
    				i++;
    				debug("\t\ttag %u\n", be32_to_cpu(tag->block));
    			} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
    			i++;
    			DB_FOUND = YES;
    		} else if (be32_to_cpu(jdb->h_blocktype) ==
    				EXT3_JOURNAL_COMMIT_BLOCK) {
    			if (be32_to_cpu(jdb->h_sequence) !=
    			     be32_to_cpu(jsb->s_sequence)) {
    				print_jrnl_status(recovery_flag);
    				break;
    			}
    
    			if (transaction_state == TRANSACTION_RUNNING ||
    					(DB_FOUND == NO)) {
    				transaction_state = TRANSACTION_COMPLETE;
    				i++;
    				jsb->s_sequence =
    					cpu_to_be32(be32_to_cpu(
    						jsb->s_sequence) + 1);
    			}
    			prev_desc_logical_no = curr_desc_logical_no;
    			if ((recovery_flag == RECOVER) && (DB_FOUND == YES))
    				recover_transaction(prev_desc_logical_no);
    
    			DB_FOUND = NO;
    		} else if (be32_to_cpu(jdb->h_blocktype) ==
    				EXT3_JOURNAL_REVOKE_BLOCK) {
    			if (be32_to_cpu(jdb->h_sequence) !=
    			    be32_to_cpu(jsb->s_sequence)) {
    				print_jrnl_status(recovery_flag);
    				break;
    			}
    			if (recovery_flag == SCAN)
    				ext4fs_push_revoke_blk((char *)jdb);
    			i++;
    		} else {
    			debug("Else Case\n");
    			if (be32_to_cpu(jdb->h_sequence) !=
    			    be32_to_cpu(jsb->s_sequence)) {
    				print_jrnl_status(recovery_flag);
    				break;
    			}
    		}
    	}
    
    end:
    	if (recovery_flag == RECOVER) {
    
    		uint32_t new_feature_incompat;
    
    Uma Shankar's avatar
    Uma Shankar committed
    		jsb->s_start = cpu_to_be32(1);
    		jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1);
    		/* get the superblock */
    
    		ext4_read_superblock((char *)fs->sb);
    
    		new_feature_incompat = le32_to_cpu(fs->sb->feature_incompat);
    		new_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
    		fs->sb->feature_incompat = cpu_to_le32(new_feature_incompat);
    
    Uma Shankar's avatar
    Uma Shankar committed
    
    		/* Update the super block */
    		put_ext4((uint64_t) (SUPERBLOCK_SIZE),
    			 (struct ext2_sblock *)fs->sb,
    			 (uint32_t) SUPERBLOCK_SIZE);
    
    		ext4_read_superblock((char *)fs->sb);
    
    Uma Shankar's avatar
    Uma Shankar committed
    
    		blknr = read_allocated_block(&inode_journal,
    					 EXT2_JOURNAL_SUPERBLOCK);
    
    		put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
    
    Uma Shankar's avatar
    Uma Shankar committed
    			 (struct journal_superblock_t *)temp_buff,
    			 (uint32_t) fs->blksz);
    		ext4fs_free_revoke_blks();
    	}
    	free(temp_buff);
    	free(temp_buff1);
    
    	return 0;
    }
    
    static void update_descriptor_block(long int blknr)
    {
    	int i;
    	long int jsb_blknr;
    	struct journal_header_t jdb;
    	struct ext3_journal_block_tag tag;
    	struct ext2_inode inode_journal;
    	struct journal_superblock_t *jsb = NULL;
    	char *buf = NULL;
    	char *temp = NULL;
    	struct ext_filesystem *fs = get_fs();
    	char *temp_buff = zalloc(fs->blksz);
    	if (!temp_buff)
    		return;
    
    	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
    	jsb_blknr = read_allocated_block(&inode_journal,
    					 EXT2_JOURNAL_SUPERBLOCK);
    
    	ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
    		       temp_buff);
    
    Uma Shankar's avatar
    Uma Shankar committed
    	jsb = (struct journal_superblock_t *) temp_buff;
    
    	jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
    	jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
    	jdb.h_sequence = jsb->s_sequence;
    	buf = zalloc(fs->blksz);
    	if (!buf) {
    		free(temp_buff);
    		return;
    	}
    	temp = buf;
    	memcpy(buf, &jdb, sizeof(struct journal_header_t));
    	temp += sizeof(struct journal_header_t);
    
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		if (journal_ptr[i]->blknr == -1)
    			break;
    
    		tag.block = cpu_to_be32(journal_ptr[i]->blknr);
    		tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_SAME_UUID);
    		memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
    		temp = temp + sizeof(struct ext3_journal_block_tag);
    	}
    
    	tag.block = cpu_to_be32(journal_ptr[--i]->blknr);
    	tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
    	memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
    	       sizeof(struct ext3_journal_block_tag));
    
    	put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
    
    Uma Shankar's avatar
    Uma Shankar committed
    
    	free(temp_buff);
    	free(buf);
    }
    
    static void update_commit_block(long int blknr)
    {
    	struct journal_header_t jdb;
    	struct ext_filesystem *fs = get_fs();
    	char *buf = NULL;
    	struct ext2_inode inode_journal;
    	struct journal_superblock_t *jsb;
    	long int jsb_blknr;
    	char *temp_buff = zalloc(fs->blksz);
    	if (!temp_buff)
    		return;
    
    
    	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
    			  &inode_journal);
    
    Uma Shankar's avatar
    Uma Shankar committed
    	jsb_blknr = read_allocated_block(&inode_journal,
    					 EXT2_JOURNAL_SUPERBLOCK);
    
    	ext4fs_devread((lbaint_t)jsb_blknr * fs->sect_perblk, 0, fs->blksz,
    		       temp_buff);
    
    Uma Shankar's avatar
    Uma Shankar committed
    	jsb = (struct journal_superblock_t *) temp_buff;
    
    	jdb.h_blocktype = cpu_to_be32(EXT3_JOURNAL_COMMIT_BLOCK);
    	jdb.h_magic = cpu_to_be32(EXT3_JOURNAL_MAGIC_NUMBER);
    	jdb.h_sequence = jsb->s_sequence;
    	buf = zalloc(fs->blksz);
    	if (!buf) {
    		free(temp_buff);
    		return;
    	}
    	memcpy(buf, &jdb, sizeof(struct journal_header_t));
    
    	put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
    
    Uma Shankar's avatar
    Uma Shankar committed
    
    	free(temp_buff);
    	free(buf);
    }
    
    void ext4fs_update_journal(void)
    {
    	struct ext2_inode inode_journal;
    	struct ext_filesystem *fs = get_fs();
    	long int blknr;
    	int i;
    	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
    	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
    	update_descriptor_block(blknr);
    	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
    		if (journal_ptr[i]->blknr == -1)
    			break;
    		blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
    		put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
    			 journal_ptr[i]->buf, fs->blksz);
    	}
    	blknr = read_allocated_block(&inode_journal, jrnl_blk_idx++);
    	update_commit_block(blknr);
    	printf("update journal finished\n");
    }