From: Theodore Ts'o Date: Wed, 20 Feb 2002 06:06:25 +0000 (-0500) Subject: Add new inode I/O abstraction interface which exports an inode as X-Git-Tag: E2FSPROGS-1.27-WIP-0305~15 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43be;p=tools%2Fe2fsprogs.git Add new inode I/O abstraction interface which exports an inode as an I/O object. Export ext2_file_flush as a public interface. Also minor cleanups to tighten code in other I/O abstractions, and to mark a void * pointer as const in the ext2_file_write interface. --- diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index f229390..e32db2d 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,14 @@ +2002-02-20 Theodore Tso + + * Makefile.in, inode_io.c, ext2fs.h, ext2_err.et.in: Add new io + abstraction interface which exports an ext2 inode. + + * fileio.c (ext2fs_file_flush): Export ext2fs_file_flush as a + public interface. + + * test_io.c (test_close), unix_io.c (unix_close): Remove unneeded + conditional; save a few bytes. + 2002-02-12 Theodore Tso * Makefile.in (tst_badblocks): Add some extra .o files when diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in index 2c2c94c..54dc160 100644 --- a/lib/ext2fs/Makefile.in +++ b/lib/ext2fs/Makefile.in @@ -43,6 +43,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \ initialize.o \ inline.o \ inode.o \ + inode_io.o \ ismounted.o \ link.o \ llseek.o \ @@ -94,6 +95,7 @@ SRCS= ext2_err.c \ $(srcdir)/initialize.c \ $(srcdir)/inline.c \ $(srcdir)/inode.c \ + $(srcdir)/inode_io.c \ $(srcdir)/ismounted.c \ $(srcdir)/link.c \ $(srcdir)/llseek.c \ @@ -377,6 +379,10 @@ inode.o: $(srcdir)/inode.c $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h $(srcdir)/e2image.h +inode_io.o: $(srcdir)/inode_io.c $(srcdir)/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ + $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h ismounted.o: $(srcdir)/ismounted.c $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in index 235f75d..ab36c9d 100644 --- a/lib/ext2fs/ext2_err.et.in +++ b/lib/ext2fs/ext2_err.et.in @@ -59,8 +59,8 @@ ec EXT2_ET_MAGIC_EXT2_FILE, ec EXT2_ET_MAGIC_E2IMAGE, "Wrong magic number for Ext2 Image Header" -ec EXT2_ET_MAGIC_RESERVED_8, - "Wrong magic number --- RESERVED_8" +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" @@ -272,5 +272,8 @@ ec EXT2_ET_JOURNAL_UNSUPP_VERSION, ec EXT2_ET_LOAD_EXT_JOURNAL, "Error loading external journal" +ec EXT2_ET_NO_JOURNAL, + "Journal not found" + end diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 75512d1..e37b817 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -638,9 +638,10 @@ extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, int flags, ext2_file_t *ret); extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file); extern errcode_t ext2fs_file_close(ext2_file_t file); +extern errcode_t ext2fs_file_flush(ext2_file_t file); extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf, unsigned int wanted, unsigned int *got); -extern errcode_t ext2fs_file_write(ext2_file_t file, void *buf, +extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, unsigned int nbytes, unsigned int *written); extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, int whence, ext2_off_t *ret_pos); @@ -678,6 +679,23 @@ extern errcode_t ext2fs_initialize(const char *name, int flags, struct ext2_super_block *param, io_manager manager, ext2_filsys *ret_fs); +/* icount.c */ +extern void ext2fs_free_icount(ext2_icount_t icount); +extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size, + ext2_icount_t hint, ext2_icount_t *ret); +extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size, + ext2_icount_t *ret); +extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, + __u16 count); +extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount); +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); + /* inode.c */ extern errcode_t ext2fs_flush_icache(ext2_filsys fs); extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, @@ -703,23 +721,9 @@ extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino); -/* icount.c */ -extern void ext2fs_free_icount(ext2_icount_t icount); -extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size, - ext2_icount_t hint, ext2_icount_t *ret); -extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size, - ext2_icount_t *ret); -extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret); -extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret); -extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret); -extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, - __u16 count); -extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount); -errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); - +/* inode_io.c */ +extern io_manager inode_io_manager; + /* ismounted.c */ extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags); extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, diff --git a/lib/ext2fs/fileio.c b/lib/ext2fs/fileio.c index e2f4795..f0b216e 100644 --- a/lib/ext2fs/fileio.c +++ b/lib/ext2fs/fileio.c @@ -88,7 +88,7 @@ ext2_filsys ext2fs_file_get_fs(ext2_file_t file) * This function flushes the dirty block buffer out to disk if * necessary. */ -static errcode_t ext2fs_file_flush(ext2_file_t file) +errcode_t ext2fs_file_flush(ext2_file_t file) { errcode_t retval; ext2_filsys fs; @@ -235,7 +235,7 @@ fail: } -errcode_t ext2fs_file_write(ext2_file_t file, void *buf, +errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, unsigned int nbytes, unsigned int *written) { ext2_filsys fs; diff --git a/lib/ext2fs/inode_io.c b/lib/ext2fs/inode_io.c new file mode 100644 index 0000000..bb72403 --- /dev/null +++ b/lib/ext2fs/inode_io.c @@ -0,0 +1,264 @@ +/* + * inode_io.c --- This is allows an inode in an ext2 filesystem image + * to be accessed via the I/O manager interface. + * + * Copyright (C) 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +struct inode_private_data { + int magic; + char name[32]; + ext2_file_t file; + ext2_filsys fs; + ext2_ino_t ino; + int flags; + struct inode_private_data *next; +}; + +static struct inode_private_data *top_intern; +static int ino_unique = 0; + +static errcode_t inode_open(const char *name, int flags, io_channel *channel); +static errcode_t inode_close(io_channel channel); +static errcode_t inode_set_blksize(io_channel channel, int blksize); +static errcode_t inode_read_blk(io_channel channel, unsigned long block, + int count, void *data); +static errcode_t inode_write_blk(io_channel channel, unsigned long block, + int count, const void *data); +static errcode_t inode_flush(io_channel channel); +static errcode_t inode_write_byte(io_channel channel, unsigned long offset, + int size, const void *data); + +static struct struct_io_manager struct_inode_manager = { + EXT2_ET_MAGIC_IO_MANAGER, + "Inode I/O Manager", + inode_open, + inode_close, + inode_set_blksize, + inode_read_blk, + inode_write_blk, + inode_flush, + inode_write_byte +}; + +io_manager inode_io_manager = &struct_inode_manager; + +errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, + char **name) +{ + struct inode_private_data *data; + errcode_t retval; + + if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data), + (void **) &data))) + return retval; + data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL; + sprintf(data->name, "%lu:%d", ino, ino_unique++); + data->file = 0; + data->fs = fs; + data->ino = ino; + data->flags = 0; + data->next = top_intern; + top_intern = data; + *name = data->name; + return 0; +} + + +static errcode_t inode_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + struct inode_private_data *prev, *data = NULL; + errcode_t retval; + int open_flags; + + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + + for (data = top_intern, prev = NULL; data; + prev = data, data = data->next) + if (strcmp(name, data->name) == 0) + break; + if (!data) + return ENOENT; + if (prev) + prev->next = data->next; + else + top_intern = data->next; + + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), + (void **) &io); + if (retval) + goto cleanup; + memset(io, 0, sizeof(struct struct_io_channel)); + + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + io->manager = inode_io_manager; + retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + + open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0; + retval = ext2fs_file_open(data->fs, data->ino, open_flags, + &data->file); + if (retval) + goto cleanup; + + *channel = io; + return 0; + +cleanup: + if (data) { + ext2fs_free_mem((void **) &data); + } + if (io) + ext2fs_free_mem((void **) &io); + return retval; +} + +static errcode_t inode_close(io_channel channel) +{ + struct inode_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + + retval = ext2fs_file_close(data->file); + + ext2fs_free_mem((void **) &channel->private_data); + if (channel->name) + ext2fs_free_mem((void **) &channel->name); + ext2fs_free_mem((void **) &channel); + return retval; +} + +static errcode_t inode_set_blksize(io_channel channel, int blksize) +{ + struct inode_private_data *data; + errcode_t retval; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + channel->block_size = blksize; + return 0; +} + + +static errcode_t inode_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + struct inode_private_data *data; + struct inode_cache *cache; + errcode_t retval; + char *cp; + int i, j; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if ((retval = ext2fs_file_lseek(data->file, + block * channel->block_size, + EXT2_SEEK_SET, 0))) + return retval; + + count = (count < 0) ? -count : (count * channel->block_size); + + return ext2fs_file_read(data->file, buf, count, 0); +} + +static errcode_t inode_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + struct inode_private_data *data; + struct inode_cache *cache; + errcode_t retval = 0, retval2; + const char *cp; + int writethrough; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if ((retval = ext2fs_file_lseek(data->file, + block * channel->block_size, + EXT2_SEEK_SET, 0))) + return retval; + + count = (count < 0) ? -count : (count * channel->block_size); + + return ext2fs_file_write(data->file, buf, count, 0); +} + +static errcode_t inode_write_byte(io_channel channel, unsigned long offset, + int size, const void *buf) +{ + struct inode_private_data *data; + errcode_t retval = 0; + size_t actual; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if ((retval = ext2fs_file_lseek(data->file, offset, + EXT2_SEEK_SET, 0))) + return retval; + + return ext2fs_file_write(data->file, buf, size, 0); +} + +/* + * Flush data buffers to disk. + */ +static errcode_t inode_flush(io_channel channel) +{ + struct inode_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + return ext2fs_file_flush(data->file); +} + diff --git a/lib/ext2fs/test_io.c b/lib/ext2fs/test_io.c index b259d0f..baca786 100644 --- a/lib/ext2fs/test_io.c +++ b/lib/ext2fs/test_io.c @@ -154,8 +154,7 @@ static errcode_t test_close(io_channel channel) if (data->real) retval = io_channel_close(data->real); - if (channel->private_data) - ext2fs_free_mem((void **) &channel->private_data); + ext2fs_free_mem((void **) &channel->private_data); if (channel->name) ext2fs_free_mem((void **) &channel->name); ext2fs_free_mem((void **) &channel); diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 7fa4b1a..0f993e4 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -385,8 +385,8 @@ static errcode_t unix_close(io_channel channel) if (close(data->dev) < 0) retval = errno; free_cache(channel, data); - if (channel->private_data) - ext2fs_free_mem((void **) &channel->private_data); + + ext2fs_free_mem((void **) &channel->private_data); if (channel->name) ext2fs_free_mem((void **) &channel->name); ext2fs_free_mem((void **) &channel);