Add support for extents to libext2fs

Initial implemenation of extents support in libext2fs

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
bitmap-optimize
Theodore Ts'o 2007-10-14 23:04:58 -04:00
parent e3df15abdb
commit 3eb07f6493
6 changed files with 1448 additions and 4 deletions

View File

@ -10,6 +10,8 @@ INSTALL = @INSTALL@
@DEBUGFS_CMT@DEBUGFS_LIB_OBJS = bb_compat.o fileio.o \
@DEBUGFS_CMT@ inode_io.o namei.o write_bb_file.o
MK_CMDS= _SS_DIR_OVERRIDE=../ss ../ss/mk_cmds
@RESIZER_CMT@RESIZE_LIB_OBJS = dupfs.o test_io.o
@IMAGER_CMT@E2IMAGE_LIB_OBJS = imager.o
@ -35,6 +37,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
dir_iterate.o \
expanddir.o \
ext_attr.o \
extent.o \
finddev.o \
flushb.o \
freefs.o \
@ -90,6 +93,7 @@ SRCS= ext2_err.c \
$(srcdir)/dupfs.c \
$(srcdir)/expanddir.c \
$(srcdir)/ext_attr.c \
$(srcdir)/extent.c \
$(srcdir)/fileio.c \
$(srcdir)/finddev.c \
$(srcdir)/flushb.c \
@ -239,6 +243,68 @@ ext2_tdbtool: tdbtool.o
@echo " LD $@"
@$(CC) -o ext2_tdbtool tdbtool.o tdb.o
extent_dbg.c: $(srcdir)/extent_dbg.ct
@echo " MK_CMDS $<"
@$(MK_CMDS) $(srcdir)/extent_dbg.ct
debug_cmds.c debug_cmds.h: $(top_srcdir)/debugfs/debug_cmds.ct
@echo " MK_CMDS $<@"
@$(MK_CMDS) $(top_srcdir)/debugfs/debug_cmds.ct
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o dump.o set_fields.o logdump.o htree.o unused.o
debugfs.o: $(top_srcdir)/debugfs/debugfs.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
util.o: $(top_srcdir)/debugfs/util.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
ncheck.o: $(top_srcdir)/debugfs/ncheck.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
icheck.o: $(top_srcdir)/debugfs/icheck.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
ls.o: $(top_srcdir)/debugfs/ls.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
lsdel.o: $(top_srcdir)/debugfs/lsdel.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
dump.o: $(top_srcdir)/debugfs/dump.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
set_fields.o: $(top_srcdir)/debugfs/set_fields.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
logdump.o: $(top_srcdir)/debugfs/logdump.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
htree.o: $(top_srcdir)/debugfs/htree.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
unused.o: $(top_srcdir)/debugfs/unused.c
@echo " CC $<"
@$(CC) $(ALL_CFLAGS) -c $< -o $@
tst_extents: $(srcdir)/extent.c extent_dbg.c $(DEBUG_OBJS) $(LIBSS) $(LIBE2P) $(DEPLIBUUID) $(DEPLIBBLKID)
@echo " LD $@"
@$(CC) -o tst_extents $(srcdir)/extent.c extent_dbg.c \
$(ALL_CFLAGS) -DDEBUG $(DEBUG_OBJS) $(LIBSS) $(LIBE2P) \
$(LIBUUID) $(STATIC_LIBEXT2FS) $(LIBBLKID) $(LIBCOM_ERR) \
-I $(top_srcdir)/debugfs
mkjournal: mkjournal.c $(STATIC_LIBEXT2FS)
@echo " LD $@"
@$(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS)
@ -282,7 +348,7 @@ clean::
tst_badblocks tst_iscan ext2_err.et ext2_err.c ext2_err.h \
tst_byteswap tst_ismounted tst_getsize tst_sectgetsize \
tst_bitops tst_types tst_icount tst_super_size \
ext2_tdbtool mkjournal \
ext2_tdbtool mkjournal debug_cmds.c \
../libext2fs.a ../libext2fs_p.a ../libext2fs_chk.a
mostlyclean:: clean

View File

@ -62,8 +62,8 @@ ec EXT2_ET_MAGIC_E2IMAGE,
ec EXT2_ET_MAGIC_INODE_IO_CHANNEL,
"Wrong magic number for inode io_channel structure"
ec EXT2_ET_MAGIC_RESERVED_9,
"Wrong magic number --- RESERVED_9"
ec EXT2_ET_MAGIC_EXTENT_HANDLE,
"Wrong magic number for ext4 extent handle"
ec EXT2_ET_BAD_MAGIC,
"Bad magic number in super-block"
@ -329,5 +329,76 @@ ec EXT2_ET_TDB_ERR_RDONLY,
ec EXT2_ET_RO_BLOCK_ITERATE,
"Attempt to modify a block mapping via a read-only block iterator"
end
ec EXT2_ET_MAGIC_EXTENT_PATH,
"Wrong magic number for ext4 extent saved path"
ec EXT2_ET_MAGIC_RESERVED_10,
"Wrong magic number --- RESERVED_10"
ec EXT2_ET_MAGIC_RESERVED_11,
"Wrong magic number --- RESERVED_11"
ec EXT2_ET_MAGIC_RESERVED_12,
"Wrong magic number --- RESERVED_12"
ec EXT2_ET_MAGIC_RESERVED_13,
"Wrong magic number --- RESERVED_13"
ec EXT2_ET_MAGIC_RESERVED_14,
"Wrong magic number --- RESERVED_14"
ec EXT2_ET_MAGIC_RESERVED_15,
"Wrong magic number --- RESERVED_15"
ec EXT2_ET_MAGIC_RESERVED_16,
"Wrong magic number --- RESERVED_16"
ec EXT2_ET_MAGIC_RESERVED_17,
"Wrong magic number --- RESERVED_17"
ec EXT2_ET_MAGIC_RESERVED_18,
"Wrong magic number --- RESERVED_18"
ec EXT2_ET_MAGIC_RESERVED_19,
"Wrong magic number --- RESERVED_19"
ec EXT2_ET_EXTENT_HEADER_BAD,
"Corrupt extent header"
ec EXT2_ET_EXTENT_INDEX_BAD,
"Corrupt extent index"
ec EXT2_ET_EXTENT_LEAF_BAD,
"Corrupt extent"
ec EXT2_ET_EXTENT_NO_SPACE,
"No free space in extent map"
ec EXT2_ET_INODE_NOT_EXTENT,
"Inode does not use extents"
ec EXT2_ET_EXTENT_NO_NEXT,
"No 'next' extent"
ec EXT2_ET_EXTENT_NO_PREV,
"No 'previous' extent"
ec EXT2_ET_EXTENT_NO_UP,
"No 'up' extent"
ec EXT2_ET_EXTENT_NO_DOWN,
"No 'down' extent"
ec EXT2_ET_NO_CURRENT_NODE,
"No current node"
ec EXT2_ET_OP_NOT_SUPPORTED,
"Ext2fs operation not supported"
ec EXT2_ET_CANT_INSERT_EXTENT,
"No room to insert extent in node"
ec EXT2_ET_EXTENT_NOT_FOUND,
"Extent not found"
end

View File

@ -289,6 +289,65 @@ struct struct_ext2_filsys {
#define EXT2_BMOVE_DEBUG 0x0002
#endif
/*
* Generic (non-filesystem layout specific) extents structure
*/
#define EXT2_EXTENT_FLAGS_LEAF 0x0001
#define EXT2_EXTENT_FLAGS_UNINIT 0x0002
#define EXT2_EXTENT_FLAGS_SECOND_VISIT 0x0004
struct ext2fs_extent {
blk64_t e_pblk; /* first physical block */
blk64_t e_lblk; /* first logical block extent covers */
__u32 e_len; /* number of blocks covered by extent */
__u32 e_flags; /* extent flags */
};
typedef struct ext2_extent_handle *ext2_extent_handle_t;
typedef struct ext2_extent_path *ext2_extent_path_t;
/*
* Flags used by ext2fs_extent_get()
*/
#define EXT2_EXTENT_CURRENT 0x0000
#define EXT2_EXTENT_MOVE_MASK 0x000F
#define EXT2_EXTENT_ROOT 0x0001
#define EXT2_EXTENT_LAST_LEAF 0x0002
#define EXT2_EXTENT_FIRST_SIB 0x0003
#define EXT2_EXTENT_LAST_SIB 0x0004
#define EXT2_EXTENT_NEXT_SIB 0x0005
#define EXT2_EXTENT_PREV_SIB 0x0006
#define EXT2_EXTENT_NEXT_LEAF 0x0007
#define EXT2_EXTENT_PREV_LEAF 0x0008
#define EXT2_EXTENT_NEXT 0x0009
#define EXT2_EXTENT_PREV 0x000A
#define EXT2_EXTENT_UP 0x000B
#define EXT2_EXTENT_DOWN 0x000C
#define EXT2_EXTENT_DOWN_AND_LAST 0x000D
/*
* Flags used by ext2fs_extent_insert()
*/
#define EXT2_EXTENT_INSERT_AFTER 0x0001
/*
* Data structure returned by ext2fs_extent_get_info()
*/
struct ext2_extent_info {
int curr_entry;
int curr_level;
int num_entries;
int max_entries;
int max_depth;
int bytes_avail;
blk64_t max_lblk;
blk64_t max_pblk;
__u32 max_len;
__u32 max_uninit_len;
};
/*
* Flags for directory block reading and writing functions
*/
@ -722,6 +781,22 @@ extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
char *block_buf,
int adjust, __u32 *newcount);
/* extent.c */
extern errcode_t ext2fs_extent_header_verify(void *ptr, int size);
extern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino,
ext2_extent_handle_t *handle);
extern errcode_t ext2fs_extent_get(ext2_extent_handle_t handle,
int flags, struct ext2fs_extent *extent);
extern errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, int flags,
struct ext2fs_extent *extent);
extern errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags,
struct ext2fs_extent *extent);
extern errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags);
extern errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle,
struct ext2_extent_info *info);
extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
blk64_t blk);
/* fileio.c */
extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,

View File

@ -126,6 +126,26 @@ struct ext3_ext_path {
#define EXT_MAX_BLOCK 0xffffffff
#define EXT_CACHE_MARK 0xffff
/*
* EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
* initialized extent. This is 2^15 and not (2^16 - 1), since we use the
* MSB of ee_len field in the extent datastructure to signify if this
* particular extent is an initialized extent or an uninitialized (i.e.
* preallocated).
* EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
* uninitialized extent.
* If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
* uninitialized one. In other words, if MSB of ee_len is set, it is an
* uninitialized extent with only one special scenario when ee_len = 0x8000.
* In this case we can not have an uninitialized extent of zero length and
* thus we make it as a special case of initialized extent with 0x8000 length.
* This way we get better extent-to-group alignment for initialized extents.
* Hence, the maximum number of blocks we can have in an *initialized*
* extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
*/
#define EXT_INIT_MAX_LEN (1UL << 15)
#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
#define EXT_FIRST_EXTENT(__hdr__) \
((struct ext3_extent *) (((char *) (__hdr__)) + \

1144
lib/ext2fs/extent.c Normal file

File diff suppressed because it is too large Load Diff

68
lib/ext2fs/extent_dbg.ct Normal file
View File

@ -0,0 +1,68 @@
#
# Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
# under the terms of the GNU Public License.
#
command_table extent_cmds;
request do_inode, "Open an inode",
inode;
request do_current_node, "Current extent node",
current_node, current;
request do_root_node, "Goto root extent",
root_node, root;
request do_last_leaf, "Goto last leaf",
last_leaf;
request do_first_sib, "Goto first sibling",
first_sibling, first_sib;
request do_last_sib, "Goto last sibling",
last_sibling, last_sib;
request do_next_sib, "Goto next sibling",
next_sibling, next_sib, ns;
request do_prev_sib, "Goto previous sibling",
prev_sibling, prev_sib, ps;
request do_next_leaf, "Goto next leaf",
next_leaf, nl;
request do_prev_leaf, "Goto previous leaf",
prev_leaf, pl;
request do_next, "Goto next node",
next, n;
request do_prev, "Goto previous node",
previous, prev, p;
request do_up, "Up node",
up_node, up, u;
request do_down, "Down node",
down_node, down, d;
request do_delete_node, "Delete node",
delete_node, delete;
request do_insert_node, "Insert node",
insert_node, insert;
request do_replace_node, "Insert node",
replace_node, replace;
request do_print_all, "Iterate over all nodes and print them",
print_all, all;
request do_goto_block, "Goto extent containing specified block",
goto_block, goto;
request do_info, "Print extent info",
info;
end;