ChangeLog, Makefile.in, configure.in:

configure.in (rmakefile): Added (optional) private directory for resize2fs.
  Makefile.in: Change recursive descent rules to check to see if a
  	directory exists before trying to make it.
Many files:
  Initial checkin of work done to date.
bitmap-optimize
Theodore Ts'o 1997-06-07 20:42:58 +00:00
parent 5972d0d644
commit 24b2c7a7a1
10 changed files with 704 additions and 11 deletions

View File

@ -1,3 +1,11 @@
Sat Jun 7 16:38:40 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* configure.in (rmakefile): Added (optional) private directory for
resize2fs.
* Makefile.in: Change recursive descent rules to check to see if a
directory exists before trying to make it.
Thu May 8 22:23:49 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Makefile.in (source_tar_file): Fix up makefile to work in new

View File

@ -8,7 +8,7 @@ INSTALL = @INSTALL@
@MCONFIG@
LIB_SUBDIRS=lib/et lib/ss lib/ext2fs lib/e2p lib/uuid
PROG_SUBDIRS=e2fsck debugfs misc tests/progs
PROG_SUBDIRS=e2fsck debugfs misc resize tests/progs
SUBDIRS=$(LIB_SUBDIRS) $(PROG_SUBDIRS) tests
SUBS= include/linux/types.h
@ -35,23 +35,29 @@ install-libs: install-libs-recursive
TAGS clean-recursive distclean-recursive \
mostlyclean-recursive realclean-recursive install-recursive:
for subdir in $(SUBDIRS); do \
target=`echo $@|$(SED) 's/-recursive//'`; \
echo making $$target in $$subdir; \
(cd $$subdir && $(MAKE) $$target) || exit 1; \
if test -d $$subdir ; then \
target=`echo $@|$(SED) 's/-recursive//'`; \
echo making $$target in $$subdir; \
(cd $$subdir && $(MAKE) $$target) || exit 1; \
fi ; \
done
all-progs-recursive install-progs-recursive:
for subdir in $(PROG_SUBDIRS); do \
target=`echo $@|$(SED) 's/-progs-recursive//'`; \
echo making $$target in $$subdir; \
(cd $$subdir && $(MAKE) $$target) || exit 1; \
if test -d $$subdir ; then \
target=`echo $@|$(SED) 's/-progs-recursive//'`; \
echo making $$target in $$subdir; \
(cd $$subdir && $(MAKE) $$target) || exit 1; \
fi ; \
done
all-libs-recursive install-libs-recursive install-shlibs-libs-recursive:
for subdir in $(LIB_SUBDIRS); do \
target=`echo $@|$(SED) 's/-libs-recursive//'`; \
echo making $$target in $$subdir; \
(cd $$subdir && $(MAKE) $$target) || exit 1; \
if test -d $$subdir ; then \
target=`echo $@|$(SED) 's/-libs-recursive//'`; \
echo making $$target in $$subdir; \
(cd $$subdir && $(MAKE) $$target) || exit 1; \
fi ; \
done
mostlyclean: mostlyclean-recursive mostlyclean-local
@ -98,6 +104,7 @@ $(srcdir)/.exclude-file:
> $(srcdir)/.exclude-file)
echo "$(SRCROOT)/build" >> $(srcdir)/.exclude-file
echo "$(SRCROOT)/rpm.log" >> $(srcdir)/.exclude-file
echo "$(SRCROOT)/resize" >> $(srcdir)/.exclude-file
echo "$(SRCROOT)/.exclude-file" >> $(srcdir)/.exclude-file
echo $(SRCROOT)/e2fsprogs-@E2FSPROGS_VERSION@.tar.gz \
>> $(srcdir)/.exclude-file

View File

@ -504,7 +504,11 @@ dnl
test -d lib || mkdir lib
test -d include || mkdir include
test -d include/linux || mkdir include/linux
rmakefile=
if test -d ${srcdir}/resize ; then
rmakefile=resize/Makefile
fi
AC_OUTPUT(MCONFIG lib/substitute_sh Makefile lib/et/Makefile
lib/ss/Makefile lib/ext2fs/Makefile lib/e2p/Makefile lib/uuid/Makefile
misc/Makefile e2fsck/Makefile debugfs/Makefile tests/Makefile
tests/progs/Makefile doc/Makefile)
tests/progs/Makefile $rmakefile doc/Makefile)

70
resize/Makefile.in Normal file
View File

@ -0,0 +1,70 @@
#
# Standard e2fsprogs prologue....
#
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
top_builddir = ..
my_dir = resize
INSTALL = @INSTALL@
@MCONFIG@
PROGS= resize2fs
MANPAGES= resize2fs.8
RESIZE_OBJS= banalysis.o resize2fs.o main.o
SRCS= $(srcdir)/banalysis.c \
$(srcdir)/resize2fs.c \
$(srcdir)/main.c
LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBUUID)
DEPLIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBUUID)
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $@
all:: $(PROGS) $(MANPAGES)
resize2fs: $(RESIZE_OBJS) $(DEPLIBS)
$(CC) $(ALL_LDFLAGS) -o resize2fs $(RESIZE_OBJS) $(LIBS)
resize2fs.8: $(SUBSTITUTE) $(srcdir)/resize2fs.8.in
-$(CHMOD) +x $(SUBSTITUTE)
$(SUBSTITUTE) $(srcdir)/resize2fs.8.in resize2fs.8
installdirs:
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(usbindir) \
$(DESTDIR)$(man8dir) $(DESTDIR)$(cat8dir)
install: $(PROGS) $(MANPAGES) installdirs
for i in $(PROGS); do \
$(INSTALL_PROGRAM) $$i $(DESTDIR)$(usbindir)/$$i; \
$(STRIP) $(DESTDIR)$(usbindir)/$$i; \
done
for i in $(MANPAGES); do \
$(INSTALL_DATA) $$i $(DESTDIR)$(man8dir)/$$i; \
done
uninstall:
for i in $(PROGS); do \
$(RM) -f $(usbindir)/$$i; \
done
for i in $(MANPAGES); do \
$(RM) -f $(man8dir)/$$i; \
done
clean:
$(RM) -f $(PROGS) $(MANPAGES) \#* *.s *.o *.a *~ core
mostlyclean: clean
distclean: clean
$(RM) -f .depend Makefile
# +++ Dependency line eater +++
#
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#

141
resize/banalysis.c Normal file
View File

@ -0,0 +1,141 @@
/*
* banalysis.c --- Analyze a filesystem for a block struct
*
* Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fs/ext2fs.h"
#include "ext2fs/brel.h"
#include "banalysis.h"
struct process_block_struct {
struct ext2_block_analyzer_funcs *funcs;
struct ext2_inode_context *ctx;
void *private;
};
/*
* This function returns 1 if the inode's block entries actually
* contain block entries.
*/
static int inode_has_valid_blocks(struct ext2_inode *inode)
{
/*
* Only directories, regular files, and some symbolic links
* have valid block entries.
*/
if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
!LINUX_S_ISLNK(inode->i_mode))
return 0;
/*
* If the symbolic link is a "fast symlink", then the symlink
* target is stored in the block entries.
*/
if (LINUX_S_ISLNK (inode->i_mode) && inode->i_blocks == 0 &&
inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long))
return 0;
return 1;
}
static int process_block(ext2_filsys fs, blk_t *block_nr,
int blockcnt, blk_t ref_block,
int ref_offset, void *private)
{
struct process_block_struct *pb = private;
blk_t new_block;
struct ext2_block_relocate_entry ent;
if (ref_block == 0)
ref_offset = blockcnt;
new_block = pb->funcs->block_analyze(fs, *block_nr, ref_block,
ref_offset, pb->ctx, pb->private);
if (new_block) {
ent.new = new_block;
ent.offset = ref_offset;
if (ref_block) {
ent.owner.block_ref = ref_block;
ent.flags = 0;
} else {
ent.owner.inode_ref = pb->ctx->ino;
ent.flags = RELOCATE_INODE_REF;
}
ext2fs_brel_put(pb->ctx->brel, *block_nr, &ent);
}
return 0;
}
errcode_t ext2_block_analyze(ext2_filsys fs,
struct ext2_block_analyzer_funcs *funcs,
ext2_brel block_relocation_table,
void *private)
{
ino_t ino;
struct ext2_inode inode;
errcode_t retval;
struct process_block_struct pb;
struct ext2_inode_context ctx;
ext2_inode_scan scan;
char *block_buf;
retval = ext2fs_open_inode_scan(fs, 0, &scan);
if (retval)
return retval;
pb.funcs = funcs;
pb.private = private;
pb.ctx = &ctx;
block_buf = malloc(fs->blocksize * 3);
if (!block_buf)
return ENOMEM;
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval)
return retval;
ctx.ctx = private;
ctx.brel = block_relocation_table;
while (ino) {
if ((inode.i_links_count == 0) ||
!inode_has_valid_blocks(&inode))
goto next;
ctx.ino = ino;
ctx.inode = &inode;
ctx.error = 0;
if (funcs->pre_analyze &&
!(*funcs->pre_analyze)(fs, &ctx, private))
goto next;
retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
process_block, &pb);
if (retval)
return retval;
if (funcs->post_analyze)
(funcs->post_analyze)(fs, &ctx, private);
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
goto next;
}
return 0;
}

30
resize/banalysis.h Normal file
View File

@ -0,0 +1,30 @@
/*
* banalysis.h --- Block analysis header file
*/
struct ext2_inode_context {
ino_t ino;
struct ext2_inode * inode;
errcode_t error;
ext2_brel brel;
void * ctx;
};
struct ext2_block_analyzer_funcs {
int (*pre_analyze)(ext2_filsys fs,
struct ext2_inode_context *icontext,
void *private);
blk_t (*block_analyze)(ext2_filsys fs, blk_t blk,
blk_t ref_block, int ref_offset,
struct ext2_inode_context *icontext,
void *private);
void (*post_analyze)(ext2_filsys fs,
struct ext2_inode_context *icontext,
void *private);
};
errcode_t ext2_block_analyze(ext2_filsys fs,
struct ext2_block_analyzer_funcs *funcs,
ext2_brel block_relocation_table,
void *private);

76
resize/main.c Normal file
View File

@ -0,0 +1,76 @@
/*
* main.c --- ext2 resizer main program
*
* Copyright (C) 1997 Theodore Ts'o
*
* %Begin-Header%
* All rights reserved.
* %End-Header%
*/
#include "resize2fs.h"
#define E2FSPROGS_VERSION "1.10"
#define E2FSPROGS_DATE "27-Apr-97"
char *program_name, *device_name;
static volatile void usage (char *program_name)
{
fprintf (stderr, "usage: %s device new-size\n", program_name);
exit (1);
}
void main (int argc, char ** argv)
{
errcode_t retval;
ext2_filsys fs;
int c;
blk_t new_size;
io_manager io_ptr;
fprintf (stderr, "resize2fs %s, %s for EXT2 FS %s, %s\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE,
EXT2FS_VERSION, EXT2FS_DATE);
if (argc && *argv)
program_name = *argv;
while ((c = getopt (argc, argv, "h")) != EOF) {
switch (c) {
case 'h':
usage(program_name);
break;
default:
usage (program_name);
}
}
if (optind > argc - 2)
usage (program_name);
device_name = argv[optind++];
new_size = atoi(argv[optind++]);
initialize_ext2_error_table();
#if 1
io_ptr = unix_io_manager;
#else
io_ptr = test_io_manager;
test_io_backing_manager = unix_io_manager;
#endif
retval = ext2fs_open (device_name, 0, 0, 0,
io_ptr, &fs);
if (retval) {
com_err (program_name, retval, "while trying to open %s",
device_name);
printf ("Couldn't find valid filesystem superblock.\n");
exit (1);
}
retval = ext2fs_read_bitmaps(fs);
if (retval) {
com_err (program_name, retval,
"while trying to read the bitmaps", device_name);
ext2fs_close (fs);
exit (1);
}
resize_fs(fs, new_size);
ext2fs_close (fs);
exit (0);
}

32
resize/resize2fs.8.in Normal file
View File

@ -0,0 +1,32 @@
.\" -*- nroff -*-
.\" Copyright 1997 by Theodore Ts'o. All Rights Reserved.
.\"
.TH RESIZE2FS 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
.SH NAME
resize2fs \- ext2 file system resizer
.SH SYNOPSIS
.B resize2fs
[
device
]
.SH DESCRIPTION
The
.B resize2fs
program will resize ext2 file systems. It can be used to enlarge or
shrink an ext2 file system.
.br
.I device
is the special file corresponding to the device containing the ext2
file system (e.g /dev/hdXX).
.SH OPTIONS
.TP
.I -h
Displays a help message.
.SH AUTHOR
.B debugfs
was written by Theodore Ts'o <tytso@mit.edu>.
.SH SEE ALSO
.BR dumpe2fs (8),
.BR tune2fs (8),
.BR e2fsck (8),
.BR mke2fs (8)

277
resize/resize2fs.c Normal file
View File

@ -0,0 +1,277 @@
/*
* resize2fs.c --- ext2 main routine
*
* Copyright (C) 1997 Theodore Ts'o
*
* %Begin-Header%
* All rights reserved.
* %End-Header%
*/
#include "resize2fs.h"
/*
* This routine adjusts the superblock and other data structures...
*/
static errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size)
{
ext2_filsys fs;
int overhead = 0;
int rem;
errcode_t retval;
ino_t real_end;
blk_t blk, group_block;
unsigned long i;
struct ext2_group_desc *new;
fs = rfs->new_fs;
fs->super->s_blocks_count = new_size;
retry:
fs->group_desc_count = (fs->super->s_blocks_count -
fs->super->s_first_data_block +
EXT2_BLOCKS_PER_GROUP(fs->super) - 1)
/ EXT2_BLOCKS_PER_GROUP(fs->super);
if (fs->group_desc_count == 0)
return EXT2_ET_TOOSMALL;
fs->desc_blocks = (fs->group_desc_count +
EXT2_DESC_PER_BLOCK(fs->super) - 1)
/ EXT2_DESC_PER_BLOCK(fs->super);
/*
* Overhead is the number of bookkeeping blocks per group. It
* includes the superblock backup, the group descriptor
* backups, the inode bitmap, the block bitmap, and the inode
* table.
*
* XXX Not all block groups need the descriptor blocks, but
* being clever is tricky...
*/
overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group;
/*
* See if the last group is big enough to support the
* necessary data structures. If not, we need to get rid of
* it.
*/
rem = (fs->super->s_blocks_count - fs->super->s_first_data_block) %
fs->super->s_blocks_per_group;
if ((fs->group_desc_count == 1) && rem && (rem < overhead))
return EXT2_ET_TOOSMALL;
if (rem && (rem < overhead+50)) {
fs->super->s_blocks_count -= rem;
goto retry;
}
/*
* Adjust the number of inodes
*/
fs->super->s_inodes_count = fs->super->s_inodes_per_group *
fs->group_desc_count;
/*
* Adjust the number of free blocks
*/
blk = rfs->old_fs->super->s_blocks_count;
if (blk > fs->super->s_blocks_count)
fs->super->s_free_blocks_count -=
(blk - fs->super->s_blocks_count);
else
fs->super->s_free_blocks_count +=
(fs->super->s_blocks_count - blk);
/*
* Adjust the bitmaps for size
*/
retval = ext2fs_resize_inode_bitmap(fs->super->s_inodes_count,
fs->super->s_inodes_count,
fs->inode_map);
if (retval)
return retval;
real_end = ((EXT2_BLOCKS_PER_GROUP(fs->super)
* fs->group_desc_count)) - 1 +
fs->super->s_first_data_block;
retval = ext2fs_resize_block_bitmap(fs->super->s_blocks_count-1,
real_end, fs->block_map);
if (retval)
return retval;
/*
* Reallocate the group descriptors as necessary.
*/
if (rfs->old_fs->desc_blocks != fs->desc_blocks) {
new = realloc(fs->group_desc,
fs->desc_blocks * fs->blocksize);
if (!new)
return ENOMEM;
fs->group_desc = new;
}
group_block = rfs->old_fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
if (i < rfs->old_fs->group_desc_count) {
group_block += fs->super->s_blocks_per_group;
continue;
}
/* XXXX */
}
return 0;
}
/*
* This routine reserves a block in the new filesystem. If the block
* is already used, we mark it as needing relocation. Otherwise, we
* just mark it as used.
*/
static reserve_block(ext2_resize_t rfs, blk_t blk)
{
if (ext2fs_test_block_bitmap(rfs->new_fs->block_map, blk))
ext2fs_mark_block_bitmap(rfs->move_blocks, blk);
else
ext2fs_mark_block_bitmap(rfs->new_fs->block_map, blk);
}
/*
* This routine is a helper function for determine_relocations(). It
* is called for each block group which has a superblock, and for
* which we need to expand the size of the descriptor table. We have
* to account for the fact that in some cases we will need to move the
* inode table, which will mean moving or reserving blocks at the end
* of the inode table, since the inode table will be moved down to
* make space.
*
* "And the block group descriptors waddled across the street..."
*/
static void make_way_for_descriptors(ext2_resize_t rfs,
int block_group,
blk_t group_blk)
{
blk_t blk, start_blk, end_blk, itable, move_by;
unsigned long i;
ext2_filsys fs;
start_blk = group_blk + rfs->old_fs->desc_blocks + 1;
end_blk = group_blk + rfs->new_fs->desc_blocks + 1;
fs = rfs->new_fs;
itable = fs->group_desc[block_group].bg_inode_table;
if (end_blk > itable) {
move_by = itable - end_blk;
for (blk = itable, i=0; i < move_by; blk++, i++) {
ext2fs_unmark_block_bitmap(fs->block_map, blk);
reserve_block(rfs, blk+fs->inode_blocks_per_group);
}
end_blk -= move_by;
fs->group_desc[i].bg_inode_table += move_by;
}
for (blk = start_blk; blk < end_blk; blk++)
reserve_block(rfs, blk);
}
/*
* This routine marks and unmarks reserved blocks in the new block
* bitmap. It also determines which blocks need to be moved and
* places this information into the move_blocks bitmap.
*/
static errcode_t determine_relocations(ext2_resize_t rfs)
{
int i;
blk_t blk, group_blk;
unsigned long old_blocks, new_blocks;
errcode_t retval;
retval = ext2fs_allocate_block_bitmap(rfs->old_fs,
"blocks to be moved",
&rfs->move_blocks);
if (retval)
return retval;
old_blocks = rfs->old_fs->desc_blocks;
new_blocks = rfs->new_fs->desc_blocks;
group_blk = rfs->old_fs->super->s_first_data_block;
/*
* If we're reducing the number of descriptor blocks, this
* makes life easy. :-) We just have to mark some extra
* blocks as free.
*/
if (old_blocks > new_blocks) {
for (i = 0; i < rfs->new_fs->group_desc_count; i++) {
if (!ext2fs_bg_has_super(rfs->new_fs, i)) {
group_blk += rfs->new_fs->super->s_blocks_per_group;
continue;
}
for (blk = group_blk+1+old_blocks;
blk < group_blk+1+new_blocks; blk++)
ext2fs_unmark_block_bitmap(rfs->new_fs->block_map,
blk);
group_blk += rfs->new_fs->super->s_blocks_per_group;
}
}
/*
* If we're increasing the number of descriptor blocks, life
* gets interesting. In some cases, we will need to move the
* inode table.
*/
if (old_blocks < new_blocks) {
for (i = 0; i < rfs->new_fs->group_desc_count; i++) {
if (!ext2fs_bg_has_super(rfs->new_fs, i)) {
group_blk += rfs->new_fs->super->s_blocks_per_group;
continue;
}
make_way_for_descriptors(rfs, i, group_blk);
group_blk += rfs->new_fs->super->s_blocks_per_group;
}
}
/*
* Finally, if we're shrinking the filesystem, we need to
* move all of the blocks that don't fit any more
*/
for (blk = rfs->new_fs->super->s_blocks_count;
blk < rfs->old_fs->super->s_blocks_count; blk++) {
if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk))
ext2fs_mark_block_bitmap(rfs->move_blocks, blk);
}
}
/*
* This is the top-level routine which does the dirty deed....
*/
errcode_t resize_fs(ext2_filsys fs, blk_t new_size)
{
ext2_resize_t rfs;
errcode_t retval;
/*
* First, create the data structure
*/
rfs = malloc(sizeof(struct ext2_resize_struct));
if (!rfs)
return ENOMEM;
memset(rfs, 0, sizeof(struct ext2_resize_struct));
rfs->old_fs = fs;
retval = ext2fs_dup_handle(fs, &rfs->new_fs);
if (retval) {
free(rfs);
return retval;
}
retval = adjust_superblock(rfs, new_size);
if (retval)
goto errout;
return 0;
errout:
ext2fs_free(rfs->new_fs);
free(rfs);
return retval;
}

48
resize/resize2fs.h Normal file
View File

@ -0,0 +1,48 @@
/*
* resize2fs.h --- ext2 resizer header file
*
* Copyright (C) 1997 Theodore Ts'o
*
* %Begin-Header%
* All rights reserved.
* %End-Header%
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fs/ext2fs.h"
#include "ext2fs/brel.h"
#include "banalysis.h"
#ifdef __STDC__
#define NOARGS void
#else
#define NOARGS
#define const
#endif
/*
* The core state structure for the ext2 resizer
*/
struct ext2_resize_struct {
ext2_filsys old_fs;
ext2_filsys new_fs;
ext2_brel block_relocate;
ext2fs_block_bitmap move_blocks;
};
typedef struct ext2_resize_struct *ext2_resize_t;
/* prototypes */
extern errcode_t resize_fs(ext2_filsys fs, blk_t new_size);