static errcode_t unix_close(io_channel channel) { struct unix_private_data *data; errcode_t retval = 0; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); if (--channel->refcount > 0) return 0; #ifndef NO_IO_CACHE retval = flush_cached_blocks(channel, data, 0); #endif if (close(data->dev) < 0) retval = errno; free_cache(data); ext2fs_free_mem(&channel->private_data); if (channel->name) ext2fs_free_mem(&channel->name); ext2fs_free_mem(&channel); return retval; }
static errcode_t unix_write_byte(io_channel channel, unsigned long offset, int size, const void *buf) { struct unix_private_data *data; errcode_t retval = 0; ssize_t actual; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); #ifndef NO_IO_CACHE /* * Flush out the cache completely */ if ((retval = flush_cached_blocks(channel, data, 1))) return retval; #endif if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0) return errno; actual = write(data->dev, buf, size); if (actual != size) return EXT2_ET_SHORT_WRITE; return 0; }
static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, int count, const void *buf) { struct unix_private_data *data; struct unix_cache *cache, *reuse; errcode_t retval = 0; const char *cp; int writethrough; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); #ifdef NO_IO_CACHE return raw_write_blk(channel, data, block, count, buf); #else /* * If we're doing an odd-sized write or a very large write, * flush out the cache completely and then do a direct write. */ if (count < 0 || count > WRITE_DIRECT_SIZE) { if ((retval = flush_cached_blocks(channel, data, 1))) return retval; return raw_write_blk(channel, data, block, count, buf); } /* * For a moderate-sized multi-block write, first force a write * if we're in write-through cache mode, and then fill the * cache with the blocks. */ writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; if (writethrough) retval = raw_write_blk(channel, data, block, count, buf); cp = buf; while (count > 0) { cache = find_cached_block(data, block, &reuse); if (!cache) { cache = reuse; reuse_cache(channel, data, cache, block); } memcpy(cache->buf, cp, channel->block_size); cache->dirty = !writethrough; count--; block++; cp += channel->block_size; } return retval; #endif /* NO_IO_CACHE */ }
/* * Flush data buffers to disk. */ static errcode_t unix_flush(io_channel channel) { struct unix_private_data *data; errcode_t retval = 0; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); #ifndef NO_IO_CACHE retval = flush_cached_blocks(channel, data, 0); #endif fsync(data->dev); return retval; }
static errcode_t unix_set_blksize(io_channel channel, int blksize) { struct unix_private_data *data; errcode_t retval; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); if (channel->block_size != blksize) { #ifndef NO_IO_CACHE if ((retval = flush_cached_blocks(channel, data, 0))) return retval; #endif channel->block_size = blksize; free_cache(data); if ((retval = alloc_cache(channel, data))) return retval; } return 0; }
static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, int count, void *buf) { struct unix_private_data *data; struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; errcode_t retval; char *cp; int i, j; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); #ifdef NO_IO_CACHE return raw_read_blk(channel, data, block, count, buf); #else /* * If we're doing an odd-sized read or a very large read, * flush out the cache and then do a direct read. */ if (count < 0 || count > WRITE_DIRECT_SIZE) { if ((retval = flush_cached_blocks(channel, data, 0))) return retval; return raw_read_blk(channel, data, block, count, buf); } cp = buf; while (count > 0) { /* If it's in the cache, use it! */ if ((cache = find_cached_block(data, block, &reuse[0]))) { #ifdef DEBUG printf("Using cached block %lu\n", block); #endif memcpy(cp, cache->buf, channel->block_size); count--; block++; cp += channel->block_size; continue; } /* * Find the number of uncached blocks so we can do a * single read request */ for (i=1; i < count; i++) if (find_cached_block(data, block+i, &reuse[i])) break; #ifdef DEBUG printf("Reading %d blocks starting at %lu\n", i, block); #endif if ((retval = raw_read_blk(channel, data, block, i, cp))) return retval; /* Save the results in the cache */ for (j=0; j < i; j++) { count--; cache = reuse[j]; reuse_cache(channel, data, cache, block++); memcpy(cache->buf, cp, channel->block_size); cp += channel->block_size; } } return 0; #endif /* NO_IO_CACHE */ }