2 * swapfs.c --- byte-swap an ext2 filesystem
4 * Copyright 1996, 1997 by Theodore Ts'o
7 * This file may be redistributed under the terms of the GNU Public
16 #include <et/com_err.h>
19 struct swap_block_struct {
24 struct ext2_inode *inode;
28 * This is a helper function for block_iterate. We mark all of the
29 * indirect and direct blocks as changed, so that block_iterate will
32 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
37 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
39 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
40 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
45 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
52 if (blockcnt < EXT2_NDIR_BLOCKS)
56 if (blockcnt == BLOCK_COUNT_IND) {
57 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
61 if (blockcnt == BLOCK_COUNT_DIND) {
62 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
66 if (blockcnt == BLOCK_COUNT_TIND) {
67 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
75 * This function is responsible for byte-swapping all of the indirect,
76 * block pointers. It is also responsible for byte-swapping directories.
78 static void swap_inode_blocks(e2fsck_t ctx, ino_t ino, char *block_buf,
79 struct ext2_inode *inode)
82 struct swap_block_struct sb;
86 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
89 if (LINUX_S_ISDIR(inode->i_mode))
92 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
95 com_err("swap_inode_blocks", retval,
96 "while calling ext2fs_block_iterate");
97 ctx->flags |= E2F_FLAG_ABORT;
101 com_err("swap_inode_blocks", sb.errcode,
102 "while calling iterator function");
103 ctx->flags |= E2F_FLAG_ABORT;
108 static void swap_inodes(e2fsck_t ctx)
110 ext2_filsys fs = ctx->fs;
113 char *buf, *block_buf;
115 struct ext2_inode * inode;
117 e2fsck_use_inode_shortcuts(ctx, 1);
119 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
122 com_err("swap_inodes", retval,
123 "while allocating inode buffer");
124 ctx->flags |= E2F_FLAG_ABORT;
127 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
128 "block interate buffer");
129 for (group = 0; group < fs->group_desc_count; group++) {
130 retval = io_channel_read_blk(fs->io,
131 fs->group_desc[group].bg_inode_table,
132 fs->inode_blocks_per_group, buf);
134 com_err("swap_inodes", retval,
135 "while reading inode table (group %d)",
137 ctx->flags |= E2F_FLAG_ABORT;
140 inode = (struct ext2_inode *) buf;
141 for (i=0; i < fs->super->s_inodes_per_group;
142 i++, ino++, inode++) {
143 ctx->stashed_ino = ino;
144 ctx->stashed_inode = inode;
146 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
147 ext2fs_swap_inode(fs, inode, inode, 0);
150 * Skip deleted files.
152 if (inode->i_links_count == 0)
155 if (LINUX_S_ISDIR(inode->i_mode) ||
156 ((inode->i_block[EXT2_IND_BLOCK] ||
157 inode->i_block[EXT2_DIND_BLOCK] ||
158 inode->i_block[EXT2_TIND_BLOCK]) &&
159 ext2fs_inode_has_valid_blocks(inode)))
160 swap_inode_blocks(ctx, ino, block_buf, inode);
162 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
165 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
166 ext2fs_swap_inode(fs, inode, inode, 1);
168 retval = io_channel_write_blk(fs->io,
169 fs->group_desc[group].bg_inode_table,
170 fs->inode_blocks_per_group, buf);
172 com_err("swap_inodes", retval,
173 "while writing inode table (group %d)",
175 ctx->flags |= E2F_FLAG_ABORT;
179 ext2fs_free_mem((void **) &buf);
180 ext2fs_free_mem((void **) &block_buf);
181 e2fsck_use_inode_shortcuts(ctx, 0);
184 void swap_filesys(e2fsck_t ctx)
186 ext2_filsys fs = ctx->fs;
187 #ifdef RESOURCE_TRACK
188 struct resource_track rtrack;
190 init_resource_track(&rtrack);
193 if (!(ctx->options & E2F_OPT_PREEN))
194 printf("Pass 0: Doing byte-swap of filesystem\n");
197 mtrace_print("Byte swap");
200 if (fs->super->s_mnt_count) {
201 fprintf(stderr, "%s: the filesystem must be freshly "
202 "checked using fsck\n"
203 "and not mounted before trying to "
204 "byte-swap it.\n", ctx->device_name);
205 ctx->flags |= E2F_FLAG_ABORT;
208 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
209 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
210 EXT2_FLAG_SWAP_BYTES_WRITE);
211 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
213 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
214 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
217 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
219 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
220 fs->flags |= EXT2_FLAG_SWAP_BYTES;
221 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
222 EXT2_FLAG_SWAP_BYTES_WRITE);
225 #ifdef RESOURCE_TRACK
226 if (ctx->options & E2F_OPT_TIME2)
227 print_resource_track("Byte swap", &rtrack);