unix_io.c revision b5abe6fac9c9e7caf4710501d1657d30e4857ef6
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * unix_io.c --- This is the Unix I/O interface to the I/O manager. 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Implements a one-block write-through cache. 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. 719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 1119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 164cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 184cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 211d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_STAT_H 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 231d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 241d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 261d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 28b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#if EXT2_FLAT_INCLUDES 29b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 30b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#else 317b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o#include <linux/ext2_fs.h> 32b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#endif 337b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 347b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o#include "ext2fs.h" 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o/* 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * For checking structure magic numbers... 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 40f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define EXT2_CHECK_MAGIC(struct, code) \ 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if ((struct)->magic != (code)) return (code) 42f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct unix_private_data { 44f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int magic; 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int flags; 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *buf; 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int buf_block_nr; 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel); 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel); 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize); 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *data); 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *data); 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel); 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 60f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic struct struct_io_manager struct_unix_manager = { 61f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_ET_MAGIC_IO_MANAGER, 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "Unix I/O Manager", 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_open, 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_close, 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_set_blksize, 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_read_blk, 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_write_blk, 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_flush 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oio_manager unix_io_manager = &struct_unix_manager; 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel) 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel io = NULL; 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data = NULL; 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (name == 0) 8050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return EXT2_ET_BAD_DEVICE_NAME; 817b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct struct_io_channel), 827b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o (void **) &io); 837b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 847b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 85f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o memset(io, 0, sizeof(struct struct_io_channel)); 86f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 877b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct unix_private_data), 887b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o (void **) &data); 897b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 917b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->manager = unix_io_manager; 937b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name); 947b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 967b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o strcpy(io->name, name); 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->private_data = data; 99f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->block_size = 1024; 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->read_error = 0; 101f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->write_error = 0; 102a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o io->refcount = 1; 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(data, 0, sizeof(struct unix_private_data)); 105f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; 1067b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(io->block_size, (void **) &data->buf); 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1087b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1107b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->dev = open(name, (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY); 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->dev < 0) { 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *channel = io; 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (io) 1217b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &io); 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data) { 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1247b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data->buf); 1257b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data); 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel) 1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval = 0; 1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 135f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 138a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 139a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (--channel->refcount > 0) 140a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 141f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (close(data->dev) < 0) 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1457b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data->buf); 1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->private_data) 1477b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &channel->private_data); 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->name) 1497b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &channel->name); 1507b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &channel); 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize) 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1577b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 159f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 161f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 162f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->block_size != blksize) { 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o channel->block_size = blksize; 1657b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o ext2fs_free_mem((void **) &data->buf); 1667b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o retval = ext2fs_get_mem(blksize, (void **) &data->buf); 1677b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1687b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *buf) 1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 181f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 184f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 186f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If it's in the cache, use it! 1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) { 1923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(buf, data->buf, channel->block_size); 1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 195f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#if 0 196f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("read_block %lu (%d)\n", block, count); 197f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif 1983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = (count < 0) ? -count : count * channel->block_size; 199f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 20019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 2015be8dc2143c7b3b21a9b8fb56797dd855ee87560Theodore Ts'o retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; 2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = read(data->dev, buf, size); 2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual < 0) 2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = 0; 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_READ; 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) { 2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = block; 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset((char *) buf+actual, 0, size-actual); 2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->read_error) 2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->read_error)(channel, block, count, buf, 2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *buf) 2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 230f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 234f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 236f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 2373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) 2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = channel->block_size; 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else { 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; /* Invalidate the cache */ 2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count < 0) 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = -count; 2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = count * channel->block_size; 2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 247f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 248f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 24919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 2505be8dc2143c7b3b21a9b8fb56797dd855ee87560Theodore Ts'o retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; 2513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = write(data->dev, buf, size); 2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_WRITE; 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->write_error) 2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->write_error)(channel, block, count, buf, 2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 27336f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o * Flush data buffers to disk. 2743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel) 2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 277f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct unix_private_data *data; 278f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 279f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 280f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 281f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 282f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 28336f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o fsync(data->dev); 2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 287