Checkin of e2fsprogs 1.03.
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
+E2fsprogs 1.03 (March 27, 1996)
+===============================
+
+Change the m68k bit numbering for bitmasks to match the bit numbering
+used by all other ext2 implementations. (This change was requested by
+the m68k kernel development team.)
+
+Support (in-development) filesystem format revision which supports
+(among other things) dynamically sized inodes.
+
+Fixed a bug in the ext2 library so that an intelligent error is
+returned if mke2fs is run with a ridiculously small number of blocks
+for a partition.
+
+Fixed a bug in the ext2 library which required that the device be
+openable in read/write mode in order to determine its size. This
+caused e2fsck -n to require read/write access when it was not
+previously necessary.
+
+Fixed a bug in e2fsck which casued it to occasionally fail the test
+suite depending on which version of the floating point library it was
+using.
+
+Fixed a bug in e2fsck so that it now halts with a fatal error when
+certain superblock consistency checks fail. Previously it continued
+running e2fsck, with some potential confusing/damaging consequences.
+
+Added new flag to fsck which allows the root to be checked in parallel
+with other filesytems. This is not the safest thing in the world to
+do, but some system administrators really wanted it.
+
E2fsprogs 1.02 (January 16, 1996)
=================================
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
fprintf(out, "Superblock size = %d\n", sizeof(struct ext2_super_block));
fprintf(out, "Block size = %d, fragment size = %d\n",
EXT2_BLOCK_SIZE(fs->super), EXT2_FRAG_SIZE(fs->super));
+ fprintf(out, "Inode size = %d\n", EXT2_INODE_SIZE(fs->super));
fprintf(out, "%d inodes, %d free\n", fs->super->s_inodes_count,
fs->super->s_free_inodes_count);
fprintf(out, "%d blocks, %d free, %d reserved, first block = %d\n",
fprintf(out, "%d blocks per group\n", fs->super->s_blocks_per_group);
fprintf(out, "%d fragments per group\n", fs->super->s_frags_per_group);
fprintf(out, "%d inodes per group\n", EXT2_INODES_PER_GROUP(fs->super));
- fprintf(out, "%d inodes per block\n", EXT2_INODES_PER_BLOCK(fs->super));
fprintf(out, "%ld group%s (%ld descriptors block%s)\n",
fs->group_desc_count, (fs->group_desc_count != 1) ? "s" : "",
fs->desc_blocks, (fs->desc_blocks != 1) ? "s" : "");
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
+Tue Mar 26 12:03:42 1996 <tytso@rsts-11.mit.edu>
+
+ * e2fsck.c (show_stats): Don't use floating point to display
+ percentage of non-contiguous files, as different libc
+ handle result truncation differently, and this causes the
+ test suite to bomb out depending on which libc you are
+ using.
+
+ * util.c (allocate_memory): Fix error message to omit extraneous
+ %%s.
+
+Tue Mar 5 03:50:40 1996 <tytso@rsts-11.mit.edu>
+
+ * pass4.c (pass4):
+ * pass2.c (check_dir_block):
+ * pass1.c (pass1): Add support for dynamic first inode revision.
+
+Wed Feb 14 16:27:30 1996 <tytso@rsts-11.mit.edu>
+
+ * pass3.c (check_root): Fix spelling typo
+
+Mon Feb 5 22:30:30 1996 <tytso@rsts-11.mit.edu>
+
+ * e2fsck.c (check_super_block): If the superblock fails certain
+ internal consistency checks, exit with a fatal error after
+ printing the "superblock is corrupt message".
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
int inodes, inodes_used, blocks, blocks_used;
int dir_links;
int num_files, num_links;
+ int frag_percent;
dir_links = 2 * fs_directory_count - 1;
num_files = fs_total_count - dir_links;
blocks = fs->super->s_blocks_count;
blocks_used = (fs->super->s_blocks_count -
fs->super->s_free_blocks_count);
+
+ frag_percent = (10000 * fs_fragmented) / inodes_used;
+ frag_percent = (frag_percent + 5) / 10;
if (!verbose) {
- printf("%s: %d/%d files (%3.1f%% non-contiguous), %d/%d blocks\n",
+ printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
device_name, inodes_used, inodes,
- 100.00 * fs_fragmented / inodes_used,
+ frag_percent / 10, frag_percent % 10,
blocks_used, blocks);
return;
}
printf ("\n%8d inode%s used (%d%%)\n", inodes_used,
(inodes_used != 1) ? "s" : "",
100 * inodes_used / inodes);
- printf ("%8d non-contiguous inodes (%3.1f%%)\n",
- fs_fragmented, 100.00 * fs_fragmented / inodes_used);
+ printf ("%8d non-contiguous inodes (%0d.%d%%)\n",
+ fs_fragmented, frag_percent / 10, frag_percent % 10);
printf (" # of inodes with ind/dind/tind blocks: %d/%d/%d\n",
fs_ind_count, fs_dind_count, fs_tind_count);
printf ("%8d block%s used (%d%%)\n"
"have been %u\n", s->s_blocks_per_group,
should_be);
printf(corrupt_msg);
+ fatal_error(0);
}
should_be = (s->s_log_block_size == 0) ? 1 : 0;
"have been %u\n", s->s_first_data_block,
should_be);
printf(corrupt_msg);
+ fatal_error(0);
}
/*
#ifdef EXT2_CURRENT_REV
if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
- com_err(program_name, retval, "while trying to open %s",
+ com_err(program_name, EXT2_ET_REV_TOO_HIGH,
+ "while trying to open %s",
filesystem_name);
printf ("Get a newer version of e2fsck!\n");
fatal_error(0);
ext2fs_unmark_valid(fs);
}
}
- if ((ino != EXT2_ROOT_INO) && (ino < EXT2_FIRST_INO)) {
+ if ((ino != EXT2_ROOT_INO) &&
+ (ino < EXT2_FIRST_INODE(fs->super))) {
ext2fs_mark_inode_bitmap(inode_used_map, ino);
if (inode.i_mode != 0) {
printf("Reserved inode %lu has bad mode. ", ino);
* Make sure the inode listed is a legal one.
*/
if (((dirent->inode != EXT2_ROOT_INO) &&
- (dirent->inode < EXT2_FIRST_INO)) ||
+ (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
(dirent->inode > fs->super->s_inodes_count)) {
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
if (retval)
printf("Root inode not allocated. ");
preenhalt(fs);
- if (!ask("Rellocate", 1)) {
+ if (!ask("Reallocate", 1)) {
ext2fs_unmark_valid(fs);
fatal_error("Cannot proceed without a root inode.");
}
printf("Pass 4: Checking reference counts\n");
for (i=1; i <= fs->super->s_inodes_count; i++) {
if (i == EXT2_BAD_INO ||
- (i > EXT2_ROOT_INO && i < EXT2_FIRST_INO))
+ (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
continue;
if (!(ext2fs_test_inode_bitmap(inode_used_map, i)))
continue;
#endif
ret = malloc(size);
if (!ret) {
- sprintf(buf, "%%s: Can't allocate %s\n", description);
+ sprintf(buf, "Can't allocate %s\n", description);
fatal_error(buf);
}
memset(ret, 0, size);
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
printf ("(group %s)\n", gr->gr_name);
}
+#ifndef EXT2_INODE_SIZE
+#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
+#endif
+
void list_super (struct ext2_super_block * s)
{
+ int inode_blocks_per_group;
+
+ inode_blocks_per_group = (((s->s_inodes_per_group *
+ EXT2_INODE_SIZE(s)) +
+ EXT2_BLOCK_SIZE(s) - 1) /
+ EXT2_BLOCK_SIZE(s));
+
printf ("Filesystem magic number: 0x%04X\n", s->s_magic);
+ printf ("Filesystem revision #: %d\n", s->s_rev_level);
printf ("Filesystem state: ");
print_fs_state (stdout, s->s_state);
printf ("\n");
printf ("Blocks per group: %u\n", s->s_blocks_per_group);
printf ("Fragments per group: %u\n", s->s_frags_per_group);
printf ("Inodes per group: %u\n", s->s_inodes_per_group);
+ printf ("Inode blocks per group: %u\n", inode_blocks_per_group);
printf ("Last mount time: %s", ctime ((time_t *) &s->s_mtime));
printf ("Last write time: %s", ctime ((time_t *) &s->s_wtime));
printf ("Mount count: %u\n", s->s_mnt_count);
printf ("Reserved blocks gid: ");
print_group (s->s_def_resgid);
#endif
+#ifdef EXT2_DYNAMIC_REV
+ if (s->s_rev_level >= EXT2_DYNAMIC_REV) {
+ printf("First inode: %d\n", s->s_first_ino);
+ printf("Inode size: %d\n", s->s_inode_size);
+ }
+#endif
}
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
+Tue Mar 26 12:06:32 1996 <tytso@rsts-11.mit.edu>
+
+ * bitops.h (ext2fs_set_bit, ext2fs_clear_bit, ext2fs_test_bit):
+ Change the m68k bit numbering for bitmasks to match with
+ the bit numbering used by all other ext2 implementations.
+
+Thu Mar 7 03:37:00 1996 <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_get_next_inode, ext2fs_close_inode_scan,
+ ext2fs_open_inode_scan): Support dynamically-sized inodes.
+
+Wed Mar 6 12:26:29 1996 <tytso@rsts-11.mit.edu>
+
+ * inode.c (ext2fs_read_inode, ext2fs_write_inode): Support
+ dynamically-sized inodes.
+
+ * openfs.c (ext2fs_open): Allow dynamic revision filesystem to be
+ loaded.
+
+Tue Mar 5 03:49:37 1996 <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Catch an error condition where
+ the passed in size is *really* too small.
+
+ * alloc.c (ext2fs_new_inode):
+ * ext2fs.h (EXT2_FIRST_INODE): Add support for dynamic revision to
+ get first inode.
+
+Wed Feb 21 15:56:17 1996 <tytso@rsts-11.mit.edu>
+
+ * getsize.c (ext2fs_get_device_size): Open the device read-only
+ when trying to determine its size.
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
- if (start_inode < EXT2_FIRST_INO)
- start_inode = EXT2_FIRST_INO;
+ if (start_inode < EXT2_FIRST_INODE(fs->super))
+ start_inode = EXT2_FIRST_INODE(fs->super);
i = start_inode;
do {
break;
i++;
if (i > fs->super->s_inodes_count)
- i = EXT2_FIRST_INO;
+ i = EXT2_FIRST_INODE(fs->super);
} while (i != start_inode);
if (ext2fs_test_inode_bitmap(map, i))
char retval;
__asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
- : "=d" (retval) : "d" (nr), "a" (addr));
+ : "=d" (retval) : "d" (nr^7), "a" (addr));
return retval;
}
char retval;
__asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
- : "=d" (retval) : "d" (nr), "a" (addr));
+ : "=d" (retval) : "d" (nr^7), "a" (addr));
return retval;
}
char retval;
__asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
- : "=d" (retval) : "d" (nr), "a" (addr));
+ : "=d" (retval) : "d" (nr^7), "a" (addr));
return retval;
}
{
int i;
int block = fs->super->s_first_data_block;
- int next, inode_blocks_per_group;
+ int next;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
- inode_blocks_per_group = fs->super->s_inodes_per_group /
- EXT2_INODES_PER_BLOCK (fs->super);
-
for (i = 0; i < fs->group_desc_count; i++) {
next = block + fs->super->s_blocks_per_group;
/*
* within the group
*/
if (fs->group_desc[i].bg_inode_table < block ||
- fs->group_desc[i].bg_inode_table+inode_blocks_per_group >=
- next)
+ ((fs->group_desc[i].bg_inode_table +
+ fs->inode_blocks_per_group) >= next))
return EXT2_ET_GDESC_BAD_INODE_TABLE;
block = next;
ec EXT2_ET_BAD_DEVICE_NAME,
"Illegal or malformed device name"
+ec EXT2_ET_MISSING_INODE_TABLE,
+ "A block group is missing an inode table."
+
end
typedef struct ext2fs_struct_block_bitmap *ext2fs_block_bitmap;
+#ifdef EXT2_DYNAMIC_REV
+#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)
+#else
+#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO
+#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
+#endif
+
/*
* Flags for the ext2_filsys structure
*/
#define EXT2_FLAG_BB_DIRTY 0x20
#define EXT2_SWAP_BYTES 0x40
+/*
+ * Special flag in the ext2 inode i_flag field that means that this is
+ * a new inode. (So that ext2_write_inode() can clear extra fields.)
+ */
+#define EXT2_NEW_INODE_FL 0x80000000
+
struct struct_ext2_filsys {
int magic;
io_channel io;
int inodes_left, blocks_left, groups_left;
int inode_buffer_blocks;
char * inode_buffer;
- struct ext2_inode * inode_scan_ptr;
+ int inode_size;
+ char * ptr;
+ int bytes_left;
+ char *temp_buffer;
errcode_t (*done_group)(ext2_filsys fs,
ext2_inode_scan scan,
dgrp_t group,
char ch;
#endif /* HAVE_SYS_DISKLABEL_H */
- fd = open(file, O_RDWR);
+ fd = open(file, O_RDONLY);
if (fd < 0)
return errno;
set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
set_field(s_errors, EXT2_ERRORS_DEFAULT);
+
+#ifdef EXT2_DYNAMIC_REV
+ set_field(s_rev_level, EXT2_GOOD_OLD_REV);
+ if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
+ set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
+ set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
+ }
+#endif
+
set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
super->s_lastcheck = time(NULL);
super->s_first_data_block +
EXT2_BLOCKS_PER_GROUP(super) - 1)
/ EXT2_BLOCKS_PER_GROUP(super);
+ if (fs->group_desc_count == 0)
+ return EXT2_ET_TOOSMALL;
fs->desc_blocks = (fs->group_desc_count +
EXT2_DESC_PER_BLOCK(super) - 1)
/ EXT2_DESC_PER_BLOCK(super);
* the inode table blocks in the descriptor. If not, add some
* additional inodes/group. Waste not, want not...
*/
- fs->inode_blocks_per_group = (super->s_inodes_per_group +
- EXT2_INODES_PER_BLOCK(super) - 1) /
- EXT2_INODES_PER_BLOCK(super);
- super->s_inodes_per_group = fs->inode_blocks_per_group *
- EXT2_INODES_PER_BLOCK(super);
-
+ fs->inode_blocks_per_group = (((super->s_inodes_per_group *
+ EXT2_INODE_SIZE(super)) +
+ EXT2_BLOCK_SIZE(super) - 1) /
+ EXT2_BLOCK_SIZE(super));
+ super->s_inodes_per_group = ((fs->inode_blocks_per_group *
+ EXT2_BLOCK_SIZE(super)) /
+ EXT2_INODE_SIZE(super));
+ /*
+ * Finally, make sure the number of inodes per group is a
+ * multiple of 8. This is needed to simplify the bitmap
+ * splicing code.
+ */
+ super->s_inodes_per_group &= ~7;
+ fs->inode_blocks_per_group = (((super->s_inodes_per_group *
+ EXT2_INODE_SIZE(super)) +
+ EXT2_BLOCK_SIZE(super) - 1) /
+ EXT2_BLOCK_SIZE(super));
+
/*
* adjust inode count to reflect the adjusted inodes_per_group
*/
scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
scan->fs = fs;
+ scan->inode_size = EXT2_INODE_SIZE(fs->super);
+ scan->bytes_left = 0;
scan->current_group = -1;
scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
scan->groups_left = fs->group_desc_count;
free(scan);
return ENOMEM;
}
+ scan->temp_buffer = malloc(scan->inode_size);
+ if (!scan->temp_buffer) {
+ free(scan->inode_buffer);
+ free(scan);
+ return ENOMEM;
+ }
*ret_scan = scan;
return 0;
}
free(scan->inode_buffer);
scan->inode_buffer = NULL;
+ free(scan->temp_buffer);
+ scan->temp_buffer = NULL;
free(scan);
return;
}
{
errcode_t retval;
int num_blocks;
+ int extra_bytes = 0;
EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
+ /*
+ * Do we need to start reading a new block group?
+ */
if (scan->inodes_left <= 0) {
- if (scan->blocks_left <= 0) {
- if (scan->done_group) {
- retval = (scan->done_group)
- (scan->fs, scan,
- scan->current_group,
- scan->done_group_data);
- if (retval)
- return retval;
- }
- do {
- if (scan->groups_left <= 0) {
- *ino = 0;
- return 0;
- }
- scan->current_group++;
- scan->groups_left--;
-
- scan->current_block =
- scan->fs->group_desc[scan->current_group].bg_inode_table;
- scan->blocks_left = (EXT2_INODES_PER_GROUP(scan->fs->super) /
- EXT2_INODES_PER_BLOCK(scan->fs->super));
- } while (scan->current_block == 0);
- } else {
- scan->current_block += scan->inode_buffer_blocks;
+ if (scan->done_group) {
+ retval = (scan->done_group)
+ (scan->fs, scan,
+ scan->current_group,
+ scan->done_group_data);
+ if (retval)
+ return retval;
+ }
+ if (scan->groups_left <= 0) {
+ *ino = 0;
+ return 0;
}
+ scan->current_group++;
+ scan->groups_left--;
+
+ scan->current_block = scan->fs->
+ group_desc[scan->current_group].bg_inode_table;
+
+ if (scan->current_block == 0)
+ return EXT2_ET_MISSING_INODE_TABLE;
+ scan->bytes_left = 0;
+ scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
+ scan->blocks_left = scan->fs->inode_blocks_per_group;
+ }
+
+ /*
+ * Have we run out of space in the inode buffer? If so, we
+ * need to read in more blocks.
+ */
+ if (scan->bytes_left < scan->inode_size) {
+ memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
+ extra_bytes = scan->bytes_left;
+
scan->blocks_left -= scan->inode_buffer_blocks;
num_blocks = scan->inode_buffer_blocks;
if (scan->blocks_left < 0)
num_blocks += scan->blocks_left;
- scan->inodes_left = EXT2_INODES_PER_BLOCK(scan->fs->super) *
- num_blocks;
-
retval = io_channel_read_blk(scan->fs->io, scan->current_block,
num_blocks, scan->inode_buffer);
if (retval)
return EXT2_ET_NEXT_INODE_READ;
- scan->inode_scan_ptr = (struct ext2_inode *) scan->inode_buffer;
+ scan->ptr = scan->inode_buffer;
+ scan->bytes_left = num_blocks * scan->fs->blocksize;
+
+ scan->current_block += scan->inode_buffer_blocks;
+ }
+
+ if (extra_bytes) {
+ memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
+ scan->inode_size - extra_bytes);
+ scan->ptr += scan->inode_size - extra_bytes;
+ scan->bytes_left -= scan->inode_size - extra_bytes;
+
+ if (scan->fs->flags & EXT2_SWAP_BYTES)
+ inocpy_with_swap(inode, (struct ext2_inode *)
+ scan->temp_buffer);
+ else
+ *inode = *((struct ext2_inode *) scan->temp_buffer);
+ } else {
+ if (scan->fs->flags & EXT2_SWAP_BYTES)
+ inocpy_with_swap(inode, (struct ext2_inode *)
+ scan->ptr);
+ else
+ *inode = *((struct ext2_inode *) scan->ptr);
+ scan->ptr += scan->inode_size;
+ scan->bytes_left -= scan->inode_size;
}
- if (scan->fs->flags & EXT2_SWAP_BYTES)
- inocpy_with_swap(inode, scan->inode_scan_ptr++);
- else
- *inode = *scan->inode_scan_ptr++;
scan->inodes_left--;
scan->current_inode++;
* Functions to read and write a single inode.
*/
static char *inode_buffer = 0;
-static blk_t inode_buffer_block;
+static blk_t inode_buffer_block = 0;
static int inode_buffer_size = 0;
errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
struct ext2_inode * inode)
{
- unsigned long group;
- unsigned long block;
- unsigned long block_nr;
+ unsigned long group, block, block_nr, offset;
+ char *ptr;
errcode_t retval;
- int i;
+ int clen, length;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
}
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
- block = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) /
- EXT2_INODES_PER_BLOCK(fs->super);
- i = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) %
- EXT2_INODES_PER_BLOCK(fs->super);
+ offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+ EXT2_INODE_SIZE(fs->super);
+ block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
block_nr = fs->group_desc[group].bg_inode_table + block;
if (block_nr != inode_buffer_block) {
retval = io_channel_read_blk(fs->io, block_nr, 1,
return retval;
inode_buffer_block = block_nr;
}
+ offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+ ptr = ((char *) inode_buffer) + offset;
+
+ memset(inode, 0, sizeof(struct ext2_inode));
+ length = EXT2_INODE_SIZE(fs->super);
+ if (length > sizeof(struct ext2_inode))
+ length = sizeof(struct ext2_inode);
+
+ if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
+ clen = EXT2_BLOCK_SIZE(fs->super) - offset;
+ memcpy((char *) inode, ptr, clen);
+ length -= clen;
+
+ retval = io_channel_read_blk(fs->io, block_nr+1, 1,
+ inode_buffer);
+ if (retval)
+ return retval;
+ inode_buffer_block = block_nr+1;
+
+ memcpy(((char *) inode) + clen,
+ inode_buffer, length);
+ } else
+ memcpy((char *) inode, ptr, length);
+
if (fs->flags & EXT2_SWAP_BYTES)
- inocpy_with_swap(inode,
- (struct ext2_inode *) inode_buffer + i);
- else
- memcpy (inode, (struct ext2_inode *) inode_buffer + i,
- sizeof (struct ext2_inode));
+ inocpy_with_swap(inode, inode);
+
return 0;
}
errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
struct ext2_inode * inode)
{
- unsigned long group;
- unsigned long block;
- unsigned long block_nr;
+ unsigned long group, block, block_nr, offset;
errcode_t retval;
- int i;
+ struct ext2_inode temp_inode;
+ char *ptr;
+ int i, clen, length;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
inode_buffer_size = fs->blocksize;
inode_buffer_block = 0;
}
-
+ if (fs->flags & EXT2_SWAP_BYTES)
+ inocpy_with_swap(&temp_inode, inode);
+ else
+ memcpy(&temp_inode, inode, sizeof(struct ext2_inode));
+
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
- block = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) /
- EXT2_INODES_PER_BLOCK(fs->super);
- i = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) %
- EXT2_INODES_PER_BLOCK(fs->super);
+ offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+ EXT2_INODE_SIZE(fs->super);
+ block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
block_nr = fs->group_desc[group].bg_inode_table + block;
+ offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+ ptr = (char *) inode_buffer + offset;
+
+ length = EXT2_INODE_SIZE(fs->super);
+ if (length > sizeof(struct ext2_inode))
+ length = sizeof(struct ext2_inode);
+
if (inode_buffer_block != block_nr) {
retval = io_channel_read_blk(fs->io, block_nr, 1,
inode_buffer);
return retval;
inode_buffer_block = block_nr;
}
- if (fs->flags & EXT2_SWAP_BYTES)
- inocpy_with_swap((struct ext2_inode *) inode_buffer + i,
- inode);
- else
- memcpy ((struct ext2_inode *) inode_buffer + i, inode,
- sizeof (struct ext2_inode));
+
+ if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
+ clen = EXT2_BLOCK_SIZE(fs->super) - offset;
+ memcpy(ptr, &temp_inode, clen);
+ length -= clen;
+ } else {
+ memcpy(ptr, &temp_inode, length);
+ length = 0;
+ }
retval = io_channel_write_blk(fs->io, block_nr, 1, inode_buffer);
if (retval)
return retval;
+
+ if (length) {
+ retval = io_channel_read_blk(fs->io, ++block_nr, 1,
+ inode_buffer);
+ if (retval) {
+ inode_buffer_block = 0;
+ return retval;
+ }
+ inode_buffer_block = block_nr;
+ memcpy(inode_buffer, ((char *) &temp_inode) + clen, length);
+
+ retval = io_channel_write_blk(fs->io, block_nr, 1,
+ inode_buffer);
+ if (retval)
+ return retval;
+ }
+
fs->flags |= EXT2_FLAG_CHANGED;
return 0;
}
retval = EXT2_ET_BAD_MAGIC;
goto cleanup;
}
+#ifdef EXT2_DYNAMIC_REV
+ if (fs->super->s_rev_level > EXT2_DYNAMIC_REV) {
+ retval = EXT2_ET_REV_TOO_HIGH;
+ goto cleanup;
+ }
+#else
#ifdef EXT2_CURRENT_REV
if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
retval = EXT2_ET_REV_TOO_HIGH;
goto cleanup;
}
#endif
+#endif
fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
fs->fragsize = EXT2_FRAG_SIZE(fs->super);
- fs->inode_blocks_per_group = (fs->super->s_inodes_per_group /
- EXT2_INODES_PER_BLOCK(fs->super));
+ fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
+ EXT2_INODE_SIZE(fs->super) +
+ EXT2_BLOCK_SIZE(fs->super) - 1) /
+ EXT2_BLOCK_SIZE(fs->super));
if (block_size) {
if (block_size != fs->blocksize) {
retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
return EXT2_ET_RO_FILSYS;
if (!inode_bitmap)
return 0;
- nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
+ nbytes = (EXT2_INODES_PER_GROUP(fs->super)+7) / 8;
+
bitmap_block = malloc(fs->blocksize);
if (!bitmap_block)
return ENOMEM;
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
+Thu Mar 7 03:43:20 1996 <tytso@rsts-11.mit.edu>
+
+ * mke2fs.c (PRS): Add (for development only) support to
+ specify revision and inode size of the new filesystem.
+
+Tue Mar 5 03:51:35 1996 <tytso@rsts-11.mit.edu>
+
+ * mke2fs.8.in: Fix a few minor typo's in the man page.
+
+ * mke2fs.c (reserve_inodes): Add support for dynamic first inode
+ revision.
+
+Mon Feb 5 22:19:49 1996 <tytso@rsts-11.mit.edu>
+
+ * fsck.c (check_all, PRS): Added new flag -P, which turns on the
+ parallel root option. This allows you to check the root
+ filesystem in parallel with the other filesystems. Note
+ that this is not the safest thing in the world to do,
+ since if the root filesystem is in doubt things like
+ the e2fsck executable might be corrupted! But some
+ sysadmins, who don't want to repartition the root
+ filesystem to be small and compact, may really want this
+ option turned on.
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
--- /dev/null
+/* Well, here's my linux version of findsuper.
+ * I'm sure you coulda done it faster. :)
+ * IMHO there isn't as much interesting data to print in the
+ * linux superblock as there is in the SunOS superblock--disk geometry is
+ * not there...and linux seems to update the dates in all the superblocks.
+ * SunOS doesn't ever touch the backup superblocks after the fs is created,
+ * as far as I can tell, so the date is more interesting IMHO and certainly
+ * marks which superblocks are backup ones.
+ *
+ * This still doesn't handle disks >2G.
+ *
+ * I wanted to add msdos support, but I couldn't make heads or tails
+ * of the kernel include files to find anything I could look for in msdos.
+ *
+ * Reading every block of a Sun partition is fairly quick. Doing the
+ * same under linux (slower hardware I suppose) just isn't the same.
+ * It might be more useful to default to reading the first (second?) block
+ * on each cyl; however, if the disk geometry is wrong, this is useless.
+ * But ya could still get the cyl size to print the numbers as cyls instead
+ * of blocks...
+ *
+ * run this as (for example)
+ * findsuper /dev/hda
+ * findsuper /dev/hda 437760 1024 (my disk has cyls of 855*512)
+ *
+ * I suppose the next step is to figgure out a way to determine if
+ * the block found is the first superblock somehow, and if so, build
+ * a partition table from the superblocks found... but this is still
+ * useful as is.
+ *
+ * Steve
+ * ssd@nevets.oau.org
+ * ssd@mae.engr.ucf.edu
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <linux/ext2_fs.h>
+
+
+main(int argc, char *argv[])
+{
+ int i;
+ int skiprate=512; /* one sector */
+ long sk=0; /* limited to 2G filesystems!! */
+ FILE *f;
+ char *s;
+
+ struct ext2_super_block ext2;
+ /* interesting fields: EXT2_SUPER_MAGIC
+ s_blocks_count s_log_block_size s_mtime s_magic s_lastcheck */
+
+ if (argc<2) {
+ fprintf(stderr,"Usage: findsuper device [skiprate [start]]\n");
+ exit(1);
+ }
+ if (argc>2) skiprate=atoi(argv[2]);
+ if (skiprate<512){
+ fprintf(stderr,"Do you really want to skip less than a sector??\n");
+ exit(2);
+ }
+ if (argc>3) sk=atol(argv[3]);
+ if (sk<0) {
+ fprintf(stderr,"Have to start at 0 or greater,not %ld\n",sk);
+ exit(1);
+ }
+ f=fopen(argv[1],"r");
+ if (!f){
+ perror(argv[1]);
+ exit(1);
+ }
+
+ /* Now, go looking for the superblock ! */
+ printf(" thisoff block fs_blk_sz blksz last_mount\n");
+ for (;!feof(f) && (i=fseek(f,sk,SEEK_SET))!= -1; sk+=skiprate){
+ if (i=fread(&ext2,sizeof(ext2),1, f)!=1){
+ perror("read failed");
+ } else if (ext2.s_magic == EXT2_SUPER_MAGIC){
+ s=ctime(&ext2.s_mtime);
+ s[24]=0;
+ printf("%9ld %9ld %9ld %5ld %s\n",sk,sk/1024,ext2.s_blocks_count,ext2.s_log_block_size,s);
+ }
+ }
+ printf("Failed on %d at %ld\n",i,sk);
+ fclose(f);
+}
.SH SYNOPSIS
.B fsck
[
-.B \-AVRTN
+.B \-AVRTNP
]
[
.B \-s
.B -N
Don't execute, just show what would be done.
.TP
+.B -P
+When the
+.B -A
+flag is set, check the root filesystem in parallel with the other filesystems.
+This is not the safest thing in the world to do,
+since if the root filesystem is in doubt things like
+the e2fsck executable might be corrupted! This option is mainly provided
+for those sysadmins who don't want to repartition the root
+filesystem to be small and compact (which is really the right solution).
+.TP
.B -s
Serialize fsck operations. This is a good idea if you checking multiple
filesystems in and the checkers are in an interactive mode. (Note:
int skip_root = 0;
int like_mount = 0;
int notitle = 0;
+int parallel_root = 0;
char *progname;
char *fstype = NULL;
struct fs_info *filesys_info;
/*
* Find and check the root filesystem first.
*/
- for (fs = filesys_info; fs; fs = fs->next) {
- if (!strcmp(fs->mountpt, "/"))
- break;
- }
- if (fs && !skip_root && !ignore(fs)) {
- fsck_device(fs->device);
- fs->flags |= FLAG_DONE;
- status |= wait_all();
- if (status > EXIT_NONDESTRUCT)
- return status;
+ if (!parallel_root) {
+ for (fs = filesys_info; fs; fs = fs->next) {
+ if (!strcmp(fs->mountpt, "/"))
+ break;
+ }
+ if (fs && !skip_root && !ignore(fs)) {
+ fsck_device(fs->device);
+ fs->flags |= FLAG_DONE;
+ status |= wait_all();
+ if (status > EXIT_NONDESTRUCT)
+ return status;
+ }
}
if (fs) fs->flags |= FLAG_DONE;
case 'M':
like_mount++;
break;
+ case 'P':
+ parallel_root++;
+ break;
case 's':
serialize++;
break;
.TP
.I -v
Verbose execution.
-.IP
+.TP
.I -F
-Force mke2fs to run, even if the specified device
+Force mke2fs to run, even if the specified device is not a
+block special device.
.TP
.I -S
Write superblock and group descriptors only. This is useful if all of
and the block and inode bitmaps. The
.B e2fsck
program should be run immediately after this option is used, and there
-is no gaurantee that any data will be salvageable.
+is no guarantee that any data will be salvageable.
.SH AUTHOR
This version of
.B mke2fs
ino_t i;
int group;
- for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INO; i++) {
+ for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) {
ext2fs_mark_inode_bitmap(fs->inode_map, i);
group = ext2fs_group_of_ino(fs, i);
fs->group_desc[group].bg_free_inodes_count--;
EXT2FS_VERSION, EXT2FS_DATE);
if (argc && *argv)
program_name = *argv;
- while ((c = getopt (argc, argv, "b:cf:g:i:l:m:qtvSF")) != EOF)
+ while ((c = getopt (argc, argv, "b:cf:g:i:l:m:qr:tvI:SF")) != EOF)
switch (c) {
case 'b':
size = strtoul(optarg, &tmp, 0);
exit(1);
}
break;
+ case 'r':
+ param.s_rev_level = atoi(optarg);
+ break;
+#ifdef EXT2_DYNAMIC_REV
+ case 'I':
+ param.s_inode_size = atoi(optarg);
+ break;
+#endif
case 'v':
verbose = 1;
break;
+Wed Mar 27 00:33:40 1996 <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.03
+
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.02
Clear? yes
Pass 3: Checking directory connectivity
-Root inode not allocated. Rellocate? yes
+Root inode not allocated. Reallocate? yes
Unconnected directory inode 11 (...)
Connect to /lost+found? yes
Clear? yes
Pass 3: Checking directory connectivity
-Root inode not allocated. Rellocate? yes
+Root inode not allocated. Reallocate? yes
Unconnected directory inode 11 (...)
Connect to /lost+found? yes
Clear? yes
Pass 3: Checking directory connectivity
-Root inode not allocated. Rellocate? yes
+Root inode not allocated. Reallocate? yes
Unconnected directory inode 11 (...)
Connect to /lost+found? yes