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