unix_io.c revision 544349270e4c74a6feb971123884a8cf5052a7ee
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; 116544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ssize_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{ 202544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ssize_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 */ 263544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void free_cache(struct unix_private_data *data) 264adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 265adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_cache *cache; 266adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i; 267adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 268adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o data->access_time = 0; 269adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { 270adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->block = 0; 271adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->access_time = 0; 272adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->dirty = 0; 273adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->in_use = 0; 274adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (cache->buf) 275c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&cache->buf); 276adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->buf = 0; 277adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 278adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 279adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 280b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 281adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* 28282c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * Try to find a block in the cache. If the block is not found, and 28382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * eldest is a non-zero pointer, then fill in eldest with the cache 28482c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * entry to that should be reused. 285adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 286544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic struct unix_cache *find_cached_block(struct unix_private_data *data, 28731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o unsigned long block, 28882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache **eldest) 289adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 29031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o struct unix_cache *cache, *unused_cache, *oldest_cache; 291adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i; 292adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 29331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o unused_cache = oldest_cache = 0; 294adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { 295adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache->in_use) { 29682c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (!unused_cache) 29782c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o unused_cache = cache; 298adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 299adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 300adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (cache->block == block) { 301adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->access_time = ++data->access_time; 302adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return cache; 303adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 304adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!oldest_cache || 305adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o (cache->access_time < oldest_cache->access_time)) 306adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o oldest_cache = cache; 307adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 30882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (eldest) 30982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o *eldest = (unused_cache) ? unused_cache : oldest_cache; 31082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o return 0; 31182c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o} 31282c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o 31382c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o/* 31482c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * Reuse a particular cache entry for another block. 31582c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o */ 31623b7c8b88673248b1f93abc717943867ad037bb4Theodore Ts'ostatic void reuse_cache(io_channel channel, struct unix_private_data *data, 31782c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache *cache, unsigned long block) 31882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o{ 31982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (cache->dirty && cache->in_use) 32082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o raw_write_blk(channel, data, cache->block, 1, cache->buf); 32182c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o 322adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->in_use = 1; 3231d47dfb91ef010c506e9354dec102385d8494d8fTheodore Ts'o cache->dirty = 0; 324adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->block = block; 325adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->access_time = ++data->access_time; 326adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 327adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 328adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o/* 329adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * Flush all of the blocks in the cache 330adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 331adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'ostatic errcode_t flush_cached_blocks(io_channel channel, 332adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_private_data *data, 333adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int invalidate) 334adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 335adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o{ 336adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o struct unix_cache *cache; 337adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o errcode_t retval, retval2; 338adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i; 339adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 340adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval2 = 0; 341adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { 342adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache->in_use) 343adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 344adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 345adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (invalidate) 346adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->in_use = 0; 347adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 348adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache->dirty) 349adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 350adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 351adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = raw_write_blk(channel, data, 352adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->block, 1, cache->buf); 353adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (retval) 354adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval2 = retval; 355adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o else 356adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o cache->dirty = 0; 357adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 358adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval2; 359adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o} 360b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif /* NO_IO_CACHE */ 361adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 3623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_open(const char *name, int flags, io_channel *channel) 3633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel io = NULL; 3653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data = NULL; 3663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 367dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o int open_flags; 3688880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o struct stat st; 369f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o#ifdef __linux__ 370f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o struct utsname ut; 371f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o#endif 3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 37350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (name == 0) 37450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return EXT2_ET_BAD_DEVICE_NAME; 375c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); 3767b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3777b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 378f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o memset(io, 0, sizeof(struct struct_io_channel)); 379f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 380c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data); 3817b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 3837b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->manager = unix_io_manager; 385c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(strlen(name)+1, &io->name); 3867b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 3887b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o strcpy(io->name, name); 3903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io->private_data = data; 391f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->block_size = 1024; 392f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->read_error = 0; 393f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o io->write_error = 0; 394a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o io->refcount = 1; 3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(data, 0, sizeof(struct unix_private_data)); 397f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; 3987b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 399adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = alloc_cache(io, data))) 400adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o goto cleanup; 401adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 402dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; 403dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#ifdef HAVE_OPEN64 404dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o data->dev = open64(name, open_flags); 405dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#else 406dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o data->dev = open(name, open_flags); 407dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#endif 4083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data->dev < 0) { 4093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 4113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 41264e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o 41364e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#ifdef __linux__ 41464e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#undef RLIM_INFINITY 41564e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4))) 41664e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#define RLIM_INFINITY ((unsigned long)(~0UL>>1)) 41764e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#else 41864e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#define RLIM_INFINITY (~0UL) 41964e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#endif 4208880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o /* 421f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * Work around a bug in 2.4.10-2.4.18 kernels where writes to 422f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * block devices are wrongly getting hit by the filesize 423f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * limit. This workaround isn't perfect, since it won't work 424f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * if glibc wasn't built against 2.2 header files. (Sigh.) 425f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o * 4268880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o */ 427f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o if ((flags & IO_FLAG_RW) && 428f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (uname(&ut) == 0) && 429f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o ((ut.release[0] == '2') && (ut.release[1] == '.') && 430f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (ut.release[2] == '4') && (ut.release[3] == '.') && 431f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (ut.release[4] == '1') && (ut.release[5] >= '0') && 432f154d2f687e922f8444ef3050dc83f5d8e0e2178Theodore Ts'o (ut.release[5] < '8')) && 4338880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o (fstat(data->dev, &st) == 0) && 4348880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o (S_ISBLK(st.st_mode))) { 4358880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o struct rlimit rlim; 4368880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o 43764e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY; 4388880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o setrlimit(RLIMIT_FSIZE, &rlim); 4398880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o getrlimit(RLIMIT_FSIZE, &rlim); 440bd27880b4ba42544f30a08ac3b6ba86190da021bTheodore Ts'o if (((unsigned long) rlim.rlim_cur) < 441bd27880b4ba42544f30a08ac3b6ba86190da021bTheodore Ts'o ((unsigned long) rlim.rlim_max)) { 4428880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o rlim.rlim_cur = rlim.rlim_max; 4438880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o setrlimit(RLIMIT_FSIZE, &rlim); 4448880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o } 4458880e7599ced6d047626dd45665b765d0f5eded5Theodore Ts'o } 44664e1b274edc48553c76511ff9b30f85c52aff046Theodore Ts'o#endif 4473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *channel = io; 4483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (data) { 452544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o free_cache(data); 453c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&data); 4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 455adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (io) 456c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&io); 4573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 4583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_close(io_channel channel) 4613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 4633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval = 0; 4643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 465f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 467f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 468a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o 469a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o if (--channel->refcount > 0) 470a29f4d30f24d68f1f1c75548e020689ede532c05Theodore Ts'o return 0; 471adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 472b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 473adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = flush_cached_blocks(channel, data, 0); 474b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 475adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 4763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (close(data->dev) < 0) 4773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = errno; 478544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o free_cache(data); 479f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o 480c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&channel->private_data); 4813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->name) 482c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&channel->name); 483c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&channel); 4843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 4853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_set_blksize(io_channel channel, int blksize) 4883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 4907b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 4913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 492f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 494f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 495f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 4963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (channel->block_size != blksize) { 497b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 498adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 0))) 499adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 500b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 501adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 5023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o channel->block_size = blksize; 503544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o free_cache(data); 504adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = alloc_cache(channel, data))) 5057b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 5063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_read_blk(io_channel channel, unsigned long block, 5123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, void *buf) 5133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 51582c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; 5163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 51731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o char *cp; 518adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o int i, j; 5193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 520f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 5213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 522f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 5233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 524b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifdef NO_IO_CACHE 525b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o return raw_read_blk(channel, data, block, count, buf); 526b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#else 5273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 52882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * If we're doing an odd-sized read or a very large read, 52982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o * flush out the cache and then do a direct read. 5303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 53182c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (count < 0 || count > WRITE_DIRECT_SIZE) { 532adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 0))) 533adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 534adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return raw_read_blk(channel, data, block, count, buf); 5353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 536adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 53731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp = buf; 538adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o while (count > 0) { 539adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* If it's in the cache, use it! */ 540544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if ((cache = find_cached_block(data, block, &reuse[0]))) { 541adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o#ifdef DEBUG 542adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o printf("Using cached block %d\n", block); 543f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif 54431dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o memcpy(cp, cache->buf, channel->block_size); 545adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o count--; 546adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o block++; 54731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp += channel->block_size; 548adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o continue; 549adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 550adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* 551adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * Find the number of uncached blocks so we can do a 552adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * single read request 553adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 554adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (i=1; i < count; i++) 555544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o if (find_cached_block(data, block+i, &reuse[i])) 556adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o break; 557adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o#ifdef DEBUG 558adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o printf("Reading %d blocks starting at %d\n", i, block); 559adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o#endif 56031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o if ((retval = raw_read_blk(channel, data, block, i, cp))) 561adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 562adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 563adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* Save the results in the cache */ 564adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o for (j=0; j < i; j++) { 565adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o count--; 56682c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o cache = reuse[j]; 56782c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o reuse_cache(channel, data, cache, block++); 56882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o memcpy(cache->buf, cp, channel->block_size); 56931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp += channel->block_size; 570adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 5713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 573b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif /* NO_IO_CACHE */ 5743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_write_blk(io_channel channel, unsigned long block, 5773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int count, const void *buf) 5783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct unix_private_data *data; 58082c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o struct unix_cache *cache, *reuse; 58123b7c8b88673248b1f93abc717943867ad037bb4Theodore Ts'o errcode_t retval = 0; 58231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o const char *cp; 58331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o int writethrough; 5843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 585f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 5863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o data = (struct unix_private_data *) channel->private_data; 587f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 5883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 589b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifdef NO_IO_CACHE 590b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o return raw_write_blk(channel, data, block, count, buf); 591b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#else 592adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* 593adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * If we're doing an odd-sized write or a very large write, 594adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * flush out the cache completely and then do a direct write. 595adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 59682c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o if (count < 0 || count > WRITE_DIRECT_SIZE) { 597adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 1))) 598adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 599adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return raw_write_blk(channel, data, block, count, buf); 6003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 602adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o /* 603adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * For a moderate-sized multi-block write, first force a write 604adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * if we're in write-through cache mode, and then fill the 605adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o * cache with the blocks. 606adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o */ 607adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; 608adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (writethrough) 609adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = raw_write_blk(channel, data, block, count, buf); 6103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 61131dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp = buf; 612adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o while (count > 0) { 613544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o cache = find_cached_block(data, block, &reuse); 614adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o if (!cache) { 61582c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o cache = reuse; 61682c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o reuse_cache(channel, data, cache, block); 617adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 61882c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o memcpy(cache->buf, cp, channel->block_size); 61982c4660c756fba5eae289e6fbf03fab55393e3e2Theodore Ts'o cache->dirty = !writethrough; 620adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o count--; 621adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o block++; 62231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o cp += channel->block_size; 623adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o } 6243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 625b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif /* NO_IO_CACHE */ 6263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 628c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'ostatic errcode_t unix_write_byte(io_channel channel, unsigned long offset, 629c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o int size, const void *buf) 630c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o{ 631c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o struct unix_private_data *data; 63231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o errcode_t retval = 0; 633544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ssize_t actual; 634c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 635c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 636c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 637c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 638c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 639b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 640c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o /* 641c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * Flush out the cache completely 642c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o */ 643c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if ((retval = flush_cached_blocks(channel, data, 1))) 644c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return retval; 645b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 646c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 647c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if (lseek(data->dev, offset, SEEK_SET) < 0) 648c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return errno; 649c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 650c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o actual = write(data->dev, buf, size); 651c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if (actual != size) 652c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return EXT2_ET_SHORT_WRITE; 653c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 654c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o return 0; 655c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o} 656c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o 6573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 65836f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o * Flush data buffers to disk. 6593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 6603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic errcode_t unix_flush(io_channel channel) 6613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 662f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct unix_private_data *data; 663adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o errcode_t retval = 0; 664f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 665f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 666f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o data = (struct unix_private_data *) channel->private_data; 667f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 668adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o 669b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#ifndef NO_IO_CACHE 670adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o retval = flush_cached_blocks(channel, data, 0); 671b8a953157bce577bff6f9d8437e8d7f2c881fe63Theodore Ts'o#endif 67236f21439f5d8b2233d13e042833d4d921a5c2c40Theodore Ts'o fsync(data->dev); 673adfc8c6c9902c3f08c79a44c1927971175f9d947Theodore Ts'o return retval; 6743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 676