sem.c: cleanup
[fio.git] / filesetup.c
1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <dirent.h>
6 #include <sys/stat.h>
7 #include <sys/mman.h>
8 #include <sys/types.h>
9
10 #include "fio.h"
11 #include "smalloc.h"
12 #include "filehash.h"
13
14 static int root_warn;
15
16 static int extend_file(struct thread_data *td, struct fio_file *f)
17 {
18         int r, new_layout = 0, unlink_file = 0, flags;
19         unsigned long long left;
20         unsigned int bs;
21         char *b;
22
23         if (read_only) {
24                 log_err("fio: refusing extend of file due to read-only\n");
25                 return 0;
26         }
27
28         /*
29          * check if we need to lay the file out complete again. fio
30          * does that for operations involving reads, or for writes
31          * where overwrite is set
32          */
33         if (td_read(td) || (td_write(td) && td->o.overwrite))
34                 new_layout = 1;
35         if (td_write(td) && !td->o.overwrite)
36                 unlink_file = 1;
37
38         if (unlink_file || new_layout) {
39                 if ((unlink(f->file_name) < 0) && (errno != ENOENT)) {
40                         td_verror(td, errno, "unlink");
41                         return 1;
42                 }
43         }
44
45         flags = O_WRONLY | O_CREAT;
46         if (new_layout)
47                 flags |= O_TRUNC;
48
49         dprint(FD_FILE, "open file %s, flags %x\n", f->file_name, flags);
50         f->fd = open(f->file_name, flags, 0644);
51         if (f->fd < 0) {
52                 td_verror(td, errno, "open");
53                 return 1;
54         }
55
56         if (!new_layout)
57                 goto done;
58
59         dprint(FD_FILE, "truncate file %s, size %llu\n", f->file_name,
60                                                         f->real_file_size);
61         if (ftruncate(f->fd, f->real_file_size) == -1) {
62                 td_verror(td, errno, "ftruncate");
63                 goto err;
64         }
65
66         dprint(FD_FILE, "fallocate file %s, size %llu\n", f->file_name,
67                                                         f->real_file_size);
68         if (posix_fallocate(f->fd, 0, f->real_file_size) < 0) {
69                 td_verror(td, errno, "posix_fallocate");
70                 goto err;
71         }
72
73         b = malloc(td->o.max_bs[DDIR_WRITE]);
74         memset(b, 0, td->o.max_bs[DDIR_WRITE]);
75
76         left = f->real_file_size;
77         while (left && !td->terminate) {
78                 bs = td->o.max_bs[DDIR_WRITE];
79                 if (bs > left)
80                         bs = left;
81
82                 r = write(f->fd, b, bs);
83
84                 if (r == (int) bs) {
85                         left -= bs;
86                         continue;
87                 } else {
88                         if (r < 0)
89                                 td_verror(td, errno, "write");
90                         else
91                                 td_verror(td, EIO, "write");
92
93                         break;
94                 }
95         }
96
97         if (td->terminate)
98                 unlink(f->file_name);
99         else if (td->o.create_fsync)
100                 fsync(f->fd);
101
102         free(b);
103 done:
104         close(f->fd);
105         f->fd = -1;
106         return 0;
107 err:
108         close(f->fd);
109         f->fd = -1;
110         return 1;
111 }
112
113 static unsigned long long get_rand_file_size(struct thread_data *td)
114 {
115         unsigned long long ret;
116         long r;
117
118         r = os_random_long(&td->file_size_state);
119         ret = td->o.file_size_low + (unsigned long long) ((double) (td->o.file_size_high - td->o.file_size_low) * (r / (RAND_MAX + 1.0)));
120         ret -= (ret % td->o.rw_min_bs);
121         return ret;
122 }
123
124 static int file_size(struct thread_data *td, struct fio_file *f)
125 {
126         struct stat st;
127
128         if (fstat(f->fd, &st) == -1) {
129                 td_verror(td, errno, "fstat");
130                 return 1;
131         }
132
133         f->real_file_size = st.st_size;
134         return 0;
135 }
136
137 static int bdev_size(struct thread_data *td, struct fio_file *f)
138 {
139         unsigned long long bytes;
140         int r;
141
142         r = blockdev_size(f->fd, &bytes);
143         if (r) {
144                 td_verror(td, r, "blockdev_size");
145                 return 1;
146         }
147
148         f->real_file_size = bytes;
149         return 0;
150 }
151
152 static int get_file_size(struct thread_data *td, struct fio_file *f)
153 {
154         int ret = 0;
155
156         if (f->flags & FIO_SIZE_KNOWN)
157                 return 0;
158
159         if (f->filetype == FIO_TYPE_FILE)
160                 ret = file_size(td, f);
161         else if (f->filetype == FIO_TYPE_BD)
162                 ret = bdev_size(td, f);
163         else
164                 f->real_file_size = -1;
165
166         if (ret)
167                 return ret;
168
169         if (f->file_offset > f->real_file_size) {
170                 log_err("%s: offset extends end (%Lu > %Lu)\n", td->o.name, f->file_offset, f->real_file_size);
171                 return 1;
172         }
173
174         f->flags |= FIO_SIZE_KNOWN;
175         return 0;
176 }
177
178 int file_invalidate_cache(struct thread_data *td, struct fio_file *f)
179 {
180         int ret = 0;
181
182         dprint(FD_IO, "invalidate cache (%d)\n", td->o.odirect);
183
184         if (td->o.odirect)
185                 return 0;
186
187         /*
188          * FIXME: add blockdev flushing too
189          */
190         if (f->mmap)
191                 ret = madvise(f->mmap, f->io_size, MADV_DONTNEED);
192         else if (f->filetype == FIO_TYPE_FILE)
193                 ret = fadvise(f->fd, f->file_offset, f->io_size, POSIX_FADV_DONTNEED);
194         else if (f->filetype == FIO_TYPE_BD) {
195                 ret = blockdev_invalidate_cache(f->fd);
196                 if (ret < 0 && errno == EACCES && geteuid()) {
197                         if (!root_warn) {
198                                 log_err("fio: only root may flush block devices. Cache flush bypassed!\n");
199                                 root_warn = 1;
200                         }
201                         ret = 0;
202                 }
203         } else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE)
204                 ret = 0;
205
206         if (ret < 0) {
207                 td_verror(td, errno, "invalidate_cache");
208                 return 1;
209         }
210
211         return ret;
212 }
213
214 int generic_close_file(struct thread_data fio_unused *td, struct fio_file *f)
215 {
216         int ret = 0;
217
218         dprint(FD_FILE, "fd close %s\n", f->file_name);
219
220         remove_file_hash(f);
221
222         if (close(f->fd) < 0)
223                 ret = errno;
224
225         f->fd = -1;
226         return ret;
227 }
228
229 int generic_open_file(struct thread_data *td, struct fio_file *f)
230 {
231         struct fio_file *__f;
232         int is_std = 0;
233         int flags = 0;
234         int from_hash = 0;
235
236         dprint(FD_FILE, "fd open %s\n", f->file_name);
237
238         if (!strcmp(f->file_name, "-")) {
239                 if (td_rw(td)) {
240                         log_err("fio: can't read/write to stdin/out\n");
241                         return 1;
242                 }
243                 is_std = 1;
244
245                 /*
246                  * move output logging to stderr, if we are writing to stdout
247                  */
248                 if (td_write(td))
249                         f_out = stderr;
250         }
251
252         if (td->o.odirect)
253                 flags |= OS_O_DIRECT;
254         if (td->o.sync_io)
255                 flags |= O_SYNC;
256         if (f->filetype != FIO_TYPE_FILE)
257                 flags |= O_NOATIME;
258
259 open_again:
260         if (td_write(td)) {
261                 assert(!read_only);
262
263                 flags |= O_RDWR;
264
265                 if (f->filetype == FIO_TYPE_FILE)
266                         flags |= O_CREAT;
267
268                 if (is_std)
269                         f->fd = dup(STDOUT_FILENO);
270                 else {
271                         __f = lookup_file_hash(f->file_name);
272                         if (__f) {
273                                 f->sem = __f->sem;
274                                 f->fd = dup(__f->fd);
275                                 f->references++;
276                                 from_hash = 1;
277                         } else
278                                 f->fd = open(f->file_name, flags, 0600);
279                 }
280         } else {
281                 if (f->filetype == FIO_TYPE_CHAR && !read_only)
282                         flags |= O_RDWR;
283                 else
284                         flags |= O_RDONLY;
285
286                 if (is_std)
287                         f->fd = dup(STDIN_FILENO);
288                 else {
289                         __f = lookup_file_hash(f->file_name);
290                         if (__f) {
291                                 f->sem = __f->sem;
292                                 f->fd = dup(__f->fd);
293                                 f->references++;
294                                 from_hash = 1;
295                         } else
296                                 f->fd = open(f->file_name, flags);
297                 }
298         }
299
300         if (f->fd == -1) {
301                 char buf[FIO_VERROR_SIZE];
302                 int __e = errno;
303
304                 if (errno == EPERM && (flags & O_NOATIME)) {
305                         flags &= ~O_NOATIME;
306                         goto open_again;
307                 }
308
309                 snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name);
310
311                 td_verror(td, __e, buf);
312         }
313
314         if (get_file_size(td, f))
315                 goto err;
316
317         if (!from_hash && f->fd != -1) {
318                 if (add_file_hash(f)) {
319                         int ret;
320
321                         /*
322                          * OK to ignore, we haven't done anything with it
323                          */
324                         ret = generic_close_file(td, f);
325                         goto open_again;
326                 }
327         }
328
329         return 0;
330 err:
331         close(f->fd);
332         return 1;
333 }
334
335 int open_files(struct thread_data *td)
336 {
337         struct fio_file *f;
338         unsigned int i;
339         int err = 0;
340
341         dprint(FD_FILE, "open files\n");
342
343         for_each_file(td, f, i) {
344                 err = td_io_open_file(td, f);
345                 if (err) {
346                         if (td->error == EMFILE) {
347                                 log_err("fio: limited open files to: %d\n", td->nr_open_files);
348                                 td->o.open_files = td->nr_open_files;
349                                 err = 0;
350                                 clear_error(td);
351                         }
352                         break;
353                 }
354
355                 if (td->o.open_files == td->nr_open_files)
356                         break;
357         }
358
359         if (!err)
360                 return 0;
361
362         for_each_file(td, f, i)
363                 td_io_close_file(td, f);
364
365         return err;
366 }
367
368 /*
369  * open/close all files, so that ->real_file_size gets set
370  */
371 static int get_file_sizes(struct thread_data *td)
372 {
373         struct fio_file *f;
374         unsigned int i;
375         int err = 0;
376
377         for_each_file(td, f, i) {
378                 if (td->io_ops->open_file(td, f)) {
379                         if (td->error != ENOENT) {
380                                 log_err("%s\n", td->verror);
381                                 err = 1;
382                         }
383                         clear_error(td);
384                 } else {
385                         if (td->io_ops->close_file)
386                                 td->io_ops->close_file(td, f);
387                 }
388
389                 if (f->real_file_size == -1ULL && td->o.size)
390                         f->real_file_size = td->o.size / td->o.nr_files;
391         }
392
393         return err;
394 }
395
396 /*
397  * Open the files and setup files sizes, creating files if necessary.
398  */
399 int setup_files(struct thread_data *td)
400 {
401         unsigned long long total_size, extend_size;
402         struct fio_file *f;
403         unsigned int i;
404         int err = 0, need_extend;
405
406         dprint(FD_FILE, "setup files\n");
407
408         /*
409          * if ioengine defines a setup() method, it's responsible for
410          * opening the files and setting f->real_file_size to indicate
411          * the valid range for that file.
412          */
413         if (td->io_ops->setup)
414                 err = td->io_ops->setup(td);
415         else
416                 err = get_file_sizes(td);
417
418         if (err)
419                 return err;
420
421         /*
422          * check sizes. if the files/devices do not exist and the size
423          * isn't passed to fio, abort.
424          */
425         total_size = 0;
426         for_each_file(td, f, i) {
427                 if (f->real_file_size == -1ULL)
428                         total_size = -1ULL;
429                 else
430                         total_size += f->real_file_size;
431         }
432
433         /*
434          * device/file sizes are zero and no size given, punt
435          */
436         if ((!total_size || total_size == -1ULL) && !td->o.size &&
437             !(td->io_ops->flags & FIO_NOIO) && !td->o.fill_device) {
438                 log_err("%s: you need to specify size=\n", td->o.name);
439                 td_verror(td, EINVAL, "total_file_size");
440                 return 1;
441         }
442
443         /*
444          * now file sizes are known, so we can set ->io_size. if size= is
445          * not given, ->io_size is just equal to ->real_file_size. if size
446          * is given, ->io_size is size / nr_files.
447          */
448         extend_size = total_size = 0;
449         need_extend = 0;
450         for_each_file(td, f, i) {
451                 f->file_offset = td->o.start_offset;
452
453                 if (!td->o.file_size_low) {
454                         /*
455                          * no file size range given, file size is equal to
456                          * total size divided by number of files. if that is
457                          * zero, set it to the real file size.
458                          */
459                         f->io_size = td->o.size / td->o.nr_files;
460                         if (!f->io_size)
461                                 f->io_size = f->real_file_size - f->file_offset;
462                 } else if (f->real_file_size < td->o.file_size_low ||
463                            f->real_file_size > td->o.file_size_high) {
464                         if (f->file_offset > td->o.file_size_low) 
465                                 goto err_offset;
466                         /*
467                          * file size given. if it's fixed, use that. if it's a
468                          * range, generate a random size in-between.
469                          */
470                         if (td->o.file_size_low == td->o.file_size_high)
471                                 f->io_size = td->o.file_size_low - f->file_offset;
472                         else
473                                 f->io_size = get_rand_file_size(td) - f->file_offset;
474                 } else
475                         f->io_size = f->real_file_size - f->file_offset;
476
477                 if (f->io_size == -1ULL)
478                         total_size = -1ULL;
479                 else
480                         total_size += f->io_size;
481
482                 if (f->filetype == FIO_TYPE_FILE &&
483                     (f->io_size + f->file_offset) > f->real_file_size &&
484                     !(td->io_ops->flags & FIO_DISKLESSIO)) {
485                         need_extend++;
486                         extend_size += (f->io_size + f->file_offset);
487                         f->flags |= FIO_FILE_EXTEND;
488                 }       
489         }
490
491         if (!td->o.size || td->o.size > total_size)
492                 td->o.size = total_size;
493
494         /*
495          * See if we need to extend some files
496          */
497         if (need_extend) {
498                 temp_stall_ts = 1;
499                 log_info("%s: Laying out IO file(s) (%u file(s) / %LuMiB)\n",
500                         td->o.name, need_extend, extend_size >> 20);
501
502                 for_each_file(td, f, i) {
503                         if (!(f->flags & FIO_FILE_EXTEND))
504                                 continue;
505
506                         assert(f->filetype == FIO_TYPE_FILE);
507                         f->flags &= ~FIO_FILE_EXTEND;
508                         f->real_file_size = (f->io_size + f->file_offset);
509                         err = extend_file(td, f);
510                         if (err)
511                                 break;
512                 }
513                 temp_stall_ts = 0;
514         }
515
516         if (err)
517                 return err;
518
519         if (!td->o.zone_size)
520                 td->o.zone_size = td->o.size;
521
522         /*
523          * iolog already set the total io size, if we read back
524          * stored entries.
525          */
526         if (!td->o.read_iolog_file)
527                 td->total_io_size = td->o.size * td->o.loops;
528         return 0;
529 err_offset:
530         log_err("%s: you need to specify valid offset=\n", td->o.name);
531         return 1;
532 }
533
534 int init_random_map(struct thread_data *td)
535 {
536         unsigned long long blocks, num_maps;
537         struct fio_file *f;
538         unsigned int i;
539
540         if (td->o.norandommap || !td_random(td))
541                 return 0;
542
543         for_each_file(td, f, i) {
544                 blocks = (f->real_file_size + td->o.rw_min_bs - 1) / (unsigned long long) td->o.rw_min_bs;
545                 num_maps = (blocks + BLOCKS_PER_MAP-1)/ (unsigned long long) BLOCKS_PER_MAP;
546                 f->file_map = smalloc(num_maps * sizeof(long));
547                 if (!f->file_map) {
548                         log_err("fio: failed allocating random map. If running a large number of jobs, try the 'norandommap' option\n");
549                         return 1;
550                 }
551                 f->num_maps = num_maps;
552         }
553
554         return 0;
555 }
556
557 void close_files(struct thread_data *td)
558 {
559         struct fio_file *f;
560         unsigned int i;
561
562         for_each_file(td, f, i)
563                 td_io_close_file(td, f);
564 }
565
566 void close_and_free_files(struct thread_data *td)
567 {
568         struct fio_file *f;
569         unsigned int i;
570
571         dprint(FD_FILE, "close files\n");
572
573         for_each_file(td, f, i) {
574                 if (td->o.unlink && f->filetype == FIO_TYPE_FILE)
575                         unlink(f->file_name);
576
577                 td_io_close_file(td, f);
578
579                 sfree(f->file_name);
580                 f->file_name = NULL;
581
582                 if (f->file_map) {
583                         sfree(f->file_map);
584                         f->file_map = NULL;
585                 }
586                 sfree(f);
587         }
588
589         td->o.filename = NULL;
590         free(td->files);
591         td->files = NULL;
592         td->o.nr_files = 0;
593 }
594
595 static void get_file_type(struct fio_file *f)
596 {
597         struct stat sb;
598
599         if (!strcmp(f->file_name, "-"))
600                 f->filetype = FIO_TYPE_PIPE;
601         else
602                 f->filetype = FIO_TYPE_FILE;
603
604         if (!lstat(f->file_name, &sb)) {
605                 if (S_ISBLK(sb.st_mode))
606                         f->filetype = FIO_TYPE_BD;
607                 else if (S_ISCHR(sb.st_mode))
608                         f->filetype = FIO_TYPE_CHAR;
609                 else if (S_ISFIFO(sb.st_mode))
610                         f->filetype = FIO_TYPE_PIPE;
611         }
612 }
613
614 int add_file(struct thread_data *td, const char *fname)
615 {
616         int cur_files = td->files_index;
617         char file_name[PATH_MAX];
618         struct fio_file *f;
619         int len = 0;
620
621         dprint(FD_FILE, "add file %s\n", fname);
622
623         f = smalloc(sizeof(*f));
624         f->fd = -1;
625
626         td->files = realloc(td->files, (cur_files + 1) * sizeof(f));
627
628         td->files[cur_files] = f;
629
630         /*
631          * init function, io engine may not be loaded yet
632          */
633         if (td->io_ops && (td->io_ops->flags & FIO_DISKLESSIO))
634                 f->real_file_size = -1ULL;
635
636         if (td->o.directory)
637                 len = sprintf(file_name, "%s/", td->o.directory);
638
639         sprintf(file_name + len, "%s", fname);
640         f->file_name = smalloc_strdup(file_name);
641
642         get_file_type(f);
643
644         if (td->o.lockfile)
645                 f->sem = fio_sem_init(1);
646
647         td->files_index++;
648         if (f->filetype == FIO_TYPE_FILE)
649                 td->nr_normal_files++;
650
651         return cur_files;
652 }
653
654 void get_file(struct fio_file *f)
655 {
656         dprint(FD_FILE, "get file %s, ref=%d\n", f->file_name, f->references);
657         assert(f->flags & FIO_FILE_OPEN);
658         f->references++;
659 }
660
661 int put_file(struct thread_data *td, struct fio_file *f)
662 {
663         int ret = 0;
664
665         dprint(FD_FILE, "put file %s, ref=%d\n", f->file_name, f->references);
666
667         if (!(f->flags & FIO_FILE_OPEN))
668                 return 0;
669
670         assert(f->references);
671         if (--f->references)
672                 return 0;
673
674         if (should_fsync(td) && td->o.fsync_on_close)
675                 fsync(f->fd);
676
677         if (td->io_ops->close_file)
678                 ret = td->io_ops->close_file(td, f);
679
680         td->nr_open_files--;
681         f->flags &= ~FIO_FILE_OPEN;
682         return ret;
683 }
684
685 void lock_file(struct thread_data *td, struct fio_file *f)
686 {
687         if (f && f->sem) {
688                 if (f->sem_owner == td && f->sem_batch--)
689                         return;
690
691                 fio_sem_down(f->sem);
692                 f->sem_owner = td;
693                 f->sem_batch = td->o.lockfile_batch;
694         }
695 }
696
697 void unlock_file(struct fio_file *f)
698 {
699         if (f && f->sem) {
700                 int sem_val;
701
702                 if (f->sem_batch)
703                         return;
704
705                 sem_getvalue(&f->sem->sem, &sem_val);
706                 if (!sem_val)
707                         f->sem_owner = NULL;
708                 fio_sem_up(f->sem);
709         }
710 }
711
712 static int recurse_dir(struct thread_data *td, const char *dirname)
713 {
714         struct dirent *dir;
715         int ret = 0;
716         DIR *D;
717
718         D = opendir(dirname);
719         if (!D) {
720                 char buf[FIO_VERROR_SIZE];
721
722                 snprintf(buf, FIO_VERROR_SIZE - 1, "opendir(%s)", dirname);
723                 td_verror(td, errno, buf);
724                 return 1;
725         }
726
727         while ((dir = readdir(D)) != NULL) {
728                 char full_path[PATH_MAX];
729                 struct stat sb;
730
731                 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
732                         continue;
733
734                 sprintf(full_path, "%s/%s", dirname, dir->d_name);
735
736                 if (lstat(full_path, &sb) == -1) {
737                         if (errno != ENOENT) {
738                                 td_verror(td, errno, "stat");
739                                 return 1;
740                         }
741                 }
742
743                 if (S_ISREG(sb.st_mode)) {
744                         add_file(td, full_path);
745                         td->o.nr_files++;
746                         continue;
747                 }
748                 if (!S_ISDIR(sb.st_mode))
749                         continue;
750
751                 if ((ret = recurse_dir(td, full_path)) != 0)
752                         break;
753         }
754
755         closedir(D);
756         return ret;
757 }
758
759 int add_dir_files(struct thread_data *td, const char *path)
760 {
761         int ret = recurse_dir(td, path);
762
763         if (!ret)
764                 log_info("fio: opendir added %d files\n", td->o.nr_files);
765
766         return ret;
767 }
768
769 void dup_files(struct thread_data *td, struct thread_data *org)
770 {
771         struct fio_file *f;
772         unsigned int i;
773         size_t bytes;
774
775         if (!org->files)
776                 return;
777
778         bytes = org->files_index * sizeof(f);
779         td->files = malloc(bytes);
780         memcpy(td->files, org->files, bytes);
781
782         for_each_file(td, f, i) {
783                 struct fio_file *__f;
784
785                 __f = smalloc(sizeof(*__f));
786
787                 if (f->file_name)
788                         __f->file_name = smalloc_strdup(f->file_name);
789
790                 td->files[i] = __f;
791         }
792 }
793
794 /*
795  * Returns the index that matches the filename, or -1 if not there
796  */
797 int get_fileno(struct thread_data *td, const char *fname)
798 {
799         struct fio_file *f;
800         unsigned int i;
801
802         for_each_file(td, f, i)
803                 if (!strcmp(f->file_name, fname))
804                         return i;
805
806         return -1;
807 }
808
809 /*
810  * For log usage, where we add/open/close files automatically
811  */
812 void free_release_files(struct thread_data *td)
813 {
814         close_files(td);
815         td->files_index = 0;
816         td->nr_normal_files = 0;
817 }