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>
21 struct swap_block_struct {
26 struct ext2_inode *inode;
30 * This is a helper function for block_iterate. We mark all of the
31 * indirect and direct blocks as changed, so that block_iterate will
34 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
39 struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
41 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
42 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
47 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
54 if (blockcnt < EXT2_NDIR_BLOCKS)
58 if (blockcnt == BLOCK_COUNT_IND) {
59 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
63 if (blockcnt == BLOCK_COUNT_DIND) {
64 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
68 if (blockcnt == BLOCK_COUNT_TIND) {
69 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
77 * This function is responsible for byte-swapping all of the indirect,
78 * block pointers. It is also responsible for byte-swapping directories.
80 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
81 struct ext2_inode *inode)
84 struct swap_block_struct sb;
88 sb.dir_buf = block_buf + ctx->fs->blocksize*3;
91 if (LINUX_S_ISDIR(inode->i_mode))
94 retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
97 com_err("swap_inode_blocks", retval,
98 _("while calling ext2fs_block_iterate"));
99 ctx->flags |= E2F_FLAG_ABORT;
103 com_err("swap_inode_blocks", sb.errcode,
104 _("while calling iterator function"));
105 ctx->flags |= E2F_FLAG_ABORT;
110 static void swap_inodes(e2fsck_t ctx)
112 ext2_filsys fs = ctx->fs;
115 char *buf, *block_buf;
117 struct ext2_inode * inode;
119 e2fsck_use_inode_shortcuts(ctx, 1);
121 retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
124 com_err("swap_inodes", retval,
125 _("while allocating inode buffer"));
126 ctx->flags |= E2F_FLAG_ABORT;
129 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
130 "block interate buffer");
131 for (group = 0; group < fs->group_desc_count; group++) {
132 retval = io_channel_read_blk(fs->io,
133 fs->group_desc[group].bg_inode_table,
134 fs->inode_blocks_per_group, buf);
136 com_err("swap_inodes", retval,
137 _("while reading inode table (group %d)"),
139 ctx->flags |= E2F_FLAG_ABORT;
142 inode = (struct ext2_inode *) buf;
143 for (i=0; i < fs->super->s_inodes_per_group;
144 i++, ino++, inode++) {
145 ctx->stashed_ino = ino;
146 ctx->stashed_inode = inode;
148 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
149 ext2fs_swap_inode(fs, inode, inode, 0);
152 * Skip deleted files.
154 if (inode->i_links_count == 0)
157 if (LINUX_S_ISDIR(inode->i_mode) ||
158 ((inode->i_block[EXT2_IND_BLOCK] ||
159 inode->i_block[EXT2_DIND_BLOCK] ||
160 inode->i_block[EXT2_TIND_BLOCK]) &&
161 ext2fs_inode_has_valid_blocks(inode)))
162 swap_inode_blocks(ctx, ino, block_buf, inode);
164 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
167 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
168 ext2fs_swap_inode(fs, inode, inode, 1);
170 retval = io_channel_write_blk(fs->io,
171 fs->group_desc[group].bg_inode_table,
172 fs->inode_blocks_per_group, buf);
174 com_err("swap_inodes", retval,
175 _("while writing inode table (group %d)"),
177 ctx->flags |= E2F_FLAG_ABORT;
181 ext2fs_free_mem(&buf);
182 ext2fs_free_mem(&block_buf);
183 e2fsck_use_inode_shortcuts(ctx, 0);
186 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
188 * On the PowerPC, the big-endian variant of the ext2 filesystem
189 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
190 * of each word. Thus a bitmap with only bit 0 set would be, as
191 * a string of bytes, 00 00 00 01 00 ...
192 * To cope with this, we byte-reverse each word of a bitmap if
193 * we have a big-endian filesystem, that is, if we are *not*
194 * byte-swapping other word-sized numbers.
196 #define EXT2_BIG_ENDIAN_BITMAPS
199 #ifdef EXT2_BIG_ENDIAN_BITMAPS
200 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
202 __u32 *p = (__u32 *) bmap->bitmap;
203 int n, nbytes = (bmap->end - bmap->start + 7) / 8;
205 for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
206 *p = ext2fs_swab32(*p);
211 void swap_filesys(e2fsck_t ctx)
213 ext2_filsys fs = ctx->fs;
214 #ifdef RESOURCE_TRACK
215 struct resource_track rtrack;
217 init_resource_track(&rtrack);
220 if (!(ctx->options & E2F_OPT_PREEN))
221 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
224 mtrace_print("Byte swap");
227 if (fs->super->s_mnt_count) {
228 fprintf(stderr, _("%s: the filesystem must be freshly "
229 "checked using fsck\n"
230 "and not mounted before trying to "
231 "byte-swap it.\n"), ctx->device_name);
232 ctx->flags |= E2F_FLAG_ABORT;
235 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
236 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
237 EXT2_FLAG_SWAP_BYTES_WRITE);
238 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
240 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
241 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
244 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
246 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
247 fs->flags |= EXT2_FLAG_SWAP_BYTES;
248 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
249 EXT2_FLAG_SWAP_BYTES_WRITE);
251 #ifdef EXT2_BIG_ENDIAN_BITMAPS
252 e2fsck_read_bitmaps(ctx);
253 ext2fs_swap_bitmap(fs->inode_map);
254 ext2fs_swap_bitmap(fs->block_map);
255 fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
257 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
259 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
261 #ifdef RESOURCE_TRACK
262 if (ctx->options & E2F_OPT_TIME2)
263 print_resource_track(_("Byte swap"), &rtrack);