mirror of https://github.com/vitalif/e2fsprogs
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
parent
5972d0d644
commit
24b2c7a7a1
|
@ -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
|
||||
|
|
27
Makefile.in
27
Makefile.in
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
#
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
Loading…
Reference in New Issue