11e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o/* 21e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * bmove.c --- Move blocks around to make way for a particular 31e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * filesystem structure. 41e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * 5543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * Copyright (C) 1997 Theodore Ts'o. 6543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * %Begin-Header% 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 9543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 10543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * %End-Header% 111e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 121e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 131e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o#include <stdio.h> 141e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o#include <string.h> 154cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 161e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o#include <unistd.h> 174cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 181d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H 191e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o#include <sys/types.h> 201d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 211d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TIME_H 221e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o#include <sys/time.h> 231d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 241e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 25b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 269abd2ce914f9373fb676f0bb620ffba3a0e3c49eTheodore Ts'o#include "ext2fsP.h" 271e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 281e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'ostruct process_block_struct { 2931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino; 301e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o struct ext2_inode * inode; 311e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_block_bitmap reserve; 329941fb73f530b11d3d1dcc97a585f63449703f5aTheodore Ts'o ext2fs_block_bitmap alloc_map; 331e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o errcode_t error; 341e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o char *buf; 351e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o int add_dir; 3636f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o int flags; 371e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o}; 381e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int process_block(ext2_filsys fs, blk64_t *block_nr, 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall e2_blkcnt_t blockcnt, blk64_t ref_block, 41b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o int ref_offset, void *priv_data) 421e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o{ 43b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o struct process_block_struct *pb; 441e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o errcode_t retval; 451e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o int ret; 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t block, orig; 471e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 48b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o pb = (struct process_block_struct *) priv_data; 491e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o block = orig = *block_nr; 501e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ret = 0; 51efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 521e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 531e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * Let's see if this is one which we need to relocate 541e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_block_bitmap2(pb->reserve, block)) { 561e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o do { 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (++block >= ext2fs_blocks_count(fs->super)) 581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o block = fs->super->s_first_data_block; 591e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (block == orig) { 601f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o pb->error = EXT2_ET_BLOCK_ALLOC_FAIL; 611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return BLOCK_ABORT; 621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext2fs_test_block_bitmap2(pb->reserve, block) || 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_test_block_bitmap2(pb->alloc_map, block)); 651e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_read_blk64(fs->io, orig, 1, pb->buf); 671e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) { 681e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb->error = retval; 691e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return BLOCK_ABORT; 701e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_write_blk64(fs->io, block, 1, pb->buf); 721e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) { 731e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb->error = retval; 741e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return BLOCK_ABORT; 751e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 761e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o *block_nr = block; 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(pb->alloc_map, block); 781e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ret = BLOCK_CHANGED; 7936f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o if (pb->flags & EXT2_BMOVE_DEBUG) 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("ino=%u, blockcnt=%lld, %llu->%llu\n", 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (unsigned) pb->ino, blockcnt, 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (unsigned long long) orig, 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (unsigned long long) block); 841e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 851e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (pb->add_dir) { 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_add_dir_block2(fs->dblist, pb->ino, 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall block, blockcnt); 881e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) { 891e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb->error = retval; 901e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ret |= BLOCK_ABORT; 911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 921e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 931e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return ret; 941e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o} 951e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 961e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'oerrcode_t ext2fs_move_blocks(ext2_filsys fs, 971e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_block_bitmap reserve, 989941fb73f530b11d3d1dcc97a585f63449703f5aTheodore Ts'o ext2fs_block_bitmap alloc_map, 991e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o int flags) 1001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o{ 10131dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino; 1021e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o struct ext2_inode inode; 1031e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o errcode_t retval; 1041e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o struct process_block_struct pb; 1051e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2_inode_scan scan; 1061e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o char *block_buf; 107efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1081e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_open_inode_scan(fs, 0, &scan); 1091e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) 1101e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return retval; 1111e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 1121e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb.reserve = reserve; 1131e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb.error = 0; 1149941fb73f530b11d3d1dcc97a585f63449703f5aTheodore Ts'o pb.alloc_map = alloc_map ? alloc_map : fs->block_map; 11536f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o pb.flags = flags; 116efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 117ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array(4, fs->blocksize, &block_buf); 1187b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1197b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 1201e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb.buf = block_buf + fs->blocksize * 3; 1211e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 1221e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 1231e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * If GET_DBLIST is set in the flags field, then we should 1241e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * gather directory block information while we're doing the 1251e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * block move. 1261e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 1271e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (flags & EXT2_BMOVE_GET_DBLIST) { 1281e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->dblist) { 1291e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_free_dblist(fs->dblist); 1301e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->dblist = NULL; 1311e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 1321e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_init_dblist(fs, 0); 1331e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) 1341e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return retval; 1351e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 1361e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 1371e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 1381e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) 1391e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return retval; 140efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o while (ino) { 1421e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if ((inode.i_links_count == 0) || 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_inode_has_valid_blocks2(fs, &inode)) 1441e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o goto next; 145efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1461e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb.ino = ino; 1471e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb.inode = &inode; 1481e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 1491e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && 1501e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o flags & EXT2_BMOVE_GET_DBLIST); 1511e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_block_iterate3(fs, ino, 0, block_buf, 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall process_block, &pb); 1541e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) 1551e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return retval; 1561e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (pb.error) 1571e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return pb.error; 1581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 1591e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o next: 1601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 1611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) 1621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o goto next; 1631e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 1641e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return 0; 1651e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o} 1661e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 167