Convert a chunk of usage.h to USE_ and SKIP_ (more to do there), and fix a
[oweals/busybox.git] / e2fsprogs / ext2fs / unix_io.c
1 /*
2  * unix_io.c --- This is the Unix (well, really POSIX) implementation
3  *      of the I/O manager.
4  *
5  * Implements a one-block write-through cache.
6  *
7  * Includes support for Windows NT support under Cygwin.
8  *
9  * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
10  *      2002 by Theodore Ts'o.
11  *
12  * %Begin-Header%
13  * This file may be redistributed under the terms of the GNU Public
14  * License.
15  * %End-Header%
16  */
17
18 #include <stdio.h>
19 #include <string.h>
20 #if HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #if HAVE_ERRNO_H
24 #include <errno.h>
25 #endif
26 #include <fcntl.h>
27 #include <time.h>
28 #ifdef __linux__
29 #include <sys/utsname.h>
30 #endif
31 #if HAVE_SYS_STAT_H
32 #include <sys/stat.h>
33 #endif
34 #if HAVE_SYS_TYPES_H
35 #include <sys/types.h>
36 #endif
37 #if HAVE_SYS_RESOURCE_H
38 #include <sys/resource.h>
39 #endif
40
41 #include "ext2_fs.h"
42 #include "ext2fs.h"
43
44 /*
45  * For checking structure magic numbers...
46  */
47
48 #define EXT2_CHECK_MAGIC(struct, code) \
49           if ((struct)->magic != (code)) return (code)
50
51 struct unix_cache {
52         char            *buf;
53         unsigned long   block;
54         int             access_time;
55         unsigned        dirty:1;
56         unsigned        in_use:1;
57 };
58
59 #define CACHE_SIZE 8
60 #define WRITE_DIRECT_SIZE 4     /* Must be smaller than CACHE_SIZE */
61 #define READ_DIRECT_SIZE 4      /* Should be smaller than CACHE_SIZE */
62
63 struct unix_private_data {
64         int     magic;
65         int     dev;
66         int     flags;
67         int     access_time;
68         ext2_loff_t offset;
69         struct unix_cache cache[CACHE_SIZE];
70 };
71
72 static errcode_t unix_open(const char *name, int flags, io_channel *channel);
73 static errcode_t unix_close(io_channel channel);
74 static errcode_t unix_set_blksize(io_channel channel, int blksize);
75 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
76                                int count, void *data);
77 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
78                                 int count, const void *data);
79 static errcode_t unix_flush(io_channel channel);
80 static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
81                                 int size, const void *data);
82 static errcode_t unix_set_option(io_channel channel, const char *option,
83                                  const char *arg);
84
85 static void reuse_cache(io_channel channel, struct unix_private_data *data,
86                  struct unix_cache *cache, unsigned long block);
87
88 /* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel
89  * does not know buffered block devices - everything is raw. */
90 #if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
91 #define NEED_BOUNCE_BUFFER
92 #else
93 #undef NEED_BOUNCE_BUFFER
94 #endif
95
96 static struct struct_io_manager struct_unix_manager = {
97         EXT2_ET_MAGIC_IO_MANAGER,
98         "Unix I/O Manager",
99         unix_open,
100         unix_close,
101         unix_set_blksize,
102         unix_read_blk,
103         unix_write_blk,
104         unix_flush,
105 #ifdef NEED_BOUNCE_BUFFER
106         0,
107 #else
108         unix_write_byte,
109 #endif
110         unix_set_option
111 };
112
113 io_manager unix_io_manager = &struct_unix_manager;
114
115 /*
116  * Here are the raw I/O functions
117  */
118 #ifndef NEED_BOUNCE_BUFFER
119 static errcode_t raw_read_blk(io_channel channel,
120                               struct unix_private_data *data,
121                               unsigned long block,
122                               int count, void *buf)
123 {
124         errcode_t       retval;
125         ssize_t         size;
126         ext2_loff_t     location;
127         int             actual = 0;
128
129         size = (count < 0) ? -count : count * channel->block_size;
130         location = ((ext2_loff_t) block * channel->block_size) + data->offset;
131         if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
132                 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
133                 goto error_out;
134         }
135         actual = read(data->dev, buf, size);
136         if (actual != size) {
137                 if (actual < 0)
138                         actual = 0;
139                 retval = EXT2_ET_SHORT_READ;
140                 goto error_out;
141         }
142         return 0;
143
144 error_out:
145         memset((char *) buf+actual, 0, size-actual);
146         if (channel->read_error)
147                 retval = (channel->read_error)(channel, block, count, buf,
148                                                size, actual, retval);
149         return retval;
150 }
151 #else /* NEED_BOUNCE_BUFFER */
152 /*
153  * Windows and FreeBSD block devices only allow sector alignment IO in offset and size
154  */
155 static errcode_t raw_read_blk(io_channel channel,
156                               struct unix_private_data *data,
157                               unsigned long block,
158                               int count, void *buf)
159 {
160         errcode_t       retval;
161         size_t          size, alignsize, fragment;
162         ext2_loff_t     location;
163         int             total = 0, actual;
164 #define BLOCKALIGN 512
165         char            sector[BLOCKALIGN];
166
167         size = (count < 0) ? -count : count * channel->block_size;
168         location = ((ext2_loff_t) block * channel->block_size) + data->offset;
169 #ifdef DEBUG
170         printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n",
171                         count, size, block, channel->block_size, location);
172 #endif
173         if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
174                 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
175                 goto error_out;
176         }
177         fragment = size % BLOCKALIGN;
178         alignsize = size - fragment;
179         if (alignsize) {
180                 actual = read(data->dev, buf, alignsize);
181                 if (actual != alignsize)
182                         goto short_read;
183         }
184         if (fragment) {
185                 actual = read(data->dev, sector, BLOCKALIGN);
186                 if (actual != BLOCKALIGN)
187                         goto short_read;
188                 memcpy(buf+alignsize, sector, fragment);
189         }
190         return 0;
191
192 short_read:
193         if (actual>0)
194                 total += actual;
195         retval = EXT2_ET_SHORT_READ;
196
197 error_out:
198         memset((char *) buf+total, 0, size-actual);
199         if (channel->read_error)
200                 retval = (channel->read_error)(channel, block, count, buf,
201                                                size, actual, retval);
202         return retval;
203 }
204 #endif
205
206 static errcode_t raw_write_blk(io_channel channel,
207                                struct unix_private_data *data,
208                                unsigned long block,
209                                int count, const void *buf)
210 {
211         ssize_t         size;
212         ext2_loff_t     location;
213         int             actual = 0;
214         errcode_t       retval;
215
216         if (count == 1)
217                 size = channel->block_size;
218         else {
219                 if (count < 0)
220                         size = -count;
221                 else
222                         size = count * channel->block_size;
223         }
224
225         location = ((ext2_loff_t) block * channel->block_size) + data->offset;
226         if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
227                 retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
228                 goto error_out;
229         }
230
231         actual = write(data->dev, buf, size);
232         if (actual != size) {
233                 retval = EXT2_ET_SHORT_WRITE;
234                 goto error_out;
235         }
236         return 0;
237
238 error_out:
239         if (channel->write_error)
240                 retval = (channel->write_error)(channel, block, count, buf,
241                                                 size, actual, retval);
242         return retval;
243 }
244
245
246 /*
247  * Here we implement the cache functions
248  */
249
250 /* Allocate the cache buffers */
251 static errcode_t alloc_cache(io_channel channel,
252                              struct unix_private_data *data)
253 {
254         errcode_t               retval;
255         struct unix_cache       *cache;
256         int                     i;
257
258         data->access_time = 0;
259         for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
260                 cache->block = 0;
261                 cache->access_time = 0;
262                 cache->dirty = 0;
263                 cache->in_use = 0;
264                 if ((retval = ext2fs_get_mem(channel->block_size,
265                                              &cache->buf)))
266                         return retval;
267         }
268         return 0;
269 }
270
271 /* Free the cache buffers */
272 static void free_cache(struct unix_private_data *data)
273 {
274         struct unix_cache       *cache;
275         int                     i;
276
277         data->access_time = 0;
278         for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
279                 cache->block = 0;
280                 cache->access_time = 0;
281                 cache->dirty = 0;
282                 cache->in_use = 0;
283                 ext2fs_free_mem(&cache->buf);
284                 cache->buf = 0;
285         }
286 }
287
288 #ifndef NO_IO_CACHE
289 /*
290  * Try to find a block in the cache.  If the block is not found, and
291  * eldest is a non-zero pointer, then fill in eldest with the cache
292  * entry to that should be reused.
293  */
294 static struct unix_cache *find_cached_block(struct unix_private_data *data,
295                                             unsigned long block,
296                                             struct unix_cache **eldest)
297 {
298         struct unix_cache       *cache, *unused_cache, *oldest_cache;
299         int                     i;
300
301         unused_cache = oldest_cache = 0;
302         for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
303                 if (!cache->in_use) {
304                         if (!unused_cache)
305                                 unused_cache = cache;
306                         continue;
307                 }
308                 if (cache->block == block) {
309                         cache->access_time = ++data->access_time;
310                         return cache;
311                 }
312                 if (!oldest_cache ||
313                     (cache->access_time < oldest_cache->access_time))
314                         oldest_cache = cache;
315         }
316         if (eldest)
317                 *eldest = (unused_cache) ? unused_cache : oldest_cache;
318         return 0;
319 }
320
321 /*
322  * Reuse a particular cache entry for another block.
323  */
324 static void reuse_cache(io_channel channel, struct unix_private_data *data,
325                  struct unix_cache *cache, unsigned long block)
326 {
327         if (cache->dirty && cache->in_use)
328                 raw_write_blk(channel, data, cache->block, 1, cache->buf);
329
330         cache->in_use = 1;
331         cache->dirty = 0;
332         cache->block = block;
333         cache->access_time = ++data->access_time;
334 }
335
336 /*
337  * Flush all of the blocks in the cache
338  */
339 static errcode_t flush_cached_blocks(io_channel channel,
340                                      struct unix_private_data *data,
341                                      int invalidate)
342
343 {
344         struct unix_cache       *cache;
345         errcode_t               retval, retval2;
346         int                     i;
347
348         retval2 = 0;
349         for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) {
350                 if (!cache->in_use)
351                         continue;
352
353                 if (invalidate)
354                         cache->in_use = 0;
355
356                 if (!cache->dirty)
357                         continue;
358
359                 retval = raw_write_blk(channel, data,
360                                        cache->block, 1, cache->buf);
361                 if (retval)
362                         retval2 = retval;
363                 else
364                         cache->dirty = 0;
365         }
366         return retval2;
367 }
368 #endif /* NO_IO_CACHE */
369
370 static errcode_t unix_open(const char *name, int flags, io_channel *channel)
371 {
372         io_channel      io = NULL;
373         struct unix_private_data *data = NULL;
374         errcode_t       retval;
375         int             open_flags;
376         struct stat     st;
377 #ifdef __linux__
378         struct          utsname ut;
379 #endif
380
381         if (name == 0)
382                 return EXT2_ET_BAD_DEVICE_NAME;
383         retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
384         if (retval)
385                 return retval;
386         memset(io, 0, sizeof(struct struct_io_channel));
387         io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
388         retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data);
389         if (retval)
390                 goto cleanup;
391
392         io->manager = unix_io_manager;
393         retval = ext2fs_get_mem(strlen(name)+1, &io->name);
394         if (retval)
395                 goto cleanup;
396
397         strcpy(io->name, name);
398         io->private_data = data;
399         io->block_size = 1024;
400         io->read_error = 0;
401         io->write_error = 0;
402         io->refcount = 1;
403
404         memset(data, 0, sizeof(struct unix_private_data));
405         data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
406
407         if ((retval = alloc_cache(io, data)))
408                 goto cleanup;
409
410         open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
411 #ifdef CONFIG_LFS
412         data->dev = open64(io->name, open_flags);
413 #else
414         data->dev = open(io->name, open_flags);
415 #endif
416         if (data->dev < 0) {
417                 retval = errno;
418                 goto cleanup;
419         }
420
421 #ifdef __linux__
422 #undef RLIM_INFINITY
423 #if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4)))
424 #define RLIM_INFINITY   ((unsigned long)(~0UL>>1))
425 #else
426 #define RLIM_INFINITY  (~0UL)
427 #endif
428         /*
429          * Work around a bug in 2.4.10-2.4.18 kernels where writes to
430          * block devices are wrongly getting hit by the filesize
431          * limit.  This workaround isn't perfect, since it won't work
432          * if glibc wasn't built against 2.2 header files.  (Sigh.)
433          *
434          */
435         if ((flags & IO_FLAG_RW) &&
436             (uname(&ut) == 0) &&
437             ((ut.release[0] == '2') && (ut.release[1] == '.') &&
438              (ut.release[2] == '4') && (ut.release[3] == '.') &&
439              (ut.release[4] == '1') && (ut.release[5] >= '0') &&
440              (ut.release[5] < '8')) &&
441             (fstat(data->dev, &st) == 0) &&
442             (S_ISBLK(st.st_mode))) {
443                 struct rlimit   rlim;
444
445                 rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
446                 setrlimit(RLIMIT_FSIZE, &rlim);
447                 getrlimit(RLIMIT_FSIZE, &rlim);
448                 if (((unsigned long) rlim.rlim_cur) <
449                     ((unsigned long) rlim.rlim_max)) {
450                         rlim.rlim_cur = rlim.rlim_max;
451                         setrlimit(RLIMIT_FSIZE, &rlim);
452                 }
453         }
454 #endif
455         *channel = io;
456         return 0;
457
458 cleanup:
459         if (data) {
460                 free_cache(data);
461                 ext2fs_free_mem(&data);
462         }
463         ext2fs_free_mem(&io);
464         return retval;
465 }
466
467 static errcode_t unix_close(io_channel channel)
468 {
469         struct unix_private_data *data;
470         errcode_t       retval = 0;
471
472         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
473         data = (struct unix_private_data *) channel->private_data;
474         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
475
476         if (--channel->refcount > 0)
477                 return 0;
478
479 #ifndef NO_IO_CACHE
480         retval = flush_cached_blocks(channel, data, 0);
481 #endif
482
483         if (close(data->dev) < 0)
484                 retval = errno;
485         free_cache(data);
486
487         ext2fs_free_mem(&channel->private_data);
488         ext2fs_free_mem(&channel->name);
489         ext2fs_free_mem(&channel);
490         return retval;
491 }
492
493 static errcode_t unix_set_blksize(io_channel channel, int blksize)
494 {
495         struct unix_private_data *data;
496         errcode_t               retval;
497
498         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
499         data = (struct unix_private_data *) channel->private_data;
500         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
501
502         if (channel->block_size != blksize) {
503 #ifndef NO_IO_CACHE
504                 if ((retval = flush_cached_blocks(channel, data, 0)))
505                         return retval;
506 #endif
507
508                 channel->block_size = blksize;
509                 free_cache(data);
510                 if ((retval = alloc_cache(channel, data)))
511                         return retval;
512         }
513         return 0;
514 }
515
516
517 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
518                                int count, void *buf)
519 {
520         struct unix_private_data *data;
521         struct unix_cache *cache, *reuse[READ_DIRECT_SIZE];
522         errcode_t       retval;
523         char            *cp;
524         int             i, j;
525
526         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
527         data = (struct unix_private_data *) channel->private_data;
528         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
529
530 #ifdef NO_IO_CACHE
531         return raw_read_blk(channel, data, block, count, buf);
532 #else
533         /*
534          * If we're doing an odd-sized read or a very large read,
535          * flush out the cache and then do a direct read.
536          */
537         if (count < 0 || count > WRITE_DIRECT_SIZE) {
538                 if ((retval = flush_cached_blocks(channel, data, 0)))
539                         return retval;
540                 return raw_read_blk(channel, data, block, count, buf);
541         }
542
543         cp = buf;
544         while (count > 0) {
545                 /* If it's in the cache, use it! */
546                 if ((cache = find_cached_block(data, block, &reuse[0]))) {
547 #ifdef DEBUG
548                         printf("Using cached block %d\n", block);
549 #endif
550                         memcpy(cp, cache->buf, channel->block_size);
551                         count--;
552                         block++;
553                         cp += channel->block_size;
554                         continue;
555                 }
556                 /*
557                  * Find the number of uncached blocks so we can do a
558                  * single read request
559                  */
560                 for (i=1; i < count; i++)
561                         if (find_cached_block(data, block+i, &reuse[i]))
562                                 break;
563 #ifdef DEBUG
564                 printf("Reading %d blocks starting at %d\n", i, block);
565 #endif
566                 if ((retval = raw_read_blk(channel, data, block, i, cp)))
567                         return retval;
568
569                 /* Save the results in the cache */
570                 for (j=0; j < i; j++) {
571                         count--;
572                         cache = reuse[j];
573                         reuse_cache(channel, data, cache, block++);
574                         memcpy(cache->buf, cp, channel->block_size);
575                         cp += channel->block_size;
576                 }
577         }
578         return 0;
579 #endif /* NO_IO_CACHE */
580 }
581
582 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
583                                 int count, const void *buf)
584 {
585         struct unix_private_data *data;
586         struct unix_cache *cache, *reuse;
587         errcode_t       retval = 0;
588         const char      *cp;
589         int             writethrough;
590
591         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
592         data = (struct unix_private_data *) channel->private_data;
593         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
594
595 #ifdef NO_IO_CACHE
596         return raw_write_blk(channel, data, block, count, buf);
597 #else
598         /*
599          * If we're doing an odd-sized write or a very large write,
600          * flush out the cache completely and then do a direct write.
601          */
602         if (count < 0 || count > WRITE_DIRECT_SIZE) {
603                 if ((retval = flush_cached_blocks(channel, data, 1)))
604                         return retval;
605                 return raw_write_blk(channel, data, block, count, buf);
606         }
607
608         /*
609          * For a moderate-sized multi-block write, first force a write
610          * if we're in write-through cache mode, and then fill the
611          * cache with the blocks.
612          */
613         writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH;
614         if (writethrough)
615                 retval = raw_write_blk(channel, data, block, count, buf);
616
617         cp = buf;
618         while (count > 0) {
619                 cache = find_cached_block(data, block, &reuse);
620                 if (!cache) {
621                         cache = reuse;
622                         reuse_cache(channel, data, cache, block);
623                 }
624                 memcpy(cache->buf, cp, channel->block_size);
625                 cache->dirty = !writethrough;
626                 count--;
627                 block++;
628                 cp += channel->block_size;
629         }
630         return retval;
631 #endif /* NO_IO_CACHE */
632 }
633
634 static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
635                                  int size, const void *buf)
636 {
637         struct unix_private_data *data;
638         errcode_t       retval = 0;
639         ssize_t         actual;
640
641         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
642         data = (struct unix_private_data *) channel->private_data;
643         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
644
645 #ifndef NO_IO_CACHE
646         /*
647          * Flush out the cache completely
648          */
649         if ((retval = flush_cached_blocks(channel, data, 1)))
650                 return retval;
651 #endif
652
653         if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0)
654                 return errno;
655
656         actual = write(data->dev, buf, size);
657         if (actual != size)
658                 return EXT2_ET_SHORT_WRITE;
659
660         return 0;
661 }
662
663 /*
664  * Flush data buffers to disk.
665  */
666 static errcode_t unix_flush(io_channel channel)
667 {
668         struct unix_private_data *data;
669         errcode_t retval = 0;
670
671         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
672         data = (struct unix_private_data *) channel->private_data;
673         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
674
675 #ifndef NO_IO_CACHE
676         retval = flush_cached_blocks(channel, data, 0);
677 #endif
678         fsync(data->dev);
679         return retval;
680 }
681
682 static errcode_t unix_set_option(io_channel channel, const char *option,
683                                  const char *arg)
684 {
685         struct unix_private_data *data;
686         unsigned long tmp;
687         char *end;
688
689         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
690         data = (struct unix_private_data *) channel->private_data;
691         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
692
693         if (!strcmp(option, "offset")) {
694                 if (!arg)
695                         return EXT2_ET_INVALID_ARGUMENT;
696
697                 tmp = strtoul(arg, &end, 0);
698                 if (*end)
699                         return EXT2_ET_INVALID_ARGUMENT;
700                 data->offset = tmp;
701                 return 0;
702         }
703         return EXT2_ET_INVALID_ARGUMENT;
704 }