bmove.c revision c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4e
1326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek/*
2326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek * bmove.c --- Move blocks around to make way for a particular
3326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek * 	filesystem structure.
4326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek *
5326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek * Copyright (C) 1997 Theodore Ts'o.  This file may be redistributed
6326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek * under the terms of the GNU Public License.
7326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek */
8326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek
9326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#include <stdio.h>
10ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie#include <string.h>
11ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie#if HAVE_UNISTD_H
12326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#include <unistd.h>
13326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#endif
14326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#if HAVE_SYS_TYPES_H
15326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#include <sys/types.h>
16326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#endif
17326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#if HAVE_SYS_TIME_H
18326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#include <sys/time.h>
19892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek#endif
20b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek
2130a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "ext2_fs.h"
22326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek#include "ext2fsP.h"
2330a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth
2430a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruthstruct process_block_struct {
25326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	ext2_ino_t		ino;
26326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	struct ext2_inode *	inode;
27326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	ext2fs_block_bitmap	reserve;
28326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	ext2fs_block_bitmap	alloc_map;
29326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	errcode_t		error;
30326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	char			*buf;
31326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	int			add_dir;
32af13d5b25b360e698cc1cf1055ad7d14e008e505Ted Kremenek	int			flags;
33283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek};
34326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek
35a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenekstatic int process_block(ext2_filsys fs, blk_t	*block_nr,
36326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek			 e2_blkcnt_t blockcnt, blk_t ref_block,
37db34ab70961ca4b24b600eb47053d7af304659f5Tom Care			 int ref_offset, void *priv_data)
38326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek{
39326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	struct process_block_struct *pb;
40326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	errcode_t	retval;
417fa9b4f258636d89342eda28f21a986c8ac353b1Ted Kremenek	int		ret;
421d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek	blk_t		block, orig;
43ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
44b1b5daf30d2597e066936772bd206500232d7d65Ted Kremenek	pb = (struct process_block_struct *) priv_data;
45c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu	block = orig = *block_nr;
46c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu	ret = 0;
47a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek
481d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek	/*
49a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek	 * Let's see if this is one which we need to relocate
50a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek	 */
51a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek	if (ext2fs_test_block_bitmap(pb->reserve, block)) {
52a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek		do {
53a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek			if (++block >= fs->super->s_blocks_count)
54ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie				block = fs->super->s_first_data_block;
55a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek			if (block == orig) {
56a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek				pb->error = EXT2_ET_BLOCK_ALLOC_FAIL;
57a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek				return BLOCK_ABORT;
58a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek			}
59a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek		} while (ext2fs_test_block_bitmap(pb->reserve, block) ||
60a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek			 ext2fs_test_block_bitmap(pb->alloc_map, block));
61a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek
621d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek		retval = io_channel_read_blk(fs->io, orig, 1, pb->buf);
63a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek		if (retval) {
641d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek			pb->error = retval;
65a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek			return BLOCK_ABORT;
66ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		}
67ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		retval = io_channel_write_blk(fs->io, block, 1, pb->buf);
68ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		if (retval) {
69ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie			pb->error = retval;
701d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek			return BLOCK_ABORT;
71ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		}
72ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		*block_nr = block;
731d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek		ext2fs_mark_block_bitmap(pb->alloc_map, block);
74ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		ret = BLOCK_CHANGED;
75cca300a91966df70c9c320e477a3c26ba622673dTed Kremenek		if (pb->flags & EXT2_BMOVE_DEBUG)
76326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek			printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino,
776f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith			       blockcnt, orig, block);
786f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith	}
79b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek	if (pb->add_dir) {
80b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek		retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
81b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek					      block, (int) blockcnt);
82ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		if (retval) {
83ad5a894df1841698c824381b414630799adc26caTed Kremenek			pb->error = retval;
846f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith			ret |= BLOCK_ABORT;
856f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith		}
866f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith	}
87b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek	return ret;
88326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek}
89b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek
90b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenekerrcode_t ext2fs_move_blocks(ext2_filsys fs,
91b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek			     ext2fs_block_bitmap reserve,
92a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek			     ext2fs_block_bitmap alloc_map,
93a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek			     int flags)
94326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek{
951d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek	ext2_ino_t	ino;
96d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose	struct ext2_inode inode;
97bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek	errcode_t	retval;
981d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek	struct process_block_struct pb;
99b1b5daf30d2597e066936772bd206500232d7d65Ted Kremenek	ext2_inode_scan	scan;
100b1b5daf30d2597e066936772bd206500232d7d65Ted Kremenek	char		*block_buf;
101326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek
1021d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek	retval = ext2fs_open_inode_scan(fs, 0, &scan);
103326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	if (retval)
104445895a97ae3f1d7bad3480839d31ed3ebcc9c83Ted Kremenek		return retval;
105c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu
106c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu	pb.reserve = reserve;
107ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek	pb.error = 0;
108ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek	pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
109ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek	pb.flags = flags;
110ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek
111ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek	retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf);
112ddc0c4814788dda4ef224cd4d22d07154a6ede49Ted Kremenek	if (retval)
11374fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek		return retval;
11474fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek	pb.buf = block_buf + fs->blocksize * 3;
11574fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek
11674fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek	/*
11774fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek	 * If GET_DBLIST is set in the flags field, then we should
11874fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek	 * gather directory block information while we're doing the
11974fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek	 * block move.
12074fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek	 */
121ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie	if (flags & EXT2_BMOVE_GET_DBLIST) {
122f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru		if (fs->dblist) {
123326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek			ext2fs_free_dblist(fs->dblist);
124326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek			fs->dblist = NULL;
125326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek		}
126ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie		retval = ext2fs_init_dblist(fs, 0);
127b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek		if (retval)
128bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek			return retval;
129b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek	}
130b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek
131b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek	retval = ext2fs_get_next_inode(scan, &ino, &inode);
1329b823e8e1ccb8a2cb49923bad22a80ca96f41f92Ted Kremenek	if (retval)
1330d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek		return retval;
1340d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek
135ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie	while (ino) {
136a2d7e6511a8767dc67381c210601b895a8ebae39Anna Zaks		if ((inode.i_links_count == 0) ||
137326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek		    !ext2fs_inode_has_valid_blocks(&inode))
138ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie			goto next;
139283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek
14004eeba43040969c05cfcb563195ef5b199297b62Anders Carlsson		pb.ino = ino;
141af13d5b25b360e698cc1cf1055ad7d14e008e505Ted Kremenek		pb.inode = &inode;
142ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
143ad5a894df1841698c824381b414630799adc26caTed Kremenek		pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) &&
144ad5a894df1841698c824381b414630799adc26caTed Kremenek			      flags & EXT2_BMOVE_GET_DBLIST);
145ad5a894df1841698c824381b414630799adc26caTed Kremenek
146682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek		retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
14704eeba43040969c05cfcb563195ef5b199297b62Anders Carlsson					      process_block, &pb);
1485d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth		if (retval)
1495d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth			return retval;
1505d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth		if (pb.error)
1515d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth			return pb.error;
1525d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth
153326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	next:
154db34ab70961ca4b24b600eb47053d7af304659f5Tom Care		retval = ext2fs_get_next_inode(scan, &ino, &inode);
155326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
156326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek			goto next;
157326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	}
158326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek	return 0;
159326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek}
160d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek
161326be568e2cb04285c84e6e26a3e6b3822607361Ted Kremenek