2 * unix_io.c --- This is the Unix I/O interface to the I/O manager.
4 * Implements a one-block write-through cache.
6 * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
7 * 2002 by Theodore Ts'o.
10 * This file may be redistributed under the terms of the GNU Public
15 #define _LARGEFILE_SOURCE
16 #define _LARGEFILE64_SOURCE
29 #include <sys/utsname.h>
35 #include <sys/types.h>
37 #include <sys/resource.h>
43 * For checking structure magic numbers...
46 #define EXT2_CHECK_MAGIC(struct, code) \
47 if ((struct)->magic != (code)) return (code)
58 #define WRITE_VIA_CACHE_SIZE 4 /* Must be smaller than CACHE_SIZE */
60 struct unix_private_data {
65 struct unix_cache cache[CACHE_SIZE];
68 static errcode_t unix_open(const char *name, int flags, io_channel *channel);
69 static errcode_t unix_close(io_channel channel);
70 static errcode_t unix_set_blksize(io_channel channel, int blksize);
71 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
72 int count, void *data);
73 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
74 int count, const void *data);
75 static errcode_t unix_flush(io_channel channel);
76 static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
77 int size, const void *data);
79 static struct struct_io_manager struct_unix_manager = {
80 EXT2_ET_MAGIC_IO_MANAGER,
91 io_manager unix_io_manager = &struct_unix_manager;
94 * Here are the raw I/O functions
96 static errcode_t raw_read_blk(io_channel channel,
97 struct unix_private_data *data,
103 ext2_loff_t location;
106 size = (count < 0) ? -count : count * channel->block_size;
107 location = (ext2_loff_t) block * channel->block_size;
108 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
109 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
112 actual = read(data->dev, buf, size);
113 if (actual != size) {
116 retval = EXT2_ET_SHORT_READ;
122 memset((char *) buf+actual, 0, size-actual);
123 if (channel->read_error)
124 retval = (channel->read_error)(channel, block, count, buf,
125 size, actual, retval);
129 static errcode_t raw_write_blk(io_channel channel,
130 struct unix_private_data *data,
132 int count, const void *buf)
135 ext2_loff_t location;
140 size = channel->block_size;
145 size = count * channel->block_size;
148 location = (ext2_loff_t) block * channel->block_size;
149 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
150 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
154 actual = write(data->dev, buf, size);
155 if (actual != size) {
156 retval = EXT2_ET_SHORT_WRITE;
162 if (channel->write_error)
163 retval = (channel->write_error)(channel, block, count, buf,
164 size, actual, retval);
170 * Here we implement the cache functions
173 /* Allocate the cache buffers */
174 static errcode_t alloc_cache(io_channel channel,
175 struct unix_private_data *data)
178 struct unix_cache *cache;
181 data->access_time = 0;
182 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
184 cache->access_time = 0;
187 if ((retval = ext2fs_get_mem(channel->block_size,
188 (void **) &cache->buf)))
194 /* Free the cache buffers */
195 static void free_cache(io_channel channel,
196 struct unix_private_data *data)
198 struct unix_cache *cache;
201 data->access_time = 0;
202 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
204 cache->access_time = 0;
208 ext2fs_free_mem((void **) &cache->buf);
214 * Try to find a block in the cache. If get_cache is non-zero, then
215 * if the block isn't in the cache, evict the oldest block in the
216 * cache and create a new cache entry for the requested block.
218 static struct unix_cache *find_cached_block(io_channel channel,
219 struct unix_private_data *data,
223 struct unix_cache *cache, *unused_cache, *oldest_cache;
226 unused_cache = oldest_cache = 0;
227 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
228 if (!cache->in_use) {
229 unused_cache = cache;
232 if (cache->block == block) {
233 cache->access_time = ++data->access_time;
237 (cache->access_time < oldest_cache->access_time))
238 oldest_cache = cache;
244 * Try to allocate cache slot.
247 cache = unused_cache;
249 cache = oldest_cache;
251 raw_write_blk(channel, data,
252 cache->block, 1, cache->buf);
255 cache->block = block;
256 cache->access_time = ++data->access_time;
261 * Flush all of the blocks in the cache
263 static errcode_t flush_cached_blocks(io_channel channel,
264 struct unix_private_data *data,
268 struct unix_cache *cache;
269 errcode_t retval, retval2;
273 for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
283 retval = raw_write_blk(channel, data,
284 cache->block, 1, cache->buf);
295 static errcode_t unix_open(const char *name, int flags, io_channel *channel)
297 io_channel io = NULL;
298 struct unix_private_data *data = NULL;
307 return EXT2_ET_BAD_DEVICE_NAME;
308 retval = ext2fs_get_mem(sizeof(struct struct_io_channel),
312 memset(io, 0, sizeof(struct struct_io_channel));
313 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
314 retval = ext2fs_get_mem(sizeof(struct unix_private_data),
319 io->manager = unix_io_manager;
320 retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name);
324 strcpy(io->name, name);
325 io->private_data = data;
326 io->block_size = 1024;
331 memset(data, 0, sizeof(struct unix_private_data));
332 data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
334 if ((retval = alloc_cache(io, data)))
337 open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
339 data->dev = open64(name, open_flags);
341 data->dev = open(name, open_flags);
350 #if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4)))
351 #define RLIM_INFINITY ((unsigned long)(~0UL>>1))
353 #define RLIM_INFINITY (~0UL)
356 * Work around a bug in 2.4.10-2.4.18 kernels where writes to
357 * block devices are wrongly getting hit by the filesize
358 * limit. This workaround isn't perfect, since it won't work
359 * if glibc wasn't built against 2.2 header files. (Sigh.)
362 if ((flags & IO_FLAG_RW) &&
364 ((ut.release[0] == '2') && (ut.release[1] == '.') &&
365 (ut.release[2] == '4') && (ut.release[3] == '.') &&
366 (ut.release[4] == '1') && (ut.release[5] >= '0') &&
367 (ut.release[5] < '8')) &&
368 (fstat(data->dev, &st) == 0) &&
369 (S_ISBLK(st.st_mode))) {
372 rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
373 setrlimit(RLIMIT_FSIZE, &rlim);
374 getrlimit(RLIMIT_FSIZE, &rlim);
375 if (((unsigned long) rlim.rlim_cur) <
376 ((unsigned long) rlim.rlim_max)) {
377 rlim.rlim_cur = rlim.rlim_max;
378 setrlimit(RLIMIT_FSIZE, &rlim);
387 free_cache(io, data);
388 ext2fs_free_mem((void **) &data);
391 ext2fs_free_mem((void **) &io);
395 static errcode_t unix_close(io_channel channel)
397 struct unix_private_data *data;
398 errcode_t retval = 0;
400 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
401 data = (struct unix_private_data *) channel->private_data;
402 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
404 if (--channel->refcount > 0)
407 retval = flush_cached_blocks(channel, data, 0);
409 if (close(data->dev) < 0)
411 free_cache(channel, data);
413 ext2fs_free_mem((void **) &channel->private_data);
415 ext2fs_free_mem((void **) &channel->name);
416 ext2fs_free_mem((void **) &channel);
420 static errcode_t unix_set_blksize(io_channel channel, int blksize)
422 struct unix_private_data *data;
425 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
426 data = (struct unix_private_data *) channel->private_data;
427 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
429 if (channel->block_size != blksize) {
430 if ((retval = flush_cached_blocks(channel, data, 0)))
433 channel->block_size = blksize;
434 free_cache(channel, data);
435 if ((retval = alloc_cache(channel, data)))
442 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
443 int count, void *buf)
445 struct unix_private_data *data;
446 struct unix_cache *cache;
451 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
452 data = (struct unix_private_data *) channel->private_data;
453 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
456 * If we're doing an odd-sized read, flush out the cache and
457 * then do a direct read.
460 if ((retval = flush_cached_blocks(channel, data, 0)))
462 return raw_read_blk(channel, data, block, count, buf);
467 /* If it's in the cache, use it! */
468 if ((cache = find_cached_block(channel, data, block, 0))) {
470 printf("Using cached block %d\n", block);
472 memcpy(cp, cache->buf, channel->block_size);
475 cp += channel->block_size;
479 * Find the number of uncached blocks so we can do a
480 * single read request
482 for (i=1; i < count; i++)
483 if (find_cached_block(channel, data, block+i, 0))
486 printf("Reading %d blocks starting at %d\n", i, block);
488 if ((retval = raw_read_blk(channel, data, block, i, cp)))
491 /* Save the results in the cache */
492 for (j=0; j < i; j++) {
494 cache = find_cached_block(channel, data, block++, 1);
496 memcpy(cache->buf, cp, channel->block_size);
497 cp += channel->block_size;
503 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
504 int count, const void *buf)
506 struct unix_private_data *data;
507 struct unix_cache *cache;
508 errcode_t retval = 0, retval2;
512 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
513 data = (struct unix_private_data *) channel->private_data;
514 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
517 * If we're doing an odd-sized write or a very large write,
518 * flush out the cache completely and then do a direct write.
520 if (count < 0 || count > WRITE_VIA_CACHE_SIZE) {
521 if ((retval = flush_cached_blocks(channel, data, 1)))
523 return raw_write_blk(channel, data, block, count, buf);
527 * For a moderate-sized multi-block write, first force a write
528 * if we're in write-through cache mode, and then fill the
529 * cache with the blocks.
531 writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
533 retval = raw_write_blk(channel, data, block, count, buf);
537 cache = find_cached_block(channel, data, block, 1);
540 * Oh shit, we couldn't get cache descriptor.
541 * Force the write directly.
543 if ((retval2 = raw_write_blk(channel, data, block,
547 memcpy(cache->buf, cp, channel->block_size);
548 cache->dirty = !writethrough;
552 cp += channel->block_size;
557 static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
558 int size, const void *buf)
560 struct unix_private_data *data;
561 errcode_t retval = 0;
564 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
565 data = (struct unix_private_data *) channel->private_data;
566 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
569 * Flush out the cache completely
571 if ((retval = flush_cached_blocks(channel, data, 1)))
574 if (lseek(data->dev, offset, SEEK_SET) < 0)
577 actual = write(data->dev, buf, size);
579 return EXT2_ET_SHORT_WRITE;
585 * Flush data buffers to disk.
587 static errcode_t unix_flush(io_channel channel)
589 struct unix_private_data *data;
590 errcode_t retval = 0;
592 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
593 data = (struct unix_private_data *) channel->private_data;
594 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
596 retval = flush_cached_blocks(channel, data, 0);