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