diff options
Diffstat (limited to 'lib/ext2fs/unix_io.c')
-rw-r--r-- | lib/ext2fs/unix_io.c | 181 |
1 files changed, 97 insertions, 84 deletions
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index da3f8fde..c3185b6a 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -1,13 +1,13 @@ /* * unix_io.c --- This is the Unix (well, really POSIX) implementation - * of the I/O manager. + * of the I/O manager. * * Implements a one-block write-through cache. * * Includes support for Windows NT support under Cygwin. * * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - * 2002 by Theodore Ts'o. + * 2002 by Theodore Ts'o. * * %Begin-Header% * This file may be redistributed under the terms of the GNU Library @@ -58,10 +58,6 @@ #define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */ #endif -#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET) -#define BLKSSZGET _IO(0x12,104)/* get block device sector size */ -#endif - #undef ALIGN_DEBUG #include "ext2_fs.h" @@ -75,11 +71,11 @@ if ((struct)->magic != (code)) return (code) struct unix_cache { - char *buf; - unsigned long block; - int access_time; - unsigned dirty:1; - unsigned in_use:1; + char *buf; + unsigned long long block; + int access_time; + unsigned dirty:1; + unsigned in_use:1; }; #define CACHE_SIZE 8 @@ -101,51 +97,9 @@ struct unix_private_data { #define IS_ALIGNED(n, align) ((((unsigned long) n) & \ ((unsigned long) ((align)-1))) == 0) -static errcode_t unix_open(const char *name, int flags, io_channel *channel); -static errcode_t unix_close(io_channel channel); -static errcode_t unix_set_blksize(io_channel channel, int blksize); -static errcode_t unix_read_blk(io_channel channel, unsigned long block, - int count, void *data); -static errcode_t unix_write_blk(io_channel channel, unsigned long block, - int count, const void *data); -static errcode_t unix_flush(io_channel channel); -static errcode_t unix_write_byte(io_channel channel, unsigned long offset, - int size, const void *data); -static errcode_t unix_set_option(io_channel channel, const char *option, - const char *arg); -static errcode_t unix_get_stats(io_channel channel, io_stats *stats) -; -static void reuse_cache(io_channel channel, struct unix_private_data *data, - struct unix_cache *cache, unsigned long long block); -static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, - int count, void *data); -static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, - int count, const void *data); -static errcode_t unix_discard(io_channel channel, unsigned long long block, - unsigned long long count); - -static struct struct_io_manager struct_unix_manager = { - EXT2_ET_MAGIC_IO_MANAGER, - "Unix I/O Manager", - unix_open, - unix_close, - unix_set_blksize, - unix_read_blk, - unix_write_blk, - unix_flush, - unix_write_byte, - unix_set_option, - unix_get_stats, - unix_read_blk64, - unix_write_blk64, - unix_discard, -}; - -io_manager unix_io_manager = &struct_unix_manager; - static errcode_t unix_get_stats(io_channel channel, io_stats *stats) { - errcode_t retval = 0; + errcode_t retval = 0; struct unix_private_data *data; @@ -180,8 +134,9 @@ static errcode_t raw_read_blk(io_channel channel, retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; goto error_out; } - if ((data->align == 0) || - ((IS_ALIGNED(buf, data->align)) && IS_ALIGNED(size, data->align))) { + if ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(size, channel->align))) { actual = read(data->dev, buf, size); if (actual != size) { short_read: @@ -250,8 +205,9 @@ static errcode_t raw_write_blk(io_channel channel, goto error_out; } - if ((data->align == 0) || - ((IS_ALIGNED(buf, data->align)) && IS_ALIGNED(size, data->align))) { + if ((channel->align == 0) || + (IS_ALIGNED(buf, channel->align) && + IS_ALIGNED(size, channel->align))) { actual = write(data->dev, buf, size); if (actual != size) { short_write: @@ -318,16 +274,14 @@ static errcode_t alloc_cache(io_channel channel, cache->in_use = 0; if (cache->buf) ext2fs_free_mem(&cache->buf); - retval = ext2fs_get_memalign(channel->block_size, - data->align, &cache->buf); + retval = io_channel_alloc_buf(channel, 0, &cache->buf); if (retval) return retval; } - if (data->align) { + if (channel->align) { if (data->bounce) ext2fs_free_mem(&data->bounce); - retval = ext2fs_get_memalign(channel->block_size, data->align, - &data->bounce); + retval = io_channel_alloc_buf(channel, 0, &data->bounce); } return retval; } @@ -439,16 +393,48 @@ static errcode_t flush_cached_blocks(io_channel channel, #endif #endif +int ext2fs_open_file(const char *pathname, int flags, mode_t mode) +{ + if (mode) +#if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return open64(pathname, flags, mode); + else + return open64(pathname, flags); +#else + return open(pathname, flags, mode); + else + return open(pathname, flags); +#endif +} + +int ext2fs_stat(const char *path, ext2fs_struct_stat *buf) +{ +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return stat64(path, buf); +#else + return stat(path, buf); +#endif +} + +int ext2fs_fstat(int fd, ext2fs_struct_stat *buf) +{ +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return fstat64(fd, buf); +#else + return fstat(fd, buf); +#endif +} + static errcode_t unix_open(const char *name, int flags, io_channel *channel) { io_channel io = NULL; struct unix_private_data *data = NULL; errcode_t retval; - int open_flags, zeroes = 0; + int open_flags; int f_nocache = 0; ext2fs_struct_stat st; #ifdef __linux__ - struct utsname ut; + struct utsname ut; #endif if (name == 0) @@ -477,16 +463,21 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel) memset(data, 0, sizeof(struct unix_private_data)); data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; data->io_stats.num_fields = 2; + data->dev = -1; open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; if (flags & IO_FLAG_EXCLUSIVE) open_flags |= O_EXCL; #if defined(O_DIRECT) - if (flags & IO_FLAG_DIRECT_IO) + if (flags & IO_FLAG_DIRECT_IO) { open_flags |= O_DIRECT; + io->align = ext2fs_get_dio_alignment(data->dev); + } #elif defined(F_NOCACHE) - if (flags & IO_FLAG_DIRECT_IO) + if (flags & IO_FLAG_DIRECT_IO) { f_nocache = F_NOCACHE; + io->align = 4096; + } #endif data->flags = flags; @@ -516,17 +507,13 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel) io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; } -#ifdef BLKSSZGET - if (flags & IO_FLAG_DIRECT_IO) { - if (ioctl(data->dev, BLKSSZGET, &data->align) != 0) - data->align = io->block_size; - } -#endif - #ifdef BLKDISCARDZEROES - ioctl(data->dev, BLKDISCARDZEROES, &zeroes); - if (zeroes) - io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; + { + int zeroes = 0; + if (ioctl(data->dev, BLKDISCARDZEROES, &zeroes) == 0 && + zeroes) + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; + } #endif #if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -534,7 +521,8 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel) * Some operating systems require that the buffers be aligned, * regardless of O_DIRECT */ - data->align = 512; + if (!io->align) + io->align = 512; #endif @@ -549,7 +537,6 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel) /* Is the block device actually writable? */ error = ioctl(data->dev, BLKROGET, &readonly); if (!error && readonly) { - close(data->dev); retval = EPERM; goto cleanup; } @@ -595,11 +582,17 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel) cleanup: if (data) { + if (data->dev >= 0) + close(data->dev); free_cache(data); ext2fs_free_mem(&data); } - if (io) + if (io) { + if (io->name) { + ext2fs_free_mem(&io->name); + } ext2fs_free_mem(&io); + } return retval; } @@ -810,7 +803,7 @@ static errcode_t unix_write_byte(io_channel channel, unsigned long offset, data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - if (data->align != 0) { + if (channel->align != 0) { #ifdef ALIGN_DEBUG printf("unix_write_byte: O_DIRECT fallback\n"); #endif @@ -888,7 +881,6 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, unsigned long long count) { struct unix_private_data *data; - __uint64_t range[2]; int ret; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); @@ -897,8 +889,10 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { #ifdef BLKDISCARD - range[0] = (__uint64_t)(block) * channel->block_size; - range[1] = (__uint64_t)(count) * channel->block_size; + __u64 range[2]; + + range[0] = (__u64)(block) * channel->block_size; + range[1] = (__u64)(count) * channel->block_size; ret = ioctl(data->dev, BLKDISCARD, &range); #else @@ -927,3 +921,22 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, unimplemented: return EXT2_ET_UNIMPLEMENTED; } + +static struct struct_io_manager struct_unix_manager = { + EXT2_ET_MAGIC_IO_MANAGER, + "Unix I/O Manager", + unix_open, + unix_close, + unix_set_blksize, + unix_read_blk, + unix_write_blk, + unix_flush, + unix_write_byte, + unix_set_option, + unix_get_stats, + unix_read_blk64, + unix_write_blk64, + unix_discard, +}; + +io_manager unix_io_manager = &struct_unix_manager; |