119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * bb_inode.c --- routines to update the bad block inode.
33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * WARNING: This routine modifies a lot of state in the filesystem; if
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * this routine returns an error, the bad block inode may be in an
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * inconsistent state.
73984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1994, 1995 Theodore Ts'o.
93984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file may be redistributed under the terms of the GNU Public
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * License.
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h>
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <fcntl.h>
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h>
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_STAT_H
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/stat.h>
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_TYPES_H
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h>
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h"
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs.h"
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct set_badblock_record {
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_badblocks_iterate	bb_iter;
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		bad_block_count;
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		*ind_blocks;
3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		max_ind_blocks;
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		ind_blocks_size;
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		ind_blocks_ptr;
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char		*block_buf;
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	err;
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      e2_blkcnt_t blockcnt,
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      blk_t ref_block, int ref_offset,
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      void *priv_data);
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				e2_blkcnt_t blockcnt,
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				blk_t ref_block, int ref_offset,
5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				void *priv_data);
523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Given a bad blocks bitmap, update the bad blocks inode to reflect
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * the map.
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t			retval;
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct set_badblock_record 	rec;
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode		inode;
623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!fs->block_map)
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return EXT2_ET_NO_BLOCK_BITMAP;
673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	rec.bad_block_count = 0;
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	rec.max_ind_blocks = 10;
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_get_array(rec.max_ind_blocks, sizeof(blk_t),
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				&rec.ind_blocks);
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto cleanup;
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	memset(rec.block_buf, 0, fs->blocksize);
8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	rec.err = 0;
813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * First clear the old bad blocks (while saving the indirect blocks)
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       BLOCK_FLAG_DEPTH_TRAVERSE, 0,
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       clear_bad_block_proc, &rec);
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto cleanup;
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (rec.err) {
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = rec.err;
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto cleanup;
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Now set the bad blocks!
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 *
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * First, mark the bad blocks as used.  This prevents a bad
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * block from being used as an indirecto block for the bad
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * block inode (!).
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (bb_list) {
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_badblocks_list_iterate_begin(bb_list,
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							     &rec.bb_iter);
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto cleanup;
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					       BLOCK_FLAG_APPEND, 0,
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					       set_bad_block_proc, &rec);
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_badblocks_list_iterate_end(rec.bb_iter);
1113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto cleanup;
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (rec.err) {
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			retval = rec.err;
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto cleanup;
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
1183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Update the bad block inode's mod time and block count
1213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * field.
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto cleanup;
1263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0);
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!inode.i_ctime)
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		inode.i_ctime = fs->now ? fs->now : time(0);
1303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_iblk_set(fs, &inode, rec.bad_block_count);
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	inode.i_size = rec.bad_block_count * fs->blocksize;
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto cleanup;
1363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectcleanup:
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&rec.ind_blocks);
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&rec.block_buf);
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Helper function for update_bb_inode()
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Clear the bad blocks in the bad block inode, while saving the
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * indirect blocks.
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef __TURBOC__
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project #pragma argsused
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				e2_blkcnt_t blockcnt,
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				blk_t ref_block EXT2FS_ATTR((unused)),
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				int ref_offset EXT2FS_ATTR((unused)),
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				void *priv_data)
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct set_badblock_record *rec = (struct set_badblock_record *)
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		priv_data;
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned long 	old_size;
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!*block_nr)
16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If the block number is outrageous, clear it and ignore it.
16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (*block_nr >= fs->super->s_blocks_count ||
17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    *block_nr < fs->super->s_first_data_block) {
17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*block_nr = 0;
17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return BLOCK_CHANGED;
17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (blockcnt < 0) {
17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (rec->ind_blocks_size >= rec->max_ind_blocks) {
17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			old_size = rec->max_ind_blocks * sizeof(blk_t);
17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			rec->max_ind_blocks += 10;
1793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_resize_mem(old_size,
18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   rec->max_ind_blocks * sizeof(blk_t),
18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   &rec->ind_blocks);
18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (retval) {
18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				rec->max_ind_blocks -= 10;
18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				rec->err = retval;
18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				return BLOCK_ABORT;
18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Mark the block as unused, and update accounting information
19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_block_alloc_stats(fs, *block_nr, -1);
1953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	*block_nr = 0;
19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return BLOCK_CHANGED;
19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Helper function for update_bb_inode()
20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Set the block list in the bad block inode, using the supplied bitmap.
20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef __TURBOC__
20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project #pragma argsused
20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      e2_blkcnt_t blockcnt,
21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      blk_t ref_block EXT2FS_ATTR((unused)),
21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      int ref_offset EXT2FS_ATTR((unused)),
21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      void *priv_data)
21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct set_badblock_record *rec = (struct set_badblock_record *)
21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		priv_data;
21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		blk;
21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (blockcnt >= 0) {
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * Get the next bad block.
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		rec->bad_block_count++;
22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * An indirect block; fetch a block from the
23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * previously used indirect block list.  The block
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * most be not marked as used; if so, get another one.
23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * If we run out of reserved indirect blocks, allocate
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * a new one.
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retry:
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			blk = rec->ind_blocks[rec->ind_blocks_ptr++];
23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (ext2fs_test_block_bitmap(fs->block_map, blk))
23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto retry;
24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else {
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			retval = ext2fs_new_block(fs, 0, 0, &blk);
24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (retval) {
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				rec->err = retval;
24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				return BLOCK_ABORT;
24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval) {
24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			rec->err = retval;
25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
2533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Update block counts
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_block_alloc_stats(fs, blk, +1);
2583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	*block_nr = blk;
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return BLOCK_CHANGED;
26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
268