1a1596438SUma Shankar /* 2a1596438SUma Shankar * (C) Copyright 2011 - 2012 Samsung Electronics 3a1596438SUma Shankar * EXT4 filesystem implementation in Uboot by 4a1596438SUma Shankar * Uma Shankar <uma.shankar@samsung.com> 5a1596438SUma Shankar * Manjunatha C Achar <a.manjunatha@samsung.com> 6a1596438SUma Shankar * 7a1596438SUma Shankar * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. 8a1596438SUma Shankar * Ext4 read optimization taken from Open-Moko 9a1596438SUma Shankar * Qi bootloader 10a1596438SUma Shankar * 11a1596438SUma Shankar * (C) Copyright 2004 12a1596438SUma Shankar * esd gmbh <www.esd-electronics.com> 13a1596438SUma Shankar * Reinhard Arlt <reinhard.arlt@esd-electronics.com> 14a1596438SUma Shankar * 15a1596438SUma Shankar * based on code from grub2 fs/ext2.c and fs/fshelp.c by 16a1596438SUma Shankar * GRUB -- GRand Unified Bootloader 17a1596438SUma Shankar * Copyright (C) 2003, 2004 Free Software Foundation, Inc. 18a1596438SUma Shankar * 19*ed34f34dSUma Shankar * ext4write : Based on generic ext4 protocol. 20*ed34f34dSUma Shankar * 21a1596438SUma Shankar * This program is free software; you can redistribute it and/or modify 22a1596438SUma Shankar * it under the terms of the GNU General Public License as published by 23a1596438SUma Shankar * the Free Software Foundation; either version 2 of the License, or 24a1596438SUma Shankar * (at your option) any later version. 25a1596438SUma Shankar * 26a1596438SUma Shankar * This program is distributed in the hope that it will be useful, 27a1596438SUma Shankar * but WITHOUT ANY WARRANTY; without even the implied warranty of 28a1596438SUma Shankar * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29a1596438SUma Shankar * GNU General Public License for more details. 30a1596438SUma Shankar * 31a1596438SUma Shankar * You should have received a copy of the GNU General Public License 32a1596438SUma Shankar * along with this program; if not, write to the Free Software 33a1596438SUma Shankar * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 34a1596438SUma Shankar */ 35a1596438SUma Shankar 36a1596438SUma Shankar #include <common.h> 37a1596438SUma Shankar #include <malloc.h> 38a1596438SUma Shankar #include <ext_common.h> 39a1596438SUma Shankar #include <ext4fs.h> 40a1596438SUma Shankar #include <linux/stat.h> 41a1596438SUma Shankar #include <linux/time.h> 42a1596438SUma Shankar #include <asm/byteorder.h> 43a1596438SUma Shankar #include "ext4_common.h" 44a1596438SUma Shankar 45a1596438SUma Shankar int ext4fs_symlinknest; 46a1596438SUma Shankar block_dev_desc_t *ext4_dev_desc; 47a1596438SUma Shankar 48a1596438SUma Shankar struct ext_filesystem *get_fs(void) 49a1596438SUma Shankar { 50a1596438SUma Shankar if (ext4_dev_desc == NULL || ext4_dev_desc->priv == NULL) 51a1596438SUma Shankar printf("Invalid Input Arguments %s\n", __func__); 52a1596438SUma Shankar 53a1596438SUma Shankar return ext4_dev_desc->priv; 54a1596438SUma Shankar } 55a1596438SUma Shankar 56a1596438SUma Shankar int init_fs(block_dev_desc_t *dev_desc) 57a1596438SUma Shankar { 58a1596438SUma Shankar struct ext_filesystem *fs; 59a1596438SUma Shankar if (dev_desc == NULL) { 60a1596438SUma Shankar printf("Invalid Input Arguments %s\n", __func__); 61a1596438SUma Shankar return -EINVAL; 62a1596438SUma Shankar } 63a1596438SUma Shankar 64a1596438SUma Shankar fs = zalloc(sizeof(struct ext_filesystem)); 65a1596438SUma Shankar if (fs == NULL) { 66a1596438SUma Shankar printf("malloc failed: %s\n", __func__); 67a1596438SUma Shankar return -ENOMEM; 68a1596438SUma Shankar } 69a1596438SUma Shankar 70a1596438SUma Shankar fs->dev_desc = dev_desc; 71a1596438SUma Shankar dev_desc->priv = fs; 72a1596438SUma Shankar 73a1596438SUma Shankar return 0; 74a1596438SUma Shankar } 75a1596438SUma Shankar 76a1596438SUma Shankar void deinit_fs(block_dev_desc_t *dev_desc) 77a1596438SUma Shankar { 78a1596438SUma Shankar if (dev_desc == NULL) { 79a1596438SUma Shankar printf("Invalid Input Arguments %s\n", __func__); 80a1596438SUma Shankar return; 81a1596438SUma Shankar } 82a1596438SUma Shankar free(dev_desc->priv); 83a1596438SUma Shankar dev_desc->priv = NULL; 84a1596438SUma Shankar } 85a1596438SUma Shankar 86a1596438SUma Shankar void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) 87a1596438SUma Shankar { 88a1596438SUma Shankar if ((node != &ext4fs_root->diropen) && (node != currroot)) 89a1596438SUma Shankar free(node); 90a1596438SUma Shankar } 91a1596438SUma Shankar 92a1596438SUma Shankar /* 93a1596438SUma Shankar * Taken from openmoko-kernel mailing list: By Andy green 94a1596438SUma Shankar * Optimized read file API : collects and defers contiguous sector 95a1596438SUma Shankar * reads into one potentially more efficient larger sequential read action 96a1596438SUma Shankar */ 97a1596438SUma Shankar int ext4fs_read_file(struct ext2fs_node *node, int pos, 98a1596438SUma Shankar unsigned int len, char *buf) 99a1596438SUma Shankar { 100a1596438SUma Shankar int i; 101a1596438SUma Shankar int blockcnt; 102a1596438SUma Shankar int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data); 103a1596438SUma Shankar int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS); 104a1596438SUma Shankar unsigned int filesize = __le32_to_cpu(node->inode.size); 105a1596438SUma Shankar int previous_block_number = -1; 106a1596438SUma Shankar int delayed_start = 0; 107a1596438SUma Shankar int delayed_extent = 0; 108a1596438SUma Shankar int delayed_skipfirst = 0; 109a1596438SUma Shankar int delayed_next = 0; 110a1596438SUma Shankar char *delayed_buf = NULL; 111a1596438SUma Shankar short status; 112a1596438SUma Shankar 113a1596438SUma Shankar /* Adjust len so it we can't read past the end of the file. */ 114a1596438SUma Shankar if (len > filesize) 115a1596438SUma Shankar len = filesize; 116a1596438SUma Shankar 117a1596438SUma Shankar blockcnt = ((len + pos) + blocksize - 1) / blocksize; 118a1596438SUma Shankar 119a1596438SUma Shankar for (i = pos / blocksize; i < blockcnt; i++) { 120a1596438SUma Shankar int blknr; 121a1596438SUma Shankar int blockoff = pos % blocksize; 122a1596438SUma Shankar int blockend = blocksize; 123a1596438SUma Shankar int skipfirst = 0; 124a1596438SUma Shankar blknr = read_allocated_block(&(node->inode), i); 125a1596438SUma Shankar if (blknr < 0) 126a1596438SUma Shankar return -1; 127a1596438SUma Shankar 128a1596438SUma Shankar blknr = blknr << log2blocksize; 129a1596438SUma Shankar 130a1596438SUma Shankar /* Last block. */ 131a1596438SUma Shankar if (i == blockcnt - 1) { 132a1596438SUma Shankar blockend = (len + pos) % blocksize; 133a1596438SUma Shankar 134a1596438SUma Shankar /* The last portion is exactly blocksize. */ 135a1596438SUma Shankar if (!blockend) 136a1596438SUma Shankar blockend = blocksize; 137a1596438SUma Shankar } 138a1596438SUma Shankar 139a1596438SUma Shankar /* First block. */ 140a1596438SUma Shankar if (i == pos / blocksize) { 141a1596438SUma Shankar skipfirst = blockoff; 142a1596438SUma Shankar blockend -= skipfirst; 143a1596438SUma Shankar } 144a1596438SUma Shankar if (blknr) { 145a1596438SUma Shankar int status; 146a1596438SUma Shankar 147a1596438SUma Shankar if (previous_block_number != -1) { 148a1596438SUma Shankar if (delayed_next == blknr) { 149a1596438SUma Shankar delayed_extent += blockend; 150a1596438SUma Shankar delayed_next += blockend >> SECTOR_BITS; 151a1596438SUma Shankar } else { /* spill */ 152a1596438SUma Shankar status = ext4fs_devread(delayed_start, 153a1596438SUma Shankar delayed_skipfirst, 154a1596438SUma Shankar delayed_extent, 155a1596438SUma Shankar delayed_buf); 156a1596438SUma Shankar if (status == 0) 157a1596438SUma Shankar return -1; 158a1596438SUma Shankar previous_block_number = blknr; 159a1596438SUma Shankar delayed_start = blknr; 160a1596438SUma Shankar delayed_extent = blockend; 161a1596438SUma Shankar delayed_skipfirst = skipfirst; 162a1596438SUma Shankar delayed_buf = buf; 163a1596438SUma Shankar delayed_next = blknr + 164a1596438SUma Shankar (blockend >> SECTOR_BITS); 165a1596438SUma Shankar } 166a1596438SUma Shankar } else { 167a1596438SUma Shankar previous_block_number = blknr; 168a1596438SUma Shankar delayed_start = blknr; 169a1596438SUma Shankar delayed_extent = blockend; 170a1596438SUma Shankar delayed_skipfirst = skipfirst; 171a1596438SUma Shankar delayed_buf = buf; 172a1596438SUma Shankar delayed_next = blknr + 173a1596438SUma Shankar (blockend >> SECTOR_BITS); 174a1596438SUma Shankar } 175a1596438SUma Shankar } else { 176a1596438SUma Shankar if (previous_block_number != -1) { 177a1596438SUma Shankar /* spill */ 178a1596438SUma Shankar status = ext4fs_devread(delayed_start, 179a1596438SUma Shankar delayed_skipfirst, 180a1596438SUma Shankar delayed_extent, 181a1596438SUma Shankar delayed_buf); 182a1596438SUma Shankar if (status == 0) 183a1596438SUma Shankar return -1; 184a1596438SUma Shankar previous_block_number = -1; 185a1596438SUma Shankar } 186a1596438SUma Shankar memset(buf, 0, blocksize - skipfirst); 187a1596438SUma Shankar } 188a1596438SUma Shankar buf += blocksize - skipfirst; 189a1596438SUma Shankar } 190a1596438SUma Shankar if (previous_block_number != -1) { 191a1596438SUma Shankar /* spill */ 192a1596438SUma Shankar status = ext4fs_devread(delayed_start, 193a1596438SUma Shankar delayed_skipfirst, delayed_extent, 194a1596438SUma Shankar delayed_buf); 195a1596438SUma Shankar if (status == 0) 196a1596438SUma Shankar return -1; 197a1596438SUma Shankar previous_block_number = -1; 198a1596438SUma Shankar } 199a1596438SUma Shankar 200a1596438SUma Shankar return len; 201a1596438SUma Shankar } 202a1596438SUma Shankar 203a1596438SUma Shankar int ext4fs_ls(const char *dirname) 204a1596438SUma Shankar { 205a1596438SUma Shankar struct ext2fs_node *dirnode; 206a1596438SUma Shankar int status; 207a1596438SUma Shankar 208a1596438SUma Shankar if (dirname == NULL) 209a1596438SUma Shankar return 0; 210a1596438SUma Shankar 211a1596438SUma Shankar status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode, 212a1596438SUma Shankar FILETYPE_DIRECTORY); 213a1596438SUma Shankar if (status != 1) { 214a1596438SUma Shankar printf("** Can not find directory. **\n"); 215a1596438SUma Shankar return 1; 216a1596438SUma Shankar } 217a1596438SUma Shankar 218a1596438SUma Shankar ext4fs_iterate_dir(dirnode, NULL, NULL, NULL); 219a1596438SUma Shankar ext4fs_free_node(dirnode, &ext4fs_root->diropen); 220a1596438SUma Shankar 221a1596438SUma Shankar return 0; 222a1596438SUma Shankar } 223a1596438SUma Shankar 224a1596438SUma Shankar int ext4fs_read(char *buf, unsigned len) 225a1596438SUma Shankar { 226a1596438SUma Shankar if (ext4fs_root == NULL || ext4fs_file == NULL) 227a1596438SUma Shankar return 0; 228a1596438SUma Shankar 229a1596438SUma Shankar return ext4fs_read_file(ext4fs_file, 0, len, buf); 230a1596438SUma Shankar } 231*ed34f34dSUma Shankar 232*ed34f34dSUma Shankar #if defined(CONFIG_CMD_EXT4_WRITE) 233*ed34f34dSUma Shankar static void ext4fs_update(void) 234*ed34f34dSUma Shankar { 235*ed34f34dSUma Shankar short i; 236*ed34f34dSUma Shankar ext4fs_update_journal(); 237*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 238*ed34f34dSUma Shankar 239*ed34f34dSUma Shankar /* update super block */ 240*ed34f34dSUma Shankar put_ext4((uint64_t)(SUPERBLOCK_SIZE), 241*ed34f34dSUma Shankar (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); 242*ed34f34dSUma Shankar 243*ed34f34dSUma Shankar /* update block groups */ 244*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 245*ed34f34dSUma Shankar fs->gd[i].bg_checksum = ext4fs_checksum_update(i); 246*ed34f34dSUma Shankar put_ext4((uint64_t)(fs->gd[i].block_id * fs->blksz), 247*ed34f34dSUma Shankar fs->blk_bmaps[i], fs->blksz); 248*ed34f34dSUma Shankar } 249*ed34f34dSUma Shankar 250*ed34f34dSUma Shankar /* update inode table groups */ 251*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 252*ed34f34dSUma Shankar put_ext4((uint64_t) (fs->gd[i].inode_id * fs->blksz), 253*ed34f34dSUma Shankar fs->inode_bmaps[i], fs->blksz); 254*ed34f34dSUma Shankar } 255*ed34f34dSUma Shankar 256*ed34f34dSUma Shankar /* update the block group descriptor table */ 257*ed34f34dSUma Shankar put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz), 258*ed34f34dSUma Shankar (struct ext2_block_group *)fs->gdtable, 259*ed34f34dSUma Shankar (fs->blksz * fs->no_blk_pergdt)); 260*ed34f34dSUma Shankar 261*ed34f34dSUma Shankar ext4fs_dump_metadata(); 262*ed34f34dSUma Shankar 263*ed34f34dSUma Shankar gindex = 0; 264*ed34f34dSUma Shankar gd_index = 0; 265*ed34f34dSUma Shankar } 266*ed34f34dSUma Shankar 267*ed34f34dSUma Shankar int ext4fs_get_bgdtable(void) 268*ed34f34dSUma Shankar { 269*ed34f34dSUma Shankar int status; 270*ed34f34dSUma Shankar int grp_desc_size; 271*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 272*ed34f34dSUma Shankar grp_desc_size = sizeof(struct ext2_block_group); 273*ed34f34dSUma Shankar fs->no_blk_pergdt = (fs->no_blkgrp * grp_desc_size) / fs->blksz; 274*ed34f34dSUma Shankar if ((fs->no_blkgrp * grp_desc_size) % fs->blksz) 275*ed34f34dSUma Shankar fs->no_blk_pergdt++; 276*ed34f34dSUma Shankar 277*ed34f34dSUma Shankar /* allocate memory for gdtable */ 278*ed34f34dSUma Shankar fs->gdtable = zalloc(fs->blksz * fs->no_blk_pergdt); 279*ed34f34dSUma Shankar if (!fs->gdtable) 280*ed34f34dSUma Shankar return -ENOMEM; 281*ed34f34dSUma Shankar /* read the group descriptor table */ 282*ed34f34dSUma Shankar status = ext4fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0, 283*ed34f34dSUma Shankar fs->blksz * fs->no_blk_pergdt, fs->gdtable); 284*ed34f34dSUma Shankar if (status == 0) 285*ed34f34dSUma Shankar goto fail; 286*ed34f34dSUma Shankar 287*ed34f34dSUma Shankar if (ext4fs_log_gdt(fs->gdtable)) { 288*ed34f34dSUma Shankar printf("Error in ext4fs_log_gdt\n"); 289*ed34f34dSUma Shankar return -1; 290*ed34f34dSUma Shankar } 291*ed34f34dSUma Shankar 292*ed34f34dSUma Shankar return 0; 293*ed34f34dSUma Shankar fail: 294*ed34f34dSUma Shankar free(fs->gdtable); 295*ed34f34dSUma Shankar fs->gdtable = NULL; 296*ed34f34dSUma Shankar 297*ed34f34dSUma Shankar return -1; 298*ed34f34dSUma Shankar } 299*ed34f34dSUma Shankar 300*ed34f34dSUma Shankar static void delete_single_indirect_block(struct ext2_inode *inode) 301*ed34f34dSUma Shankar { 302*ed34f34dSUma Shankar struct ext2_block_group *gd = NULL; 303*ed34f34dSUma Shankar static int prev_bg_bmap_idx = -1; 304*ed34f34dSUma Shankar long int blknr; 305*ed34f34dSUma Shankar int remainder; 306*ed34f34dSUma Shankar int bg_idx; 307*ed34f34dSUma Shankar int status; 308*ed34f34dSUma Shankar unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 309*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 310*ed34f34dSUma Shankar char *journal_buffer = zalloc(fs->blksz); 311*ed34f34dSUma Shankar if (!journal_buffer) { 312*ed34f34dSUma Shankar printf("No memory\n"); 313*ed34f34dSUma Shankar return; 314*ed34f34dSUma Shankar } 315*ed34f34dSUma Shankar /* get block group descriptor table */ 316*ed34f34dSUma Shankar gd = (struct ext2_block_group *)fs->gdtable; 317*ed34f34dSUma Shankar 318*ed34f34dSUma Shankar /* deleting the single indirect block associated with inode */ 319*ed34f34dSUma Shankar if (inode->b.blocks.indir_block != 0) { 320*ed34f34dSUma Shankar debug("SIPB releasing %u\n", inode->b.blocks.indir_block); 321*ed34f34dSUma Shankar blknr = inode->b.blocks.indir_block; 322*ed34f34dSUma Shankar if (fs->blksz != 1024) { 323*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 324*ed34f34dSUma Shankar } else { 325*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 326*ed34f34dSUma Shankar remainder = blknr % blk_per_grp; 327*ed34f34dSUma Shankar if (!remainder) 328*ed34f34dSUma Shankar bg_idx--; 329*ed34f34dSUma Shankar } 330*ed34f34dSUma Shankar ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); 331*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 332*ed34f34dSUma Shankar fs->sb->free_blocks++; 333*ed34f34dSUma Shankar /* journal backup */ 334*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 335*ed34f34dSUma Shankar status = 336*ed34f34dSUma Shankar ext4fs_devread(gd[bg_idx].block_id * 337*ed34f34dSUma Shankar fs->sect_perblk, 0, fs->blksz, 338*ed34f34dSUma Shankar journal_buffer); 339*ed34f34dSUma Shankar if (status == 0) 340*ed34f34dSUma Shankar goto fail; 341*ed34f34dSUma Shankar if (ext4fs_log_journal 342*ed34f34dSUma Shankar (journal_buffer, gd[bg_idx].block_id)) 343*ed34f34dSUma Shankar goto fail; 344*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 345*ed34f34dSUma Shankar } 346*ed34f34dSUma Shankar } 347*ed34f34dSUma Shankar fail: 348*ed34f34dSUma Shankar free(journal_buffer); 349*ed34f34dSUma Shankar } 350*ed34f34dSUma Shankar 351*ed34f34dSUma Shankar static void delete_double_indirect_block(struct ext2_inode *inode) 352*ed34f34dSUma Shankar { 353*ed34f34dSUma Shankar int i; 354*ed34f34dSUma Shankar short status; 355*ed34f34dSUma Shankar static int prev_bg_bmap_idx = -1; 356*ed34f34dSUma Shankar long int blknr; 357*ed34f34dSUma Shankar int remainder; 358*ed34f34dSUma Shankar int bg_idx; 359*ed34f34dSUma Shankar unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 360*ed34f34dSUma Shankar unsigned int *di_buffer = NULL; 361*ed34f34dSUma Shankar unsigned int *DIB_start_addr = NULL; 362*ed34f34dSUma Shankar struct ext2_block_group *gd = NULL; 363*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 364*ed34f34dSUma Shankar char *journal_buffer = zalloc(fs->blksz); 365*ed34f34dSUma Shankar if (!journal_buffer) { 366*ed34f34dSUma Shankar printf("No memory\n"); 367*ed34f34dSUma Shankar return; 368*ed34f34dSUma Shankar } 369*ed34f34dSUma Shankar /* get the block group descriptor table */ 370*ed34f34dSUma Shankar gd = (struct ext2_block_group *)fs->gdtable; 371*ed34f34dSUma Shankar 372*ed34f34dSUma Shankar if (inode->b.blocks.double_indir_block != 0) { 373*ed34f34dSUma Shankar di_buffer = zalloc(fs->blksz); 374*ed34f34dSUma Shankar if (!di_buffer) { 375*ed34f34dSUma Shankar printf("No memory\n"); 376*ed34f34dSUma Shankar return; 377*ed34f34dSUma Shankar } 378*ed34f34dSUma Shankar DIB_start_addr = (unsigned int *)di_buffer; 379*ed34f34dSUma Shankar blknr = inode->b.blocks.double_indir_block; 380*ed34f34dSUma Shankar status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, 381*ed34f34dSUma Shankar (char *)di_buffer); 382*ed34f34dSUma Shankar for (i = 0; i < fs->blksz / sizeof(int); i++) { 383*ed34f34dSUma Shankar if (*di_buffer == 0) 384*ed34f34dSUma Shankar break; 385*ed34f34dSUma Shankar 386*ed34f34dSUma Shankar debug("DICB releasing %u\n", *di_buffer); 387*ed34f34dSUma Shankar if (fs->blksz != 1024) { 388*ed34f34dSUma Shankar bg_idx = (*di_buffer) / blk_per_grp; 389*ed34f34dSUma Shankar } else { 390*ed34f34dSUma Shankar bg_idx = (*di_buffer) / blk_per_grp; 391*ed34f34dSUma Shankar remainder = (*di_buffer) % blk_per_grp; 392*ed34f34dSUma Shankar if (!remainder) 393*ed34f34dSUma Shankar bg_idx--; 394*ed34f34dSUma Shankar } 395*ed34f34dSUma Shankar ext4fs_reset_block_bmap(*di_buffer, 396*ed34f34dSUma Shankar fs->blk_bmaps[bg_idx], bg_idx); 397*ed34f34dSUma Shankar di_buffer++; 398*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 399*ed34f34dSUma Shankar fs->sb->free_blocks++; 400*ed34f34dSUma Shankar /* journal backup */ 401*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 402*ed34f34dSUma Shankar status = ext4fs_devread(gd[bg_idx].block_id 403*ed34f34dSUma Shankar * fs->sect_perblk, 0, 404*ed34f34dSUma Shankar fs->blksz, 405*ed34f34dSUma Shankar journal_buffer); 406*ed34f34dSUma Shankar if (status == 0) 407*ed34f34dSUma Shankar goto fail; 408*ed34f34dSUma Shankar 409*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, 410*ed34f34dSUma Shankar gd[bg_idx].block_id)) 411*ed34f34dSUma Shankar goto fail; 412*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 413*ed34f34dSUma Shankar } 414*ed34f34dSUma Shankar } 415*ed34f34dSUma Shankar 416*ed34f34dSUma Shankar /* removing the parent double indirect block */ 417*ed34f34dSUma Shankar blknr = inode->b.blocks.double_indir_block; 418*ed34f34dSUma Shankar if (fs->blksz != 1024) { 419*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 420*ed34f34dSUma Shankar } else { 421*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 422*ed34f34dSUma Shankar remainder = blknr % blk_per_grp; 423*ed34f34dSUma Shankar if (!remainder) 424*ed34f34dSUma Shankar bg_idx--; 425*ed34f34dSUma Shankar } 426*ed34f34dSUma Shankar ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); 427*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 428*ed34f34dSUma Shankar fs->sb->free_blocks++; 429*ed34f34dSUma Shankar /* journal backup */ 430*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 431*ed34f34dSUma Shankar memset(journal_buffer, '\0', fs->blksz); 432*ed34f34dSUma Shankar status = ext4fs_devread(gd[bg_idx].block_id * 433*ed34f34dSUma Shankar fs->sect_perblk, 0, fs->blksz, 434*ed34f34dSUma Shankar journal_buffer); 435*ed34f34dSUma Shankar if (status == 0) 436*ed34f34dSUma Shankar goto fail; 437*ed34f34dSUma Shankar 438*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, 439*ed34f34dSUma Shankar gd[bg_idx].block_id)) 440*ed34f34dSUma Shankar goto fail; 441*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 442*ed34f34dSUma Shankar } 443*ed34f34dSUma Shankar debug("DIPB releasing %ld\n", blknr); 444*ed34f34dSUma Shankar } 445*ed34f34dSUma Shankar fail: 446*ed34f34dSUma Shankar free(DIB_start_addr); 447*ed34f34dSUma Shankar free(journal_buffer); 448*ed34f34dSUma Shankar } 449*ed34f34dSUma Shankar 450*ed34f34dSUma Shankar static void delete_triple_indirect_block(struct ext2_inode *inode) 451*ed34f34dSUma Shankar { 452*ed34f34dSUma Shankar int i, j; 453*ed34f34dSUma Shankar short status; 454*ed34f34dSUma Shankar static int prev_bg_bmap_idx = -1; 455*ed34f34dSUma Shankar long int blknr; 456*ed34f34dSUma Shankar int remainder; 457*ed34f34dSUma Shankar int bg_idx; 458*ed34f34dSUma Shankar unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 459*ed34f34dSUma Shankar unsigned int *tigp_buffer = NULL; 460*ed34f34dSUma Shankar unsigned int *tib_start_addr = NULL; 461*ed34f34dSUma Shankar unsigned int *tip_buffer = NULL; 462*ed34f34dSUma Shankar unsigned int *tipb_start_addr = NULL; 463*ed34f34dSUma Shankar struct ext2_block_group *gd = NULL; 464*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 465*ed34f34dSUma Shankar char *journal_buffer = zalloc(fs->blksz); 466*ed34f34dSUma Shankar if (!journal_buffer) { 467*ed34f34dSUma Shankar printf("No memory\n"); 468*ed34f34dSUma Shankar return; 469*ed34f34dSUma Shankar } 470*ed34f34dSUma Shankar /* get block group descriptor table */ 471*ed34f34dSUma Shankar gd = (struct ext2_block_group *)fs->gdtable; 472*ed34f34dSUma Shankar 473*ed34f34dSUma Shankar if (inode->b.blocks.triple_indir_block != 0) { 474*ed34f34dSUma Shankar tigp_buffer = zalloc(fs->blksz); 475*ed34f34dSUma Shankar if (!tigp_buffer) { 476*ed34f34dSUma Shankar printf("No memory\n"); 477*ed34f34dSUma Shankar return; 478*ed34f34dSUma Shankar } 479*ed34f34dSUma Shankar tib_start_addr = (unsigned int *)tigp_buffer; 480*ed34f34dSUma Shankar blknr = inode->b.blocks.triple_indir_block; 481*ed34f34dSUma Shankar status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, 482*ed34f34dSUma Shankar (char *)tigp_buffer); 483*ed34f34dSUma Shankar for (i = 0; i < fs->blksz / sizeof(int); i++) { 484*ed34f34dSUma Shankar if (*tigp_buffer == 0) 485*ed34f34dSUma Shankar break; 486*ed34f34dSUma Shankar debug("tigp buffer releasing %u\n", *tigp_buffer); 487*ed34f34dSUma Shankar 488*ed34f34dSUma Shankar tip_buffer = zalloc(fs->blksz); 489*ed34f34dSUma Shankar if (!tip_buffer) 490*ed34f34dSUma Shankar goto fail; 491*ed34f34dSUma Shankar tipb_start_addr = (unsigned int *)tip_buffer; 492*ed34f34dSUma Shankar status = ext4fs_devread((*tigp_buffer) * 493*ed34f34dSUma Shankar fs->sect_perblk, 0, fs->blksz, 494*ed34f34dSUma Shankar (char *)tip_buffer); 495*ed34f34dSUma Shankar for (j = 0; j < fs->blksz / sizeof(int); j++) { 496*ed34f34dSUma Shankar if (*tip_buffer == 0) 497*ed34f34dSUma Shankar break; 498*ed34f34dSUma Shankar if (fs->blksz != 1024) { 499*ed34f34dSUma Shankar bg_idx = (*tip_buffer) / blk_per_grp; 500*ed34f34dSUma Shankar } else { 501*ed34f34dSUma Shankar bg_idx = (*tip_buffer) / blk_per_grp; 502*ed34f34dSUma Shankar 503*ed34f34dSUma Shankar remainder = (*tip_buffer) % blk_per_grp; 504*ed34f34dSUma Shankar if (!remainder) 505*ed34f34dSUma Shankar bg_idx--; 506*ed34f34dSUma Shankar } 507*ed34f34dSUma Shankar 508*ed34f34dSUma Shankar ext4fs_reset_block_bmap(*tip_buffer, 509*ed34f34dSUma Shankar fs->blk_bmaps[bg_idx], 510*ed34f34dSUma Shankar bg_idx); 511*ed34f34dSUma Shankar 512*ed34f34dSUma Shankar tip_buffer++; 513*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 514*ed34f34dSUma Shankar fs->sb->free_blocks++; 515*ed34f34dSUma Shankar /* journal backup */ 516*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 517*ed34f34dSUma Shankar status = 518*ed34f34dSUma Shankar ext4fs_devread(gd[bg_idx].block_id * 519*ed34f34dSUma Shankar fs->sect_perblk, 0, 520*ed34f34dSUma Shankar fs->blksz, 521*ed34f34dSUma Shankar journal_buffer); 522*ed34f34dSUma Shankar if (status == 0) 523*ed34f34dSUma Shankar goto fail; 524*ed34f34dSUma Shankar 525*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, 526*ed34f34dSUma Shankar gd[bg_idx]. 527*ed34f34dSUma Shankar block_id)) 528*ed34f34dSUma Shankar goto fail; 529*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 530*ed34f34dSUma Shankar } 531*ed34f34dSUma Shankar } 532*ed34f34dSUma Shankar free(tipb_start_addr); 533*ed34f34dSUma Shankar tipb_start_addr = NULL; 534*ed34f34dSUma Shankar 535*ed34f34dSUma Shankar /* 536*ed34f34dSUma Shankar * removing the grand parent blocks 537*ed34f34dSUma Shankar * which is connected to inode 538*ed34f34dSUma Shankar */ 539*ed34f34dSUma Shankar if (fs->blksz != 1024) { 540*ed34f34dSUma Shankar bg_idx = (*tigp_buffer) / blk_per_grp; 541*ed34f34dSUma Shankar } else { 542*ed34f34dSUma Shankar bg_idx = (*tigp_buffer) / blk_per_grp; 543*ed34f34dSUma Shankar 544*ed34f34dSUma Shankar remainder = (*tigp_buffer) % blk_per_grp; 545*ed34f34dSUma Shankar if (!remainder) 546*ed34f34dSUma Shankar bg_idx--; 547*ed34f34dSUma Shankar } 548*ed34f34dSUma Shankar ext4fs_reset_block_bmap(*tigp_buffer, 549*ed34f34dSUma Shankar fs->blk_bmaps[bg_idx], bg_idx); 550*ed34f34dSUma Shankar 551*ed34f34dSUma Shankar tigp_buffer++; 552*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 553*ed34f34dSUma Shankar fs->sb->free_blocks++; 554*ed34f34dSUma Shankar /* journal backup */ 555*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 556*ed34f34dSUma Shankar memset(journal_buffer, '\0', fs->blksz); 557*ed34f34dSUma Shankar status = 558*ed34f34dSUma Shankar ext4fs_devread(gd[bg_idx].block_id * 559*ed34f34dSUma Shankar fs->sect_perblk, 0, 560*ed34f34dSUma Shankar fs->blksz, journal_buffer); 561*ed34f34dSUma Shankar if (status == 0) 562*ed34f34dSUma Shankar goto fail; 563*ed34f34dSUma Shankar 564*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, 565*ed34f34dSUma Shankar gd[bg_idx].block_id)) 566*ed34f34dSUma Shankar goto fail; 567*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 568*ed34f34dSUma Shankar } 569*ed34f34dSUma Shankar } 570*ed34f34dSUma Shankar 571*ed34f34dSUma Shankar /* removing the grand parent triple indirect block */ 572*ed34f34dSUma Shankar blknr = inode->b.blocks.triple_indir_block; 573*ed34f34dSUma Shankar if (fs->blksz != 1024) { 574*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 575*ed34f34dSUma Shankar } else { 576*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 577*ed34f34dSUma Shankar remainder = blknr % blk_per_grp; 578*ed34f34dSUma Shankar if (!remainder) 579*ed34f34dSUma Shankar bg_idx--; 580*ed34f34dSUma Shankar } 581*ed34f34dSUma Shankar ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); 582*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 583*ed34f34dSUma Shankar fs->sb->free_blocks++; 584*ed34f34dSUma Shankar /* journal backup */ 585*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 586*ed34f34dSUma Shankar memset(journal_buffer, '\0', fs->blksz); 587*ed34f34dSUma Shankar status = ext4fs_devread(gd[bg_idx].block_id * 588*ed34f34dSUma Shankar fs->sect_perblk, 0, fs->blksz, 589*ed34f34dSUma Shankar journal_buffer); 590*ed34f34dSUma Shankar if (status == 0) 591*ed34f34dSUma Shankar goto fail; 592*ed34f34dSUma Shankar 593*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, 594*ed34f34dSUma Shankar gd[bg_idx].block_id)) 595*ed34f34dSUma Shankar goto fail; 596*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 597*ed34f34dSUma Shankar } 598*ed34f34dSUma Shankar debug("tigp buffer itself releasing %ld\n", blknr); 599*ed34f34dSUma Shankar } 600*ed34f34dSUma Shankar fail: 601*ed34f34dSUma Shankar free(tib_start_addr); 602*ed34f34dSUma Shankar free(tipb_start_addr); 603*ed34f34dSUma Shankar free(journal_buffer); 604*ed34f34dSUma Shankar } 605*ed34f34dSUma Shankar 606*ed34f34dSUma Shankar static int ext4fs_delete_file(int inodeno) 607*ed34f34dSUma Shankar { 608*ed34f34dSUma Shankar struct ext2_inode inode; 609*ed34f34dSUma Shankar short status; 610*ed34f34dSUma Shankar int i; 611*ed34f34dSUma Shankar int remainder; 612*ed34f34dSUma Shankar long int blknr; 613*ed34f34dSUma Shankar int bg_idx; 614*ed34f34dSUma Shankar int ibmap_idx; 615*ed34f34dSUma Shankar char *read_buffer = NULL; 616*ed34f34dSUma Shankar char *start_block_address = NULL; 617*ed34f34dSUma Shankar unsigned int no_blocks; 618*ed34f34dSUma Shankar 619*ed34f34dSUma Shankar static int prev_bg_bmap_idx = -1; 620*ed34f34dSUma Shankar unsigned int inodes_per_block; 621*ed34f34dSUma Shankar long int blkno; 622*ed34f34dSUma Shankar unsigned int blkoff; 623*ed34f34dSUma Shankar unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; 624*ed34f34dSUma Shankar unsigned int inode_per_grp = ext4fs_root->sblock.inodes_per_group; 625*ed34f34dSUma Shankar struct ext2_inode *inode_buffer = NULL; 626*ed34f34dSUma Shankar struct ext2_block_group *gd = NULL; 627*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 628*ed34f34dSUma Shankar char *journal_buffer = zalloc(fs->blksz); 629*ed34f34dSUma Shankar if (!journal_buffer) 630*ed34f34dSUma Shankar return -ENOMEM; 631*ed34f34dSUma Shankar /* get the block group descriptor table */ 632*ed34f34dSUma Shankar gd = (struct ext2_block_group *)fs->gdtable; 633*ed34f34dSUma Shankar status = ext4fs_read_inode(ext4fs_root, inodeno, &inode); 634*ed34f34dSUma Shankar if (status == 0) 635*ed34f34dSUma Shankar goto fail; 636*ed34f34dSUma Shankar 637*ed34f34dSUma Shankar /* read the block no allocated to a file */ 638*ed34f34dSUma Shankar no_blocks = inode.size / fs->blksz; 639*ed34f34dSUma Shankar if (inode.size % fs->blksz) 640*ed34f34dSUma Shankar no_blocks++; 641*ed34f34dSUma Shankar 642*ed34f34dSUma Shankar if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) { 643*ed34f34dSUma Shankar struct ext2fs_node *node_inode = 644*ed34f34dSUma Shankar zalloc(sizeof(struct ext2fs_node)); 645*ed34f34dSUma Shankar if (!node_inode) 646*ed34f34dSUma Shankar goto fail; 647*ed34f34dSUma Shankar node_inode->data = ext4fs_root; 648*ed34f34dSUma Shankar node_inode->ino = inodeno; 649*ed34f34dSUma Shankar node_inode->inode_read = 0; 650*ed34f34dSUma Shankar memcpy(&(node_inode->inode), &inode, sizeof(struct ext2_inode)); 651*ed34f34dSUma Shankar 652*ed34f34dSUma Shankar for (i = 0; i < no_blocks; i++) { 653*ed34f34dSUma Shankar blknr = read_allocated_block(&(node_inode->inode), i); 654*ed34f34dSUma Shankar if (fs->blksz != 1024) { 655*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 656*ed34f34dSUma Shankar } else { 657*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 658*ed34f34dSUma Shankar remainder = blknr % blk_per_grp; 659*ed34f34dSUma Shankar if (!remainder) 660*ed34f34dSUma Shankar bg_idx--; 661*ed34f34dSUma Shankar } 662*ed34f34dSUma Shankar ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], 663*ed34f34dSUma Shankar bg_idx); 664*ed34f34dSUma Shankar debug("EXT4_EXTENTS Block releasing %ld: %d\n", 665*ed34f34dSUma Shankar blknr, bg_idx); 666*ed34f34dSUma Shankar 667*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 668*ed34f34dSUma Shankar fs->sb->free_blocks++; 669*ed34f34dSUma Shankar 670*ed34f34dSUma Shankar /* journal backup */ 671*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 672*ed34f34dSUma Shankar status = 673*ed34f34dSUma Shankar ext4fs_devread(gd[bg_idx].block_id * 674*ed34f34dSUma Shankar fs->sect_perblk, 0, 675*ed34f34dSUma Shankar fs->blksz, journal_buffer); 676*ed34f34dSUma Shankar if (status == 0) 677*ed34f34dSUma Shankar goto fail; 678*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, 679*ed34f34dSUma Shankar gd[bg_idx].block_id)) 680*ed34f34dSUma Shankar goto fail; 681*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 682*ed34f34dSUma Shankar } 683*ed34f34dSUma Shankar } 684*ed34f34dSUma Shankar if (node_inode) { 685*ed34f34dSUma Shankar free(node_inode); 686*ed34f34dSUma Shankar node_inode = NULL; 687*ed34f34dSUma Shankar } 688*ed34f34dSUma Shankar } else { 689*ed34f34dSUma Shankar 690*ed34f34dSUma Shankar delete_single_indirect_block(&inode); 691*ed34f34dSUma Shankar delete_double_indirect_block(&inode); 692*ed34f34dSUma Shankar delete_triple_indirect_block(&inode); 693*ed34f34dSUma Shankar 694*ed34f34dSUma Shankar /* read the block no allocated to a file */ 695*ed34f34dSUma Shankar no_blocks = inode.size / fs->blksz; 696*ed34f34dSUma Shankar if (inode.size % fs->blksz) 697*ed34f34dSUma Shankar no_blocks++; 698*ed34f34dSUma Shankar for (i = 0; i < no_blocks; i++) { 699*ed34f34dSUma Shankar blknr = read_allocated_block(&inode, i); 700*ed34f34dSUma Shankar if (fs->blksz != 1024) { 701*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 702*ed34f34dSUma Shankar } else { 703*ed34f34dSUma Shankar bg_idx = blknr / blk_per_grp; 704*ed34f34dSUma Shankar remainder = blknr % blk_per_grp; 705*ed34f34dSUma Shankar if (!remainder) 706*ed34f34dSUma Shankar bg_idx--; 707*ed34f34dSUma Shankar } 708*ed34f34dSUma Shankar ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], 709*ed34f34dSUma Shankar bg_idx); 710*ed34f34dSUma Shankar debug("ActualB releasing %ld: %d\n", blknr, bg_idx); 711*ed34f34dSUma Shankar 712*ed34f34dSUma Shankar gd[bg_idx].free_blocks++; 713*ed34f34dSUma Shankar fs->sb->free_blocks++; 714*ed34f34dSUma Shankar /* journal backup */ 715*ed34f34dSUma Shankar if (prev_bg_bmap_idx != bg_idx) { 716*ed34f34dSUma Shankar memset(journal_buffer, '\0', fs->blksz); 717*ed34f34dSUma Shankar status = ext4fs_devread(gd[bg_idx].block_id 718*ed34f34dSUma Shankar * fs->sect_perblk, 719*ed34f34dSUma Shankar 0, fs->blksz, 720*ed34f34dSUma Shankar journal_buffer); 721*ed34f34dSUma Shankar if (status == 0) 722*ed34f34dSUma Shankar goto fail; 723*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, 724*ed34f34dSUma Shankar gd[bg_idx].block_id)) 725*ed34f34dSUma Shankar goto fail; 726*ed34f34dSUma Shankar prev_bg_bmap_idx = bg_idx; 727*ed34f34dSUma Shankar } 728*ed34f34dSUma Shankar } 729*ed34f34dSUma Shankar } 730*ed34f34dSUma Shankar 731*ed34f34dSUma Shankar /* from the inode no to blockno */ 732*ed34f34dSUma Shankar inodes_per_block = fs->blksz / fs->inodesz; 733*ed34f34dSUma Shankar ibmap_idx = inodeno / inode_per_grp; 734*ed34f34dSUma Shankar 735*ed34f34dSUma Shankar /* get the block no */ 736*ed34f34dSUma Shankar inodeno--; 737*ed34f34dSUma Shankar blkno = __le32_to_cpu(gd[ibmap_idx].inode_table_id) + 738*ed34f34dSUma Shankar (inodeno % __le32_to_cpu(inode_per_grp)) / inodes_per_block; 739*ed34f34dSUma Shankar 740*ed34f34dSUma Shankar /* get the offset of the inode */ 741*ed34f34dSUma Shankar blkoff = ((inodeno) % inodes_per_block) * fs->inodesz; 742*ed34f34dSUma Shankar 743*ed34f34dSUma Shankar /* read the block no containing the inode */ 744*ed34f34dSUma Shankar read_buffer = zalloc(fs->blksz); 745*ed34f34dSUma Shankar if (!read_buffer) 746*ed34f34dSUma Shankar goto fail; 747*ed34f34dSUma Shankar start_block_address = read_buffer; 748*ed34f34dSUma Shankar status = ext4fs_devread(blkno * fs->sect_perblk, 749*ed34f34dSUma Shankar 0, fs->blksz, read_buffer); 750*ed34f34dSUma Shankar if (status == 0) 751*ed34f34dSUma Shankar goto fail; 752*ed34f34dSUma Shankar 753*ed34f34dSUma Shankar if (ext4fs_log_journal(read_buffer, blkno)) 754*ed34f34dSUma Shankar goto fail; 755*ed34f34dSUma Shankar 756*ed34f34dSUma Shankar read_buffer = read_buffer + blkoff; 757*ed34f34dSUma Shankar inode_buffer = (struct ext2_inode *)read_buffer; 758*ed34f34dSUma Shankar memset(inode_buffer, '\0', sizeof(struct ext2_inode)); 759*ed34f34dSUma Shankar 760*ed34f34dSUma Shankar /* write the inode to original position in inode table */ 761*ed34f34dSUma Shankar if (ext4fs_put_metadata(start_block_address, blkno)) 762*ed34f34dSUma Shankar goto fail; 763*ed34f34dSUma Shankar 764*ed34f34dSUma Shankar /* update the respective inode bitmaps */ 765*ed34f34dSUma Shankar inodeno++; 766*ed34f34dSUma Shankar ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx); 767*ed34f34dSUma Shankar gd[ibmap_idx].free_inodes++; 768*ed34f34dSUma Shankar fs->sb->free_inodes++; 769*ed34f34dSUma Shankar /* journal backup */ 770*ed34f34dSUma Shankar memset(journal_buffer, '\0', fs->blksz); 771*ed34f34dSUma Shankar status = ext4fs_devread(gd[ibmap_idx].inode_id * 772*ed34f34dSUma Shankar fs->sect_perblk, 0, fs->blksz, journal_buffer); 773*ed34f34dSUma Shankar if (status == 0) 774*ed34f34dSUma Shankar goto fail; 775*ed34f34dSUma Shankar if (ext4fs_log_journal(journal_buffer, gd[ibmap_idx].inode_id)) 776*ed34f34dSUma Shankar goto fail; 777*ed34f34dSUma Shankar 778*ed34f34dSUma Shankar ext4fs_update(); 779*ed34f34dSUma Shankar ext4fs_deinit(); 780*ed34f34dSUma Shankar 781*ed34f34dSUma Shankar if (ext4fs_init() != 0) { 782*ed34f34dSUma Shankar printf("error in File System init\n"); 783*ed34f34dSUma Shankar goto fail; 784*ed34f34dSUma Shankar } 785*ed34f34dSUma Shankar 786*ed34f34dSUma Shankar free(start_block_address); 787*ed34f34dSUma Shankar free(journal_buffer); 788*ed34f34dSUma Shankar 789*ed34f34dSUma Shankar return 0; 790*ed34f34dSUma Shankar fail: 791*ed34f34dSUma Shankar free(start_block_address); 792*ed34f34dSUma Shankar free(journal_buffer); 793*ed34f34dSUma Shankar 794*ed34f34dSUma Shankar return -1; 795*ed34f34dSUma Shankar } 796*ed34f34dSUma Shankar 797*ed34f34dSUma Shankar int ext4fs_init(void) 798*ed34f34dSUma Shankar { 799*ed34f34dSUma Shankar short status; 800*ed34f34dSUma Shankar int i; 801*ed34f34dSUma Shankar unsigned int real_free_blocks = 0; 802*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 803*ed34f34dSUma Shankar 804*ed34f34dSUma Shankar /* populate fs */ 805*ed34f34dSUma Shankar fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root); 806*ed34f34dSUma Shankar fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root); 807*ed34f34dSUma Shankar fs->sect_perblk = fs->blksz / SECTOR_SIZE; 808*ed34f34dSUma Shankar 809*ed34f34dSUma Shankar /* get the superblock */ 810*ed34f34dSUma Shankar fs->sb = zalloc(SUPERBLOCK_SIZE); 811*ed34f34dSUma Shankar if (!fs->sb) 812*ed34f34dSUma Shankar return -ENOMEM; 813*ed34f34dSUma Shankar if (!ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, 814*ed34f34dSUma Shankar (char *)fs->sb)) 815*ed34f34dSUma Shankar goto fail; 816*ed34f34dSUma Shankar 817*ed34f34dSUma Shankar /* init journal */ 818*ed34f34dSUma Shankar if (ext4fs_init_journal()) 819*ed34f34dSUma Shankar goto fail; 820*ed34f34dSUma Shankar 821*ed34f34dSUma Shankar /* get total no of blockgroups */ 822*ed34f34dSUma Shankar fs->no_blkgrp = (uint32_t)ext4fs_div_roundup( 823*ed34f34dSUma Shankar (ext4fs_root->sblock.total_blocks - 824*ed34f34dSUma Shankar ext4fs_root->sblock.first_data_block), 825*ed34f34dSUma Shankar ext4fs_root->sblock.blocks_per_group); 826*ed34f34dSUma Shankar 827*ed34f34dSUma Shankar /* get the block group descriptor table */ 828*ed34f34dSUma Shankar fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1); 829*ed34f34dSUma Shankar if (ext4fs_get_bgdtable() == -1) { 830*ed34f34dSUma Shankar printf("Error in getting the block group descriptor table\n"); 831*ed34f34dSUma Shankar goto fail; 832*ed34f34dSUma Shankar } 833*ed34f34dSUma Shankar fs->gd = (struct ext2_block_group *)fs->gdtable; 834*ed34f34dSUma Shankar 835*ed34f34dSUma Shankar /* load all the available bitmap block of the partition */ 836*ed34f34dSUma Shankar fs->blk_bmaps = zalloc(fs->no_blkgrp * sizeof(char *)); 837*ed34f34dSUma Shankar if (!fs->blk_bmaps) 838*ed34f34dSUma Shankar goto fail; 839*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 840*ed34f34dSUma Shankar fs->blk_bmaps[i] = zalloc(fs->blksz); 841*ed34f34dSUma Shankar if (!fs->blk_bmaps[i]) 842*ed34f34dSUma Shankar goto fail; 843*ed34f34dSUma Shankar } 844*ed34f34dSUma Shankar 845*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 846*ed34f34dSUma Shankar status = 847*ed34f34dSUma Shankar ext4fs_devread(fs->gd[i].block_id * fs->sect_perblk, 0, 848*ed34f34dSUma Shankar fs->blksz, (char *)fs->blk_bmaps[i]); 849*ed34f34dSUma Shankar if (status == 0) 850*ed34f34dSUma Shankar goto fail; 851*ed34f34dSUma Shankar } 852*ed34f34dSUma Shankar 853*ed34f34dSUma Shankar /* load all the available inode bitmap of the partition */ 854*ed34f34dSUma Shankar fs->inode_bmaps = zalloc(fs->no_blkgrp * sizeof(unsigned char *)); 855*ed34f34dSUma Shankar if (!fs->inode_bmaps) 856*ed34f34dSUma Shankar goto fail; 857*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 858*ed34f34dSUma Shankar fs->inode_bmaps[i] = zalloc(fs->blksz); 859*ed34f34dSUma Shankar if (!fs->inode_bmaps[i]) 860*ed34f34dSUma Shankar goto fail; 861*ed34f34dSUma Shankar } 862*ed34f34dSUma Shankar 863*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 864*ed34f34dSUma Shankar status = ext4fs_devread(fs->gd[i].inode_id * fs->sect_perblk, 865*ed34f34dSUma Shankar 0, fs->blksz, 866*ed34f34dSUma Shankar (char *)fs->inode_bmaps[i]); 867*ed34f34dSUma Shankar if (status == 0) 868*ed34f34dSUma Shankar goto fail; 869*ed34f34dSUma Shankar } 870*ed34f34dSUma Shankar 871*ed34f34dSUma Shankar /* 872*ed34f34dSUma Shankar * check filesystem consistency with free blocks of file system 873*ed34f34dSUma Shankar * some time we observed that superblock freeblocks does not match 874*ed34f34dSUma Shankar * with the blockgroups freeblocks when improper 875*ed34f34dSUma Shankar * reboot of a linux kernel 876*ed34f34dSUma Shankar */ 877*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) 878*ed34f34dSUma Shankar real_free_blocks = real_free_blocks + fs->gd[i].free_blocks; 879*ed34f34dSUma Shankar if (real_free_blocks != fs->sb->free_blocks) 880*ed34f34dSUma Shankar fs->sb->free_blocks = real_free_blocks; 881*ed34f34dSUma Shankar 882*ed34f34dSUma Shankar return 0; 883*ed34f34dSUma Shankar fail: 884*ed34f34dSUma Shankar ext4fs_deinit(); 885*ed34f34dSUma Shankar 886*ed34f34dSUma Shankar return -1; 887*ed34f34dSUma Shankar } 888*ed34f34dSUma Shankar 889*ed34f34dSUma Shankar void ext4fs_deinit(void) 890*ed34f34dSUma Shankar { 891*ed34f34dSUma Shankar int i; 892*ed34f34dSUma Shankar struct ext2_inode inode_journal; 893*ed34f34dSUma Shankar struct journal_superblock_t *jsb; 894*ed34f34dSUma Shankar long int blknr; 895*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 896*ed34f34dSUma Shankar 897*ed34f34dSUma Shankar /* free journal */ 898*ed34f34dSUma Shankar char *temp_buff = zalloc(fs->blksz); 899*ed34f34dSUma Shankar if (temp_buff) { 900*ed34f34dSUma Shankar ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, 901*ed34f34dSUma Shankar &inode_journal); 902*ed34f34dSUma Shankar blknr = read_allocated_block(&inode_journal, 903*ed34f34dSUma Shankar EXT2_JOURNAL_SUPERBLOCK); 904*ed34f34dSUma Shankar ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, 905*ed34f34dSUma Shankar temp_buff); 906*ed34f34dSUma Shankar jsb = (struct journal_superblock_t *)temp_buff; 907*ed34f34dSUma Shankar jsb->s_start = cpu_to_be32(0); 908*ed34f34dSUma Shankar put_ext4((uint64_t) (blknr * fs->blksz), 909*ed34f34dSUma Shankar (struct journal_superblock_t *)temp_buff, fs->blksz); 910*ed34f34dSUma Shankar free(temp_buff); 911*ed34f34dSUma Shankar } 912*ed34f34dSUma Shankar ext4fs_free_journal(); 913*ed34f34dSUma Shankar 914*ed34f34dSUma Shankar /* get the superblock */ 915*ed34f34dSUma Shankar ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, (char *)fs->sb); 916*ed34f34dSUma Shankar fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; 917*ed34f34dSUma Shankar put_ext4((uint64_t)(SUPERBLOCK_SIZE), 918*ed34f34dSUma Shankar (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); 919*ed34f34dSUma Shankar free(fs->sb); 920*ed34f34dSUma Shankar fs->sb = NULL; 921*ed34f34dSUma Shankar 922*ed34f34dSUma Shankar if (fs->blk_bmaps) { 923*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 924*ed34f34dSUma Shankar free(fs->blk_bmaps[i]); 925*ed34f34dSUma Shankar fs->blk_bmaps[i] = NULL; 926*ed34f34dSUma Shankar } 927*ed34f34dSUma Shankar free(fs->blk_bmaps); 928*ed34f34dSUma Shankar fs->blk_bmaps = NULL; 929*ed34f34dSUma Shankar } 930*ed34f34dSUma Shankar 931*ed34f34dSUma Shankar if (fs->inode_bmaps) { 932*ed34f34dSUma Shankar for (i = 0; i < fs->no_blkgrp; i++) { 933*ed34f34dSUma Shankar free(fs->inode_bmaps[i]); 934*ed34f34dSUma Shankar fs->inode_bmaps[i] = NULL; 935*ed34f34dSUma Shankar } 936*ed34f34dSUma Shankar free(fs->inode_bmaps); 937*ed34f34dSUma Shankar fs->inode_bmaps = NULL; 938*ed34f34dSUma Shankar } 939*ed34f34dSUma Shankar 940*ed34f34dSUma Shankar 941*ed34f34dSUma Shankar free(fs->gdtable); 942*ed34f34dSUma Shankar fs->gdtable = NULL; 943*ed34f34dSUma Shankar fs->gd = NULL; 944*ed34f34dSUma Shankar /* 945*ed34f34dSUma Shankar * reinitiliazed the global inode and 946*ed34f34dSUma Shankar * block bitmap first execution check variables 947*ed34f34dSUma Shankar */ 948*ed34f34dSUma Shankar fs->first_pass_ibmap = 0; 949*ed34f34dSUma Shankar fs->first_pass_bbmap = 0; 950*ed34f34dSUma Shankar fs->curr_inode_no = 0; 951*ed34f34dSUma Shankar fs->curr_blkno = 0; 952*ed34f34dSUma Shankar } 953*ed34f34dSUma Shankar 954*ed34f34dSUma Shankar static int ext4fs_write_file(struct ext2_inode *file_inode, 955*ed34f34dSUma Shankar int pos, unsigned int len, char *buf) 956*ed34f34dSUma Shankar { 957*ed34f34dSUma Shankar int i; 958*ed34f34dSUma Shankar int blockcnt; 959*ed34f34dSUma Shankar int log2blocksize = LOG2_EXT2_BLOCK_SIZE(ext4fs_root); 960*ed34f34dSUma Shankar unsigned int filesize = __le32_to_cpu(file_inode->size); 961*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 962*ed34f34dSUma Shankar int previous_block_number = -1; 963*ed34f34dSUma Shankar int delayed_start = 0; 964*ed34f34dSUma Shankar int delayed_extent = 0; 965*ed34f34dSUma Shankar int delayed_skipfirst = 0; 966*ed34f34dSUma Shankar int delayed_next = 0; 967*ed34f34dSUma Shankar char *delayed_buf = NULL; 968*ed34f34dSUma Shankar 969*ed34f34dSUma Shankar /* Adjust len so it we can't read past the end of the file. */ 970*ed34f34dSUma Shankar if (len > filesize) 971*ed34f34dSUma Shankar len = filesize; 972*ed34f34dSUma Shankar 973*ed34f34dSUma Shankar blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz; 974*ed34f34dSUma Shankar 975*ed34f34dSUma Shankar for (i = pos / fs->blksz; i < blockcnt; i++) { 976*ed34f34dSUma Shankar long int blknr; 977*ed34f34dSUma Shankar int blockend = fs->blksz; 978*ed34f34dSUma Shankar int skipfirst = 0; 979*ed34f34dSUma Shankar blknr = read_allocated_block(file_inode, i); 980*ed34f34dSUma Shankar if (blknr < 0) 981*ed34f34dSUma Shankar return -1; 982*ed34f34dSUma Shankar 983*ed34f34dSUma Shankar blknr = blknr << log2blocksize; 984*ed34f34dSUma Shankar 985*ed34f34dSUma Shankar if (blknr) { 986*ed34f34dSUma Shankar if (previous_block_number != -1) { 987*ed34f34dSUma Shankar if (delayed_next == blknr) { 988*ed34f34dSUma Shankar delayed_extent += blockend; 989*ed34f34dSUma Shankar delayed_next += blockend >> SECTOR_BITS; 990*ed34f34dSUma Shankar } else { /* spill */ 991*ed34f34dSUma Shankar put_ext4((uint64_t) (delayed_start * 992*ed34f34dSUma Shankar SECTOR_SIZE), 993*ed34f34dSUma Shankar delayed_buf, 994*ed34f34dSUma Shankar (uint32_t) delayed_extent); 995*ed34f34dSUma Shankar previous_block_number = blknr; 996*ed34f34dSUma Shankar delayed_start = blknr; 997*ed34f34dSUma Shankar delayed_extent = blockend; 998*ed34f34dSUma Shankar delayed_skipfirst = skipfirst; 999*ed34f34dSUma Shankar delayed_buf = buf; 1000*ed34f34dSUma Shankar delayed_next = blknr + 1001*ed34f34dSUma Shankar (blockend >> SECTOR_BITS); 1002*ed34f34dSUma Shankar } 1003*ed34f34dSUma Shankar } else { 1004*ed34f34dSUma Shankar previous_block_number = blknr; 1005*ed34f34dSUma Shankar delayed_start = blknr; 1006*ed34f34dSUma Shankar delayed_extent = blockend; 1007*ed34f34dSUma Shankar delayed_skipfirst = skipfirst; 1008*ed34f34dSUma Shankar delayed_buf = buf; 1009*ed34f34dSUma Shankar delayed_next = blknr + 1010*ed34f34dSUma Shankar (blockend >> SECTOR_BITS); 1011*ed34f34dSUma Shankar } 1012*ed34f34dSUma Shankar } else { 1013*ed34f34dSUma Shankar if (previous_block_number != -1) { 1014*ed34f34dSUma Shankar /* spill */ 1015*ed34f34dSUma Shankar put_ext4((uint64_t) (delayed_start * 1016*ed34f34dSUma Shankar SECTOR_SIZE), delayed_buf, 1017*ed34f34dSUma Shankar (uint32_t) delayed_extent); 1018*ed34f34dSUma Shankar previous_block_number = -1; 1019*ed34f34dSUma Shankar } 1020*ed34f34dSUma Shankar memset(buf, 0, fs->blksz - skipfirst); 1021*ed34f34dSUma Shankar } 1022*ed34f34dSUma Shankar buf += fs->blksz - skipfirst; 1023*ed34f34dSUma Shankar } 1024*ed34f34dSUma Shankar if (previous_block_number != -1) { 1025*ed34f34dSUma Shankar /* spill */ 1026*ed34f34dSUma Shankar put_ext4((uint64_t) (delayed_start * SECTOR_SIZE), 1027*ed34f34dSUma Shankar delayed_buf, (uint32_t) delayed_extent); 1028*ed34f34dSUma Shankar previous_block_number = -1; 1029*ed34f34dSUma Shankar } 1030*ed34f34dSUma Shankar 1031*ed34f34dSUma Shankar return len; 1032*ed34f34dSUma Shankar } 1033*ed34f34dSUma Shankar 1034*ed34f34dSUma Shankar int ext4fs_write(const char *fname, unsigned char *buffer, 1035*ed34f34dSUma Shankar unsigned long sizebytes) 1036*ed34f34dSUma Shankar { 1037*ed34f34dSUma Shankar int ret = 0; 1038*ed34f34dSUma Shankar struct ext2_inode *file_inode = NULL; 1039*ed34f34dSUma Shankar unsigned char *inode_buffer = NULL; 1040*ed34f34dSUma Shankar int parent_inodeno; 1041*ed34f34dSUma Shankar int inodeno; 1042*ed34f34dSUma Shankar time_t timestamp = 0; 1043*ed34f34dSUma Shankar 1044*ed34f34dSUma Shankar uint64_t bytes_reqd_for_file; 1045*ed34f34dSUma Shankar unsigned int blks_reqd_for_file; 1046*ed34f34dSUma Shankar unsigned int blocks_remaining; 1047*ed34f34dSUma Shankar int existing_file_inodeno; 1048*ed34f34dSUma Shankar char filename[256]; 1049*ed34f34dSUma Shankar 1050*ed34f34dSUma Shankar char *temp_ptr = NULL; 1051*ed34f34dSUma Shankar long int itable_blkno; 1052*ed34f34dSUma Shankar long int parent_itable_blkno; 1053*ed34f34dSUma Shankar long int blkoff; 1054*ed34f34dSUma Shankar struct ext2_sblock *sblock = &(ext4fs_root->sblock); 1055*ed34f34dSUma Shankar unsigned int inodes_per_block; 1056*ed34f34dSUma Shankar unsigned int ibmap_idx; 1057*ed34f34dSUma Shankar struct ext_filesystem *fs = get_fs(); 1058*ed34f34dSUma Shankar g_parent_inode = zalloc(sizeof(struct ext2_inode)); 1059*ed34f34dSUma Shankar if (!g_parent_inode) 1060*ed34f34dSUma Shankar goto fail; 1061*ed34f34dSUma Shankar 1062*ed34f34dSUma Shankar if (ext4fs_init() != 0) { 1063*ed34f34dSUma Shankar printf("error in File System init\n"); 1064*ed34f34dSUma Shankar return -1; 1065*ed34f34dSUma Shankar } 1066*ed34f34dSUma Shankar inodes_per_block = fs->blksz / fs->inodesz; 1067*ed34f34dSUma Shankar parent_inodeno = ext4fs_get_parent_inode_num(fname, filename, F_FILE); 1068*ed34f34dSUma Shankar if (parent_inodeno == -1) 1069*ed34f34dSUma Shankar goto fail; 1070*ed34f34dSUma Shankar if (ext4fs_iget(parent_inodeno, g_parent_inode)) 1071*ed34f34dSUma Shankar goto fail; 1072*ed34f34dSUma Shankar /* check if the filename is already present in root */ 1073*ed34f34dSUma Shankar existing_file_inodeno = ext4fs_filename_check(filename); 1074*ed34f34dSUma Shankar if (existing_file_inodeno != -1) { 1075*ed34f34dSUma Shankar ret = ext4fs_delete_file(existing_file_inodeno); 1076*ed34f34dSUma Shankar fs->first_pass_bbmap = 0; 1077*ed34f34dSUma Shankar fs->curr_blkno = 0; 1078*ed34f34dSUma Shankar 1079*ed34f34dSUma Shankar fs->first_pass_ibmap = 0; 1080*ed34f34dSUma Shankar fs->curr_inode_no = 0; 1081*ed34f34dSUma Shankar if (ret) 1082*ed34f34dSUma Shankar goto fail; 1083*ed34f34dSUma Shankar } 1084*ed34f34dSUma Shankar /* calucalate how many blocks required */ 1085*ed34f34dSUma Shankar bytes_reqd_for_file = sizebytes; 1086*ed34f34dSUma Shankar blks_reqd_for_file = bytes_reqd_for_file / fs->blksz; 1087*ed34f34dSUma Shankar if (bytes_reqd_for_file % fs->blksz != 0) { 1088*ed34f34dSUma Shankar blks_reqd_for_file++; 1089*ed34f34dSUma Shankar debug("total bytes for a file %u\n", blks_reqd_for_file); 1090*ed34f34dSUma Shankar } 1091*ed34f34dSUma Shankar blocks_remaining = blks_reqd_for_file; 1092*ed34f34dSUma Shankar /* test for available space in partition */ 1093*ed34f34dSUma Shankar if (fs->sb->free_blocks < blks_reqd_for_file) { 1094*ed34f34dSUma Shankar printf("Not enough space on partition !!!\n"); 1095*ed34f34dSUma Shankar goto fail; 1096*ed34f34dSUma Shankar } 1097*ed34f34dSUma Shankar 1098*ed34f34dSUma Shankar ext4fs_update_parent_dentry(filename, &inodeno, FILETYPE_REG); 1099*ed34f34dSUma Shankar /* prepare file inode */ 1100*ed34f34dSUma Shankar inode_buffer = zalloc(fs->inodesz); 1101*ed34f34dSUma Shankar if (!inode_buffer) 1102*ed34f34dSUma Shankar goto fail; 1103*ed34f34dSUma Shankar file_inode = (struct ext2_inode *)inode_buffer; 1104*ed34f34dSUma Shankar file_inode->mode = S_IFREG | S_IRWXU | 1105*ed34f34dSUma Shankar S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH; 1106*ed34f34dSUma Shankar /* ToDo: Update correct time */ 1107*ed34f34dSUma Shankar file_inode->mtime = timestamp; 1108*ed34f34dSUma Shankar file_inode->atime = timestamp; 1109*ed34f34dSUma Shankar file_inode->ctime = timestamp; 1110*ed34f34dSUma Shankar file_inode->nlinks = 1; 1111*ed34f34dSUma Shankar file_inode->size = sizebytes; 1112*ed34f34dSUma Shankar 1113*ed34f34dSUma Shankar /* Allocate data blocks */ 1114*ed34f34dSUma Shankar ext4fs_allocate_blocks(file_inode, blocks_remaining, 1115*ed34f34dSUma Shankar &blks_reqd_for_file); 1116*ed34f34dSUma Shankar file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) / SECTOR_SIZE; 1117*ed34f34dSUma Shankar 1118*ed34f34dSUma Shankar temp_ptr = zalloc(fs->blksz); 1119*ed34f34dSUma Shankar if (!temp_ptr) 1120*ed34f34dSUma Shankar goto fail; 1121*ed34f34dSUma Shankar ibmap_idx = inodeno / ext4fs_root->sblock.inodes_per_group; 1122*ed34f34dSUma Shankar inodeno--; 1123*ed34f34dSUma Shankar itable_blkno = __le32_to_cpu(fs->gd[ibmap_idx].inode_table_id) + 1124*ed34f34dSUma Shankar (inodeno % __le32_to_cpu(sblock->inodes_per_group)) / 1125*ed34f34dSUma Shankar inodes_per_block; 1126*ed34f34dSUma Shankar blkoff = (inodeno % inodes_per_block) * fs->inodesz; 1127*ed34f34dSUma Shankar ext4fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr); 1128*ed34f34dSUma Shankar if (ext4fs_log_journal(temp_ptr, itable_blkno)) 1129*ed34f34dSUma Shankar goto fail; 1130*ed34f34dSUma Shankar 1131*ed34f34dSUma Shankar memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz); 1132*ed34f34dSUma Shankar if (ext4fs_put_metadata(temp_ptr, itable_blkno)) 1133*ed34f34dSUma Shankar goto fail; 1134*ed34f34dSUma Shankar /* copy the file content into data blocks */ 1135*ed34f34dSUma Shankar if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) { 1136*ed34f34dSUma Shankar printf("Error in copying content\n"); 1137*ed34f34dSUma Shankar goto fail; 1138*ed34f34dSUma Shankar } 1139*ed34f34dSUma Shankar ibmap_idx = parent_inodeno / ext4fs_root->sblock.inodes_per_group; 1140*ed34f34dSUma Shankar parent_inodeno--; 1141*ed34f34dSUma Shankar parent_itable_blkno = __le32_to_cpu(fs->gd[ibmap_idx].inode_table_id) + 1142*ed34f34dSUma Shankar (parent_inodeno % 1143*ed34f34dSUma Shankar __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; 1144*ed34f34dSUma Shankar blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz; 1145*ed34f34dSUma Shankar if (parent_itable_blkno != itable_blkno) { 1146*ed34f34dSUma Shankar memset(temp_ptr, '\0', fs->blksz); 1147*ed34f34dSUma Shankar ext4fs_devread(parent_itable_blkno * fs->sect_perblk, 1148*ed34f34dSUma Shankar 0, fs->blksz, temp_ptr); 1149*ed34f34dSUma Shankar if (ext4fs_log_journal(temp_ptr, parent_itable_blkno)) 1150*ed34f34dSUma Shankar goto fail; 1151*ed34f34dSUma Shankar 1152*ed34f34dSUma Shankar memcpy(temp_ptr + blkoff, g_parent_inode, 1153*ed34f34dSUma Shankar sizeof(struct ext2_inode)); 1154*ed34f34dSUma Shankar if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno)) 1155*ed34f34dSUma Shankar goto fail; 1156*ed34f34dSUma Shankar free(temp_ptr); 1157*ed34f34dSUma Shankar } else { 1158*ed34f34dSUma Shankar /* 1159*ed34f34dSUma Shankar * If parent and child fall in same inode table block 1160*ed34f34dSUma Shankar * both should be kept in 1 buffer 1161*ed34f34dSUma Shankar */ 1162*ed34f34dSUma Shankar memcpy(temp_ptr + blkoff, g_parent_inode, 1163*ed34f34dSUma Shankar sizeof(struct ext2_inode)); 1164*ed34f34dSUma Shankar gd_index--; 1165*ed34f34dSUma Shankar if (ext4fs_put_metadata(temp_ptr, itable_blkno)) 1166*ed34f34dSUma Shankar goto fail; 1167*ed34f34dSUma Shankar free(temp_ptr); 1168*ed34f34dSUma Shankar } 1169*ed34f34dSUma Shankar ext4fs_update(); 1170*ed34f34dSUma Shankar ext4fs_deinit(); 1171*ed34f34dSUma Shankar 1172*ed34f34dSUma Shankar fs->first_pass_bbmap = 0; 1173*ed34f34dSUma Shankar fs->curr_blkno = 0; 1174*ed34f34dSUma Shankar fs->first_pass_ibmap = 0; 1175*ed34f34dSUma Shankar fs->curr_inode_no = 0; 1176*ed34f34dSUma Shankar free(inode_buffer); 1177*ed34f34dSUma Shankar free(g_parent_inode); 1178*ed34f34dSUma Shankar g_parent_inode = NULL; 1179*ed34f34dSUma Shankar 1180*ed34f34dSUma Shankar return 0; 1181*ed34f34dSUma Shankar fail: 1182*ed34f34dSUma Shankar ext4fs_deinit(); 1183*ed34f34dSUma Shankar free(inode_buffer); 1184*ed34f34dSUma Shankar free(g_parent_inode); 1185*ed34f34dSUma Shankar g_parent_inode = NULL; 1186*ed34f34dSUma Shankar 1187*ed34f34dSUma Shankar return -1; 1188*ed34f34dSUma Shankar } 1189*ed34f34dSUma Shankar #endif 1190