unix_io.c revision c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4e
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 2fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o * unix_io.c --- This is the Unix (well, really POSIX) implementation 3fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o * of the I/O manager. 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Implements a one-block write-through cache. 63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 7fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o * Includes support for Windows NT support under Cygwin. 8fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o * 964e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 1064e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o * 2002 by Theodore Ts'o. 1119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 1219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 1319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 1419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 1519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 18dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE_SOURCE 19dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE64_SOURCE 20dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 234cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 254cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 26c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#if HAVE_ERRNO_H 27c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#include <errno.h> 28c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#endif 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 31f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o#ifdef __linux__ 32f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o#include <sys/utsname.h> 33f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o#endif 341d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_STAT_H 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 361d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 371d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H 383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 391d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 40fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#if HAVE_SYS_RESOURCE_H 418880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o#include <sys/resource.h> 42fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#endif 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 44b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 457b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o#include "ext2fs.h" 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 47f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o/* 48f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * For checking structure magic numbers... 49f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 50f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 51f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define EXT2_CHECK_MAGIC(struct, code) \ 52f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if ((struct)->magic != (code)) return (code) 53adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 54adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'ostruct unix_cache { 55adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o char *buf; 56adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o unsigned long block; 57adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int access_time; 58adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int dirty:1; 59adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int in_use:1; 60adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o}; 61adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 62adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o#define CACHE_SIZE 8 6382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */ 6482c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */ 65adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct unix_private_data { 67f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int magic; 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int flags; 70adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int access_time; 71adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_cache cache[CACHE_SIZE]; 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel); 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel); 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize); 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *data); 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *data); 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel); 82c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'ostatic errcode_t unix_write_byte(io_channel channel, unsigned long offset, 83c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o int size, const void *data); 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8523b7c8b88673248b1f93abc717943867ad037bb4Theodore Ts'ostatic void reuse_cache(io_channel channel, struct unix_private_data *data, 8623b7c8b88673248b1f93abc717943867ad037bb4Theodore Ts'o struct unix_cache *cache, unsigned long block); 8723b7c8b88673248b1f93abc717943867ad037bb4Theodore Ts'o 88f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic struct struct_io_manager struct_unix_manager = { 89f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_ET_MAGIC_IO_MANAGER, 903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "Unix I/O Manager", 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_open, 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_close, 933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_set_blksize, 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_read_blk, 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unix_write_blk, 96c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o unix_flush, 97a85e81a2ff4fb1afc05ff74d5da573031c3495e0Theodore Ts'o#ifdef __CYGWIN__ 98fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o 0 99fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#else 100c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o unix_write_byte 101fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#endif 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oio_manager unix_io_manager = &struct_unix_manager; 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 106adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* 107adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * Here are the raw I/O functions 108adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 109a85e81a2ff4fb1afc05ff74d5da573031c3495e0Theodore Ts'o#ifndef __CYGWIN__ 110adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'ostatic errcode_t raw_read_blk(io_channel channel, 111adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_private_data *data, 112adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o unsigned long block, 113adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int count, void *buf) 114adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 115adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o errcode_t retval; 116adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size_t size; 117adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o ext2_loff_t location; 118adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int actual = 0; 119adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 120adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size = (count < 0) ? -count : count * channel->block_size; 121adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 122adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 123adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; 124adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o goto error_out; 125adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 126adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o actual = read(data->dev, buf, size); 127adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (actual != size) { 128adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (actual < 0) 129adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o actual = 0; 130adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = EXT2_ET_SHORT_READ; 131adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o goto error_out; 132adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 133adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return 0; 134adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 135adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'oerror_out: 136adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o memset((char *) buf+actual, 0, size-actual); 137adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (channel->read_error) 138adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = (channel->read_error)(channel, block, count, buf, 139adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size, actual, retval); 140adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 141adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 142a85e81a2ff4fb1afc05ff74d5da573031c3495e0Theodore Ts'o#else /* __CYGWIN__ */ 143fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o/* 144fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o * Windows block devices only allow sector alignment IO in offset and size 145fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o */ 146fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'ostatic errcode_t raw_read_blk(io_channel channel, 147fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o struct unix_private_data *data, 148fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o unsigned long block, 149fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o int count, void *buf) 150fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o{ 151fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o errcode_t retval; 152fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o size_t size, alignsize, fragment; 153fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o ext2_loff_t location; 154fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o int total = 0, actual; 155fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#define BLOCKALIGN 512 156fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o char sector[BLOCKALIGN]; 157fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o 158fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o size = (count < 0) ? -count : count * channel->block_size; 159fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o location = (ext2_loff_t) block * channel->block_size; 160fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#ifdef DEBUG 161fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n", 162fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o count, size, block, channel->block_size, location); 163fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#endif 164fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 165fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; 166fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o goto error_out; 167fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o } 168fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o fragment = size % BLOCKALIGN; 169fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o alignsize = size - fragment; 170fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o if (alignsize) { 171fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o actual = read(data->dev, buf, alignsize); 172fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o if (actual != alignsize) 173fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o goto short_read; 174fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o } 175fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o if (fragment) { 176fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o actual = read(data->dev, sector, BLOCKALIGN); 177fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o if (actual != BLOCKALIGN) 178fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o goto short_read; 179fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o memcpy(buf+alignsize, sector, fragment); 180fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o } 181fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o return 0; 182fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o 183fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'oshort_read: 184fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o if (actual>0) 185fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o total += actual; 186fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o retval = EXT2_ET_SHORT_READ; 187fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o 188fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'oerror_out: 189fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o memset((char *) buf+total, 0, size-actual); 190fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o if (channel->read_error) 191fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o retval = (channel->read_error)(channel, block, count, buf, 192fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o size, actual, retval); 193fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o return retval; 194fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o} 195fff45483ede7fe38a31b3364a9c07e2418776deeTheodore Ts'o#endif 196adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 197adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'ostatic errcode_t raw_write_blk(io_channel channel, 198adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_private_data *data, 199adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o unsigned long block, 200adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int count, const void *buf) 201adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 202adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size_t size; 203adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o ext2_loff_t location; 204adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int actual = 0; 205adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o errcode_t retval; 206adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 207adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (count == 1) 208adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size = channel->block_size; 209adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o else { 210adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (count < 0) 211adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size = -count; 212adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o else 213adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size = count * channel->block_size; 214adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 215adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 216adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o location = (ext2_loff_t) block * channel->block_size; 217adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { 218adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; 219adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o goto error_out; 220adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 221adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 222adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o actual = write(data->dev, buf, size); 223adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (actual != size) { 224adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = EXT2_ET_SHORT_WRITE; 225adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o goto error_out; 226adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 227adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return 0; 228adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 229adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'oerror_out: 230adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (channel->write_error) 231adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = (channel->write_error)(channel, block, count, buf, 232adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o size, actual, retval); 233adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 234adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 235adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 236adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 237adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* 238adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * Here we implement the cache functions 239adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 240adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 241adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* Allocate the cache buffers */ 242adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'ostatic errcode_t alloc_cache(io_channel channel, 243adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_private_data *data) 244adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 245adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o errcode_t retval; 246adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_cache *cache; 247adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i; 248adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 249adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o data->access_time = 0; 250adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { 251adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->block = 0; 252adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->access_time = 0; 253adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->dirty = 0; 254adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->in_use = 0; 255adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = ext2fs_get_mem(channel->block_size, 256c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &cache->buf))) 257adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 258adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 259adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return 0; 260adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 261adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 262adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* Free the cache buffers */ 263adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'ostatic void free_cache(io_channel channel, 264adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_private_data *data) 265adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 266adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_cache *cache; 267adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i; 268adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 269adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o data->access_time = 0; 270adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { 271adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->block = 0; 272adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->access_time = 0; 273adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->dirty = 0; 274adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->in_use = 0; 275adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (cache->buf) 276c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&cache->buf); 277adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->buf = 0; 278adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 279adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 280adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 281b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 282adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* 28382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * Try to find a block in the cache. If the block is not found, and 28482c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * eldest is a non-zero pointer, then fill in eldest with the cache 28582c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * entry to that should be reused. 286adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 28731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'ostatic struct unix_cache *find_cached_block(io_channel channel, 28831dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o struct unix_private_data *data, 28931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o unsigned long block, 29082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache **eldest) 291adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 29231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o struct unix_cache *cache, *unused_cache, *oldest_cache; 293adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i; 294adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 29531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o unused_cache = oldest_cache = 0; 296adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { 297adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache->in_use) { 29882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (!unused_cache) 29982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o unused_cache = cache; 300adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 301adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 302adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (cache->block == block) { 303adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->access_time = ++data->access_time; 304adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return cache; 305adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 306adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!oldest_cache || 307adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o (cache->access_time < oldest_cache->access_time)) 308adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o oldest_cache = cache; 309adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 31082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (eldest) 31182c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o *eldest = (unused_cache) ? unused_cache : oldest_cache; 31282c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o return 0; 31382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o} 31482c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o 31582c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o/* 31682c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * Reuse a particular cache entry for another block. 31782c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o */ 31823b7c8b88673248b1f93abc717943867ad037bb4Theodore Ts'ostatic void reuse_cache(io_channel channel, struct unix_private_data *data, 31982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache *cache, unsigned long block) 32082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o{ 32182c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (cache->dirty && cache->in_use) 32282c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o raw_write_blk(channel, data, cache->block, 1, cache->buf); 32382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o 324adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->in_use = 1; 3251d47dfb91ef010c506e9354dec102385d8494d8fTheodore Ts'o cache->dirty = 0; 326adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->block = block; 327adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->access_time = ++data->access_time; 328adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 329adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 330adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* 331adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * Flush all of the blocks in the cache 332adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 333adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'ostatic errcode_t flush_cached_blocks(io_channel channel, 334adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_private_data *data, 335adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int invalidate) 336adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 337adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 338adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_cache *cache; 339adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o errcode_t retval, retval2; 340adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i; 341adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 342adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval2 = 0; 343adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { 344adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache->in_use) 345adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 346adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 347adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (invalidate) 348adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->in_use = 0; 349adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 350adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache->dirty) 351adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 352adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 353adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = raw_write_blk(channel, data, 354adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->block, 1, cache->buf); 355adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (retval) 356adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval2 = retval; 357adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o else 358adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->dirty = 0; 359adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 360adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval2; 361adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 362b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif /* NO_IO_CACHE */ 363adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 3643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel) 3653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel io = NULL; 3673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data = NULL; 3683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 369dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o int open_flags; 3708880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o struct stat st; 371f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o#ifdef __linux__ 372f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o struct utsname ut; 373f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o#endif 3743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 37550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (name == 0) 37650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return EXT2_ET_BAD_DEVICE_NAME; 377c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); 3787b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3797b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 380f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o memset(io, 0, sizeof(struct struct_io_channel)); 381f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 382c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data); 3837b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 3857b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->manager = unix_io_manager; 387c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(strlen(name)+1, &io->name); 3887b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 3907b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 3913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o strcpy(io->name, name); 3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->private_data = data; 393f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->block_size = 1024; 394f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->read_error = 0; 395f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->write_error = 0; 396a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o io->refcount = 1; 3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(data, 0, sizeof(struct unix_private_data)); 399f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; 4007b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 401adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = alloc_cache(io, data))) 402adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o goto cleanup; 403adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 404dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; 405dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#ifdef HAVE_OPEN64 406dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o data->dev = open64(name, open_flags); 407dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#else 408dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o data->dev = open(name, open_flags); 409dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#endif 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->dev < 0) { 4113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 4123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 4133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 41464e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o 41564e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#ifdef __linux__ 41664e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#undef RLIM_INFINITY 41764e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4))) 41864e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#define RLIM_INFINITY ((unsigned long)(~0UL>>1)) 41964e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#else 42064e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#define RLIM_INFINITY (~0UL) 42164e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#endif 4228880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o /* 423f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * Work around a bug in 2.4.10-2.4.18 kernels where writes to 424f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * block devices are wrongly getting hit by the filesize 425f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * limit. This workaround isn't perfect, since it won't work 426f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * if glibc wasn't built against 2.2 header files. (Sigh.) 427f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * 4288880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o */ 429f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o if ((flags & IO_FLAG_RW) && 430f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (uname(&ut) == 0) && 431f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o ((ut.release[0] == '2') && (ut.release[1] == '.') && 432f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (ut.release[2] == '4') && (ut.release[3] == '.') && 433f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (ut.release[4] == '1') && (ut.release[5] >= '0') && 434f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (ut.release[5] < '8')) && 4358880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o (fstat(data->dev, &st) == 0) && 4368880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o (S_ISBLK(st.st_mode))) { 4378880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o struct rlimit rlim; 4388880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o 43964e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY; 4408880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o setrlimit(RLIMIT_FSIZE, &rlim); 4418880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o getrlimit(RLIMIT_FSIZE, &rlim); 442bd27880b4ba42544f30a08ac3b6ba86190da021bTheodore Ts'o if (((unsigned long) rlim.rlim_cur) < 443bd27880b4ba42544f30a08ac3b6ba86190da021bTheodore Ts'o ((unsigned long) rlim.rlim_max)) { 4448880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o rlim.rlim_cur = rlim.rlim_max; 4458880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o setrlimit(RLIMIT_FSIZE, &rlim); 4468880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o } 4478880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o } 44864e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#endif 4493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *channel = io; 4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data) { 454adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o free_cache(io, data); 455c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&data); 4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 457adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (io) 458c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&io); 4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel) 4633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval = 0; 4663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 467f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 469f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 470a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 471a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (--channel->refcount > 0) 472a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 473adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 474b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 475adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = flush_cached_blocks(channel, data, 0); 476b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 477adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 4783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (close(data->dev) < 0) 4793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 480adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o free_cache(channel, data); 481f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o 482c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&channel->private_data); 4833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->name) 484c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&channel->name); 485c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&channel); 4863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 4873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize) 4903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 4927b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 4933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 494f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 496f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 497f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 4983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->block_size != blksize) { 499b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 500adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 0))) 501adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 502b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 503adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 5043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o channel->block_size = blksize; 505adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o free_cache(channel, data); 506adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = alloc_cache(channel, data))) 5077b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 5083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 5143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *buf) 5153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 51782c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; 5183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 51931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o char *cp; 520adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i, j; 5213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 522f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 5233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 524f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 5253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 526b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifdef NO_IO_CACHE 527b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o return raw_read_blk(channel, data, block, count, buf); 528b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#else 5293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 53082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * If we're doing an odd-sized read or a very large read, 53182c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * flush out the cache and then do a direct read. 5323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 53382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (count < 0 || count > WRITE_DIRECT_SIZE) { 534adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 0))) 535adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 536adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return raw_read_blk(channel, data, block, count, buf); 5373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 538adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 53931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp = buf; 540adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o while (count > 0) { 541adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* If it's in the cache, use it! */ 54282c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if ((cache = find_cached_block(channel, data, block, 54382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o &reuse[0]))) { 544adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o#ifdef DEBUG 545adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o printf("Using cached block %d\n", block); 546f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif 54731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o memcpy(cp, cache->buf, channel->block_size); 548adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o count--; 549adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o block++; 55031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp += channel->block_size; 551adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 552adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 553adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* 554adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * Find the number of uncached blocks so we can do a 555adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * single read request 556adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 557adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=1; i < count; i++) 55882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (find_cached_block(channel, data, block+i, 55982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o &reuse[i])) 560adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o break; 561adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o#ifdef DEBUG 562adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o printf("Reading %d blocks starting at %d\n", i, block); 563adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o#endif 56431dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o if ((retval = raw_read_blk(channel, data, block, i, cp))) 565adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 566adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 567adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* Save the results in the cache */ 568adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (j=0; j < i; j++) { 569adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o count--; 57082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o cache = reuse[j]; 57182c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o reuse_cache(channel, data, cache, block++); 57282c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o memcpy(cache->buf, cp, channel->block_size); 57331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp += channel->block_size; 574adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 5753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 577b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif /* NO_IO_CACHE */ 5783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 5813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *buf) 5823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 58482c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache *cache, *reuse; 58523b7c8b88673248b1f93abc717943867ad037bb4Theodore Ts'o errcode_t retval = 0; 58631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o const char *cp; 58731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o int writethrough; 5883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 589f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 5903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 591f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 5923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 593b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifdef NO_IO_CACHE 594b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o return raw_write_blk(channel, data, block, count, buf); 595b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#else 596adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* 597adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * If we're doing an odd-sized write or a very large write, 598adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * flush out the cache completely and then do a direct write. 599adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 60082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (count < 0 || count > WRITE_DIRECT_SIZE) { 601adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 1))) 602adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 603adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return raw_write_blk(channel, data, block, count, buf); 6043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 606adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* 607adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * For a moderate-sized multi-block write, first force a write 608adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * if we're in write-through cache mode, and then fill the 609adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * cache with the blocks. 610adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 611adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; 612adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (writethrough) 613adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = raw_write_blk(channel, data, block, count, buf); 6143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 61531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp = buf; 616adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o while (count > 0) { 61782c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o cache = find_cached_block(channel, data, block, &reuse); 618adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache) { 61982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o cache = reuse; 62082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o reuse_cache(channel, data, cache, block); 621adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 62282c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o memcpy(cache->buf, cp, channel->block_size); 62382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o cache->dirty = !writethrough; 624adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o count--; 625adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o block++; 62631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp += channel->block_size; 627adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 6283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 629b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif /* NO_IO_CACHE */ 6303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 632c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'ostatic errcode_t unix_write_byte(io_channel channel, unsigned long offset, 633c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o int size, const void *buf) 634c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o{ 635c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o struct unix_private_data *data; 63631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o errcode_t retval = 0; 637c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o size_t actual; 638c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 639c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 640c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 641c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 642c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 643b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 644c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o /* 645c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * Flush out the cache completely 646c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o */ 647c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 1))) 648c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return retval; 649b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 650c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 651c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if (lseek(data->dev, offset, SEEK_SET) < 0) 652c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return errno; 653c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 654c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o actual = write(data->dev, buf, size); 655c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if (actual != size) 656c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return EXT2_ET_SHORT_WRITE; 657c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 658c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return 0; 659c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o} 660c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 6613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 66236f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o * Flush data buffers to disk. 6633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 6643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel) 6653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 666f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct unix_private_data *data; 667adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o errcode_t retval = 0; 668f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 669f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 670f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 671f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 672adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 673b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 674adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = flush_cached_blocks(channel, data, 0); 675b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 67636f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o fsync(data->dev); 677adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 6783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 680