unix_io.c revision 36f21439f5d8b2233d13e042833d4d921a5c2c40
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> 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 2250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#if HAVE_ERRNO_H 2350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 2450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 2750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include "ext2fs/ext2_err.h" 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "io.h" 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 30f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o/* 31f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * For checking structure magic numbers... 32f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 33f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 34f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define EXT2_CHECK_MAGIC(struct, code) \ 35f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if ((struct)->magic != (code)) return (code) 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct unix_private_data { 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int magic; 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int flags; 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *buf; 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int buf_block_nr; 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel); 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel); 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize); 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *data); 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *data); 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel); 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 54f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic struct struct_io_manager struct_unix_manager = { 55f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_ET_MAGIC_IO_MANAGER, 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "Unix I/O Manager", 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_open, 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_close, 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_set_blksize, 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_read_blk, 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_write_blk, 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_flush 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oio_manager unix_io_manager = &struct_unix_manager; 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel) 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel io = NULL; 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data = NULL; 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (name == 0) 7450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return EXT2_ET_BAD_DEVICE_NAME; 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io = (io_channel) malloc(sizeof(struct struct_io_channel)); 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!io) 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ENOMEM; 78f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o memset(io, 0, sizeof(struct struct_io_channel)); 79f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o malloc(sizeof(struct unix_private_data)); 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!data) { 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ENOMEM; 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->manager = unix_io_manager; 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->name = malloc(strlen(name)+1); 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!io->name) { 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ENOMEM; 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o strcpy(io->name, name); 933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->private_data = data; 94f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->block_size = 1024; 95f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->read_error = 0; 96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->write_error = 0; 97a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o io->refcount = 1; 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(data, 0, sizeof(struct unix_private_data)); 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf = malloc(io->block_size); 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!data->buf) { 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ENOMEM; 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->dev = open(name, (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY); 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->dev < 0) { 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *channel = io; 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (io) 1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(io); 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data) { 1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data->buf); 1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data); 1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel) 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval = 0; 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 131f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 133f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 134a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 135a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (--channel->refcount > 0) 136a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (close(data->dev) < 0) 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->buf) 1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data->buf); 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->private_data) 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(channel->private_data); 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->name) 1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(channel->name); 1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(channel); 1473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize) 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 154f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 156f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 157f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->block_size != blksize) { 1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o channel->block_size = blksize; 1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free(data->buf); 1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf = malloc(blksize); 1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!data->buf) 1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ENOMEM; 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *buf) 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 176f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 179f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 181f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If it's in the cache, use it! 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) { 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(buf, data->buf, channel->block_size); 1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 190f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#if 0 191f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("read_block %lu (%d)\n", block, count); 192f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif 1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = (count < 0) ? -count : count * channel->block_size; 194f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 19519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 1983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = read(data->dev, buf, size); 2003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual < 0) 2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = 0; 2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_READ; 2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) { 2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = block; 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset((char *) buf+actual, 0, size-actual); 2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->read_error) 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->read_error)(channel, block, count, buf, 2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *buf) 2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size_t size; 225f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_loff_t location; 2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int actual = 0; 2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 229f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 231f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count == 1) 2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = channel->block_size; 2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else { 2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data->buf_block_nr = -1; /* Invalidate the cache */ 2373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (count < 0) 2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = -count; 2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size = count * channel->block_size; 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 242f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 243f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 24419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o actual = write(data->dev, buf, size); 2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (actual != size) { 2513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_SHORT_WRITE; 2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto error_out; 2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if ((count == 1) && (block == data->buf_block_nr)) 2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memcpy(data->buf, buf, size); /* Update the cache */ 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oerror_out: 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->write_error) 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = (channel->write_error)(channel, block, count, buf, 2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o size, actual, retval); 2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 26836f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o * Flush data buffers to disk. 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel) 2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 272f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct unix_private_data *data; 273f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 274f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 275f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 276f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 277f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 27836f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o fsync(data->dev); 2793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 2803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 282