static int ipo_special(struct thread_data *td, struct io_piece *ipo) { struct fio_file *f; int ret; /* * Not a special ipo */ if (ipo->ddir != DDIR_INVAL) return 0; f = td->files[ipo->fileno]; switch (ipo->file_action) { case FIO_LOG_OPEN_FILE: ret = td_io_open_file(td, f); if (!ret) break; td_verror(td, ret, "iolog open file"); return -1; case FIO_LOG_CLOSE_FILE: td_io_close_file(td, f); break; case FIO_LOG_UNLINK_FILE: td_io_unlink_file(td, f); break; default: log_err("fio: bad file action %d\n", ipo->file_action); break; } return 1; }
/* * Leaves f->fd open on success, caller must close */ static int extend_file(struct thread_data *td, struct fio_file *f) { int r, new_layout = 0, unlink_file = 0, flags; unsigned long long left; unsigned int bs; char *b = NULL; if (read_only) { log_err("fio: refusing extend of file due to read-only\n"); return 0; } /* * check if we need to lay the file out complete again. fio * does that for operations involving reads, or for writes * where overwrite is set */ if (td_read(td) || (td_write(td) && td->o.overwrite && !td->o.file_append) || (td_write(td) && td->io_ops->flags & FIO_NOEXTEND)) new_layout = 1; if (td_write(td) && !td->o.overwrite && !td->o.file_append) unlink_file = 1; if (unlink_file || new_layout) { dprint(FD_FILE, "layout unlink %s\n", f->file_name); if ((td_io_unlink_file(td, f) < 0) && (errno != ENOENT)) { td_verror(td, errno, "unlink"); return 1; } } flags = O_WRONLY; if (td->o.allow_create) flags |= O_CREAT; if (new_layout) flags |= O_TRUNC; #ifdef WIN32 flags |= _O_BINARY; #endif dprint(FD_FILE, "open file %s, flags %x\n", f->file_name, flags); f->fd = open(f->file_name, flags, 0644); if (f->fd < 0) { int err = errno; if (err == ENOENT && !td->o.allow_create) log_err("fio: file creation disallowed by " "allow_file_create=0\n"); else td_verror(td, err, "open"); return 1; } #ifdef CONFIG_POSIX_FALLOCATE if (!td->o.fill_device) { switch (td->o.fallocate_mode) { case FIO_FALLOCATE_NONE: break; case FIO_FALLOCATE_POSIX: dprint(FD_FILE, "posix_fallocate file %s size %llu\n", f->file_name, (unsigned long long) f->real_file_size); r = posix_fallocate(f->fd, 0, f->real_file_size); if (r > 0) { log_err("fio: posix_fallocate fails: %s\n", strerror(r)); } break; #ifdef CONFIG_LINUX_FALLOCATE case FIO_FALLOCATE_KEEP_SIZE: dprint(FD_FILE, "fallocate(FALLOC_FL_KEEP_SIZE) " "file %s size %llu\n", f->file_name, (unsigned long long) f->real_file_size); r = fallocate(f->fd, FALLOC_FL_KEEP_SIZE, 0, f->real_file_size); if (r != 0) td_verror(td, errno, "fallocate"); break; #endif /* CONFIG_LINUX_FALLOCATE */ default: log_err("fio: unknown fallocate mode: %d\n", td->o.fallocate_mode); assert(0); } } #endif /* CONFIG_POSIX_FALLOCATE */ if (!new_layout) goto done; /* * The size will be -1ULL when fill_device is used, so don't truncate * or fallocate this file, just write it */ if (!td->o.fill_device) { dprint(FD_FILE, "truncate file %s, size %llu\n", f->file_name, (unsigned long long) f->real_file_size); if (ftruncate(f->fd, f->real_file_size) == -1) { if (errno != EFBIG) { td_verror(td, errno, "ftruncate"); goto err; } } } b = malloc(td->o.max_bs[DDIR_WRITE]); left = f->real_file_size; while (left && !td->terminate) { bs = td->o.max_bs[DDIR_WRITE]; if (bs > left) bs = left; fill_io_buffer(td, b, bs, bs); r = write(f->fd, b, bs); if (r > 0) { left -= r; continue; } else { if (r < 0) { int __e = errno; if (__e == ENOSPC) { if (td->o.fill_device) break; log_info("fio: ENOSPC on laying out " "file, stopping\n"); break; } td_verror(td, errno, "write"); } else td_verror(td, EIO, "write"); break; } } if (td->terminate) { dprint(FD_FILE, "terminate unlink %s\n", f->file_name); td_io_unlink_file(td, f); } else if (td->o.create_fsync) { if (fsync(f->fd) < 0) { td_verror(td, errno, "fsync"); goto err; } } if (td->o.fill_device && !td_write(td)) { fio_file_clear_size_known(f); if (td_io_get_file_size(td, f)) goto err; if (f->io_size > f->real_file_size) f->io_size = f->real_file_size; } free(b); done: return 0; err: close(f->fd); f->fd = -1; if (b) free(b); return 1; }