119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * bmove.c --- Move blocks around to make way for a particular
319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 	filesystem structure.
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
58558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * Copyright (C) 1997 Theodore Ts'o.
68558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall *
78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * %Begin-Header%
88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library
98558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2.
108558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * %End-Header%
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h>
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_TYPES_H
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h>
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_TIME_H
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/time.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 "ext2fsP.h"
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct process_block_struct {
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t		ino;
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode *	inode;
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_block_bitmap	reserve;
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_block_bitmap	alloc_map;
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t		error;
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char			*buf;
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			add_dir;
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			flags;
3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int process_block(ext2_filsys fs, blk_t	*block_nr,
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 e2_blkcnt_t blockcnt, blk_t ref_block,
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 int ref_offset, void *priv_data)
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct process_block_struct *pb;
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		ret;
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		block, orig;
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb = (struct process_block_struct *) priv_data;
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	block = orig = *block_nr;
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ret = 0;
513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Let's see if this is one which we need to relocate
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_test_block_bitmap(pb->reserve, block)) {
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		do {
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (++block >= fs->super->s_blocks_count)
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				block = fs->super->s_first_data_block;
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (block == orig) {
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				return BLOCK_ABORT;
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} while (ext2fs_test_block_bitmap(pb->reserve, block) ||
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 ext2fs_test_block_bitmap(pb->alloc_map, block));
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval) {
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pb->error = retval;
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval) {
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pb->error = retval;
7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return BLOCK_ABORT;
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*block_nr = block;
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_block_bitmap(pb->alloc_map, block);
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ret = BLOCK_CHANGED;
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (pb->flags & EXT2_BMOVE_DEBUG)
8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			printf("ino=%ld, blockcnt=%lld, %u->%u\n", pb->ino,
8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       blockcnt, orig, block);
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pb->add_dir) {
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					      block, (int) blockcnt);
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval) {
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pb->error = retval;
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ret |= BLOCK_ABORT;
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ret;
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_move_blocks(ext2_filsys fs,
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     ext2fs_block_bitmap reserve,
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     ext2fs_block_bitmap alloc_map,
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     int flags)
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t	ino;
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode inode;
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct process_block_struct pb;
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_inode_scan	scan;
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char		*block_buf;
1053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_open_inode_scan(fs, 0, &scan);
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.reserve = reserve;
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.error = 0;
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.flags = flags;
1143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_get_array(4, fs->blocksize, &block_buf);
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.buf = block_buf + fs->blocksize * 3;
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If GET_DBLIST is set in the flags field, then we should
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * gather directory block information while we're doing the
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * block move.
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (flags & EXT2_BMOVE_GET_DBLIST) {
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fs->dblist) {
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_free_dblist(fs->dblist);
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->dblist = NULL;
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_init_dblist(fs, 0);
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_get_next_inode(scan, &ino, &inode);
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return retval;
1383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (ino) {
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((inode.i_links_count == 0) ||
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    !ext2fs_inode_has_valid_blocks(&inode))
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
1433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.ino = ino;
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.inode = &inode;
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      flags & EXT2_BMOVE_GET_DBLIST);
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					      process_block, &pb);
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval)
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return retval;
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (pb.error)
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return pb.error;
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	next:
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_get_next_inode(scan, &ino, &inode);
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto next;
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
165