119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * alloc.c --- allocate new inodes, blocks for ext2fs
319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library
88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2.
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h>
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h>
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_STAT_H
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/stat.h>
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_TYPES_H
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h>
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h"
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs.h"
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Check for uninit block bitmaps and deal with them appropriately
303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			  dgrp_t group)
333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t		i;
353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t		blk, super_blk, old_desc_blk, new_desc_blk;
363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		old_desc_blocks;
373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) ||
403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    !(fs->group_desc[group].bg_flags & EXT2_BG_BLOCK_UNINIT))
413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk = (group * fs->super->s_blocks_per_group) +
443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fs->super->s_first_data_block;
453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_super_and_bgd_loc(fs, group, &super_blk,
473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 &old_desc_blk, &new_desc_blk, 0);
483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (fs->super->s_feature_incompat &
503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    EXT2_FEATURE_INCOMPAT_META_BG)
513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		old_desc_blocks = fs->super->s_first_meta_bg;
523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	else
533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		old_desc_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	for (i=0; i < fs->super->s_blocks_per_group; i++, blk++) {
563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((blk == super_blk) ||
573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (old_desc_blk && old_desc_blocks &&
583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     (blk >= old_desc_blk) &&
593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     (blk < old_desc_blk + old_desc_blocks)) ||
603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (new_desc_blk && (blk == new_desc_blk)) ||
613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (blk == fs->group_desc[group].bg_block_bitmap) ||
623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (blk == fs->group_desc[group].bg_inode_bitmap) ||
633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (blk >= fs->group_desc[group].bg_inode_table &&
643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     (blk < fs->group_desc[group].bg_inode_table
653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		      + fs->inode_blocks_per_group)))
663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_fast_mark_block_bitmap(map, blk);
673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else
683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_fast_unmark_block_bitmap(map, blk);
693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fs->group_desc[group].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_group_desc_csum_set(fs, group);
723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Check for uninit inode bitmaps and deal with them appropriately
763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map,
783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			  dgrp_t group)
793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2_ino_t	i, ino;
813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) ||
843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    !(fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT))
853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ino = (group * fs->super->s_inodes_per_group) + 1;
883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	for (i=0; i < fs->super->s_inodes_per_group; i++, ino++)
893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_fast_unmark_inode_bitmap(map, ino);
903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fs->group_desc[group].bg_flags &= ~EXT2_BG_INODE_UNINIT;
923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	check_block_uninit(fs, fs->block_map, group);
933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Right now, just search forward from the parent directory's block
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * group to find the next free inode.
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Should have a special policy for directories.
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   int mode EXT2FS_ATTR((unused)),
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   ext2fs_inode_bitmap map, ext2_ino_t *ret)
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t	dir_group = 0;
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t	i;
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t	start_inode;
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
1103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!map)
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		map = fs->inode_map;
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!map)
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_NO_INODE_BITMAP;
1153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (dir > 0)
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (start_inode < EXT2_FIRST_INODE(fs->super))
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		start_inode = EXT2_FIRST_INODE(fs->super);
1223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (start_inode > fs->super->s_inodes_count)
1233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_INODE_ALLOC_FAIL;
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	i = start_inode;
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
1273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (((i - 1) % EXT2_INODES_PER_GROUP(fs->super)) == 0)
1283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			check_inode_uninit(fs, map, (i - 1) /
1293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   EXT2_INODES_PER_GROUP(fs->super));
1303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!ext2fs_fast_test_inode_bitmap(map, i))
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		i++;
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (i > fs->super->s_inodes_count)
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			i = EXT2_FIRST_INODE(fs->super);
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} while (i != start_inode);
1373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_test_inode_bitmap(map, i))
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_INODE_ALLOC_FAIL;
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	*ret = i;
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Stupid algorithm --- we now just search forward starting from the
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * goal.  Should put in a smarter one someday....
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   ext2fs_block_bitmap map, blk_t *ret)
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	i;
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!map)
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		map = fs->block_map;
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!map)
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_NO_BLOCK_BITMAP;
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!goal || (goal >= fs->super->s_blocks_count))
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goal = fs->super->s_first_data_block;
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	i = goal;
1623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	check_block_uninit(fs, map,
1633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (i - fs->super->s_first_data_block) /
1643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   EXT2_BLOCKS_PER_GROUP(fs->super));
16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
1663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (((i - fs->super->s_first_data_block) %
1673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     EXT2_BLOCKS_PER_GROUP(fs->super)) == 0)
1683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			check_block_uninit(fs, map,
1693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   (i - fs->super->s_first_data_block) /
1703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   EXT2_BLOCKS_PER_GROUP(fs->super));
1713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!ext2fs_fast_test_block_bitmap(map, i)) {
17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			*ret = i;
17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 0;
17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		i++;
17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (i >= fs->super->s_blocks_count)
17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			i = fs->super->s_first_data_block;
17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} while (i != goal);
18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return EXT2_ET_BLOCK_ALLOC_FAIL;
18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function zeros out the allocated block, and updates all of the
18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * appropriate filesystem records.
18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     char *block_buf, blk_t *ret)
18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		block;
19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char		*buf = 0;
19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!block_buf) {
19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_get_mem(fs->blocksize, &buf);
19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		block_buf = buf;
19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	memset(block_buf, 0, fs->blocksize);
20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (fs->get_alloc_block) {
2033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		blk64_t	new;
2043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = (fs->get_alloc_block)(fs, (blk64_t) goal, &new);
20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto fail;
2083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		block = (blk_t) new;
2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
2103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!fs->block_map) {
2113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_read_block_bitmap(fs);
2123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
2133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto fail;
2143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_new_block(fs, goal, 0, &block);
2173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
2183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto fail;
2193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = io_channel_write_blk(fs->io, block, 1, block_buf);
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto fail;
2243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_block_alloc_stats(fs, block, +1);
22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	*ret = block;
22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectfail:
22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (buf)
23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_mem(&buf);
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				 int num, ext2fs_block_bitmap map, blk_t *ret)
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	b = start;
23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!map)
24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		map = fs->block_map;
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!map)
24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_NO_BLOCK_BITMAP;
24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!b)
24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		b = fs->super->s_first_data_block;
24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!finish)
24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		finish = start;
24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!num)
25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		num = 1;
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (b+num-1 > fs->super->s_blocks_count)
25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			b = fs->super->s_first_data_block;
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			*ret = b;
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 0;
25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		b++;
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} while (b != finish);
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return EXT2_ET_BLOCK_ALLOC_FAIL;
26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid ext2fs_set_alloc_block_callback(ext2_filsys fs,
2643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				     errcode_t (*func)(ext2_filsys fs,
2653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						       blk64_t goal,
2663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						       blk64_t *ret),
2673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				     errcode_t (**old)(ext2_filsys fs,
2683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						       blk64_t goal,
2693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						       blk64_t *ret))
2703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
2713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
2723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
2733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (old)
2753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		*old = fs->get_alloc_block;
2763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fs->get_alloc_block = func;
2783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
279