bmove.c revision e0ed7404719a9ddd2ba427a80db5365c8bad18c0
193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke/*
293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke * bmove.c --- Move blocks around to make way for a particular
393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke * 	filesystem structure.
493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke *
593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke * Copyright (C) 1997 Theodore Ts'o.
693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke *
793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke * %Begin-Header%
893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke * This file may be redistributed under the terms of the GNU Library
993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke * General Public License, version 2.
1093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke * %End-Header%
1193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke */
1293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
1393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#include <stdio.h>
1493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#include <string.h>
1593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#if HAVE_UNISTD_H
1693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#include <unistd.h>
1793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#endif
1893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#if HAVE_SYS_TYPES_H
1993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#include <sys/types.h>
2093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#endif
2193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#if HAVE_SYS_TIME_H
2293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#include <sys/time.h>
2393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#endif
2493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
2593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#include "ext2_fs.h"
2693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke#include "ext2fsP.h"
2793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
2893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzkestruct process_block_struct {
2993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	ext2_ino_t		ino;
3093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	struct ext2_inode *	inode;
3193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	ext2fs_block_bitmap	reserve;
3293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	ext2fs_block_bitmap	alloc_map;
3393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	errcode_t		error;
3493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	char			*buf;
35c0f8c9911c82c576cdd82dabad4a2370ac53565cKristian Høgsberg	int			add_dir;
36c0f8c9911c82c576cdd82dabad4a2370ac53565cKristian Høgsberg	int			flags;
3793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke};
3893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
3993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzkestatic int process_block(ext2_filsys fs, blk64_t *block_nr,
406b369c4c7cd8a52f99bbff2a57fb316b33a87495Benjamin Franzke			 e2_blkcnt_t blockcnt, blk64_t ref_block,
416b369c4c7cd8a52f99bbff2a57fb316b33a87495Benjamin Franzke			 int ref_offset, void *priv_data)
426b369c4c7cd8a52f99bbff2a57fb316b33a87495Benjamin Franzke{
4351f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	struct process_block_struct *pb;
4451f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	errcode_t	retval;
4551f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	int		ret;
4651f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	blk64_t		block, orig;
4751f2820922b669af3947fcedd17109524644bb94Benjamin Franzke
4851f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	pb = (struct process_block_struct *) priv_data;
4951f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	block = orig = *block_nr;
5051f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	ret = 0;
5151f2820922b669af3947fcedd17109524644bb94Benjamin Franzke
5251f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	/*
5351f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	 * Let's see if this is one which we need to relocate
5451f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	 */
5551f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	if (ext2fs_test_block_bitmap2(pb->reserve, block)) {
5651f2820922b669af3947fcedd17109524644bb94Benjamin Franzke		do {
5751f2820922b669af3947fcedd17109524644bb94Benjamin Franzke			if (++block >= ext2fs_blocks_count(fs->super))
5851f2820922b669af3947fcedd17109524644bb94Benjamin Franzke				block = fs->super->s_first_data_block;
5951f2820922b669af3947fcedd17109524644bb94Benjamin Franzke			if (block == orig) {
6051f2820922b669af3947fcedd17109524644bb94Benjamin Franzke				pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
6151f2820922b669af3947fcedd17109524644bb94Benjamin Franzke				return BLOCK_ABORT;
620cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			}
630cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		} while (ext2fs_test_block_bitmap2(pb->reserve, block) ||
640cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			 ext2fs_test_block_bitmap2(pb->alloc_map, block));
650cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke
660cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		retval = io_channel_read_blk64(fs->io, orig, 1, pb->buf);
670cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		if (retval) {
680cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			pb->error = retval;
690cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			return BLOCK_ABORT;
700cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		}
710cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		retval = io_channel_write_blk64(fs->io, block, 1, pb->buf);
720cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		if (retval) {
730cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			pb->error = retval;
740cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			return BLOCK_ABORT;
750cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		}
760cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		*block_nr = block;
770cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		ext2fs_mark_block_bitmap2(pb->alloc_map, block);
780cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		ret = BLOCK_CHANGED;
790cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke		if (pb->flags & EXT2_BMOVE_DEBUG)
800cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			printf("ino=%u, blockcnt=%lld, %llu->%llu\n",
810cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			       (unsigned) pb->ino, blockcnt,
820cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			       (unsigned long long) orig,
830cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke			       (unsigned long long) block);
840cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke	}
8551f2820922b669af3947fcedd17109524644bb94Benjamin Franzke	if (pb->add_dir) {
8693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
8793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke					       block, blockcnt);
8893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		if (retval) {
8993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			pb->error = retval;
9093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			ret |= BLOCK_ABORT;
9193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		}
9293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	}
9393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	return ret;
9493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke}
9593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
9693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzkeerrcode_t ext2fs_move_blocks(ext2_filsys fs,
9793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			     ext2fs_block_bitmap reserve,
9893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			     ext2fs_block_bitmap alloc_map,
9993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			     int flags)
10093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke{
10193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	ext2_ino_t	ino;
10293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	struct ext2_inode inode;
10393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	errcode_t	retval;
10493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	struct process_block_struct pb;
10593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	ext2_inode_scan	scan;
10693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	char		*block_buf;
10793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
10893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	retval = ext2fs_open_inode_scan(fs, 0, &scan);
10993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	if (retval)
11093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		return retval;
1110cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke
11293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	pb.reserve = reserve;
1130cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke	pb.error = 0;
1140cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke	pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
11593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	pb.flags = flags;
11693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
11793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	retval = ext2fs_get_array(4, fs->blocksize, &block_buf);
11893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	if (retval)
11951f2820922b669af3947fcedd17109524644bb94Benjamin Franzke		return retval;
1200cb356dd5c93f745bb1b17987d206a24ab708f31Benjamin Franzke	pb.buf = block_buf + fs->blocksize * 3;
12193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
12293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	/*
12393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	 * If GET_DBLIST is set in the flags field, then we should
12493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	 * gather directory block information while we're doing the
12593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	 * block move.
12693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	 */
12793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	if (flags & EXT2_BMOVE_GET_DBLIST) {
12893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		if (fs->dblist) {
12993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			ext2fs_free_dblist(fs->dblist);
13093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			fs->dblist = NULL;
13193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		}
13293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		retval = ext2fs_init_dblist(fs, 0);
13393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		if (retval)
13493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			return retval;
13593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	}
136c0f8c9911c82c576cdd82dabad4a2370ac53565cKristian Høgsberg
13793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	retval = ext2fs_get_next_inode(scan, &ino, &inode);
13893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	if (retval)
13993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		return retval;
14093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
14193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	while (ino) {
14293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		if ((inode.i_links_count == 0) ||
14393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		    !ext2fs_inode_has_valid_blocks2(fs, &inode))
14493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			goto next;
14593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
14693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		pb.ino = ino;
14787dde5b1cd596c4008695ff2db9469f88c09f925Benjamin Franzke		pb.inode = &inode;
14887dde5b1cd596c4008695ff2db9469f88c09f925Benjamin Franzke
14987dde5b1cd596c4008695ff2db9469f88c09f925Benjamin Franzke		pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
15087dde5b1cd596c4008695ff2db9469f88c09f925Benjamin Franzke			      flags & EXT2_BMOVE_GET_DBLIST);
15193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
15293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		retval = ext2fs_block_iterate3(fs, ino, 0, block_buf,
15393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke					       process_block, &pb);
15493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		if (retval)
15593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			return retval;
15693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		if (pb.error)
15793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			return pb.error;
15893aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
15993aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	next:
16093aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		retval = ext2fs_get_next_inode(scan, &ino, &inode);
16193aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
16293aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke			goto next;
16393aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	}
16493aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke	return 0;
16593aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke}
16693aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke
16793aea84f472f5f9ff588f7b2d4f7320ec43bc216Benjamin Franzke