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 Theodore Ts'o.
9 * This file may be redistributed under the terms of the GNU Public
28 #include <sys/types.h>
31 #if EXT2_FLAT_INCLUDES
34 #include <linux/ext2_fs.h>
40 * For checking structure magic numbers...
43 #define EXT2_CHECK_MAGIC(struct, code) \
44 if ((struct)->magic != (code)) return (code)
46 struct unix_private_data {
54 static errcode_t unix_open(const char *name, int flags, io_channel *channel);
55 static errcode_t unix_close(io_channel channel);
56 static errcode_t unix_set_blksize(io_channel channel, int blksize);
57 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
58 int count, void *data);
59 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
60 int count, const void *data);
61 static errcode_t unix_flush(io_channel channel);
63 static struct struct_io_manager struct_unix_manager = {
64 EXT2_ET_MAGIC_IO_MANAGER,
74 io_manager unix_io_manager = &struct_unix_manager;
76 static errcode_t unix_open(const char *name, int flags, io_channel *channel)
79 struct unix_private_data *data = NULL;
83 return EXT2_ET_BAD_DEVICE_NAME;
84 retval = ext2fs_get_mem(sizeof(struct struct_io_channel),
88 memset(io, 0, sizeof(struct struct_io_channel));
89 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
90 retval = ext2fs_get_mem(sizeof(struct unix_private_data),
95 io->manager = unix_io_manager;
96 retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name);
100 strcpy(io->name, name);
101 io->private_data = data;
102 io->block_size = 1024;
107 memset(data, 0, sizeof(struct unix_private_data));
108 data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
109 retval = ext2fs_get_mem(io->block_size, (void **) &data->buf);
110 data->buf_block_nr = -1;
114 data->dev = open(name, (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY);
124 ext2fs_free_mem((void **) &io);
127 ext2fs_free_mem((void **) &data->buf);
128 ext2fs_free_mem((void **) &data);
133 static errcode_t unix_close(io_channel channel)
135 struct unix_private_data *data;
136 errcode_t retval = 0;
138 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
139 data = (struct unix_private_data *) channel->private_data;
140 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
142 if (--channel->refcount > 0)
145 if (close(data->dev) < 0)
148 ext2fs_free_mem((void **) &data->buf);
149 if (channel->private_data)
150 ext2fs_free_mem((void **) &channel->private_data);
152 ext2fs_free_mem((void **) &channel->name);
153 ext2fs_free_mem((void **) &channel);
157 static errcode_t unix_set_blksize(io_channel channel, int blksize)
159 struct unix_private_data *data;
162 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
163 data = (struct unix_private_data *) channel->private_data;
164 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
166 if (channel->block_size != blksize) {
167 channel->block_size = blksize;
168 ext2fs_free_mem((void **) &data->buf);
169 retval = ext2fs_get_mem(blksize, (void **) &data->buf);
172 data->buf_block_nr = -1;
178 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
179 int count, void *buf)
181 struct unix_private_data *data;
184 ext2_loff_t location;
187 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
188 data = (struct unix_private_data *) channel->private_data;
189 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
192 * If it's in the cache, use it!
194 if ((count == 1) && (block == data->buf_block_nr)) {
195 memcpy(buf, data->buf, channel->block_size);
199 printf("read_block %lu (%d)\n", block, count);
201 size = (count < 0) ? -count : count * channel->block_size;
202 location = (ext2_loff_t) block * channel->block_size;
203 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
204 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
207 actual = read(data->dev, buf, size);
208 if (actual != size) {
211 retval = EXT2_ET_SHORT_READ;
215 data->buf_block_nr = block;
216 memcpy(data->buf, buf, size); /* Update the cache */
221 memset((char *) buf+actual, 0, size-actual);
222 if (channel->read_error)
223 retval = (channel->read_error)(channel, block, count, buf,
224 size, actual, retval);
228 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
229 int count, const void *buf)
231 struct unix_private_data *data;
233 ext2_loff_t location;
237 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
238 data = (struct unix_private_data *) channel->private_data;
239 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
242 size = channel->block_size;
244 data->buf_block_nr = -1; /* Invalidate the cache */
248 size = count * channel->block_size;
251 location = (ext2_loff_t) block * channel->block_size;
252 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
253 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
257 actual = write(data->dev, buf, size);
258 if (actual != size) {
259 retval = EXT2_ET_SHORT_WRITE;
263 if ((count == 1) && (block == data->buf_block_nr))
264 memcpy(data->buf, buf, size); /* Update the cache */
269 if (channel->write_error)
270 retval = (channel->write_error)(channel, block, count, buf,
271 size, actual, retval);
276 * Flush data buffers to disk.
278 static errcode_t unix_flush(io_channel channel)
280 struct unix_private_data *data;
282 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
283 data = (struct unix_private_data *) channel->private_data;
284 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);