#include <fcntl.h>
#include "../fio.h"
+#include "../optgroup.h"
#ifndef EXT4_IOC_MOVE_EXT
#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent)
};
struct e4defrag_options {
- struct thread_data *td;
+ void *pad;
unsigned int inplace;
char * donor_name;
};
static struct fio_option options[] = {
{
.name = "donorname",
+ .lname = "Donor Name",
.type = FIO_OPT_STR_STORE,
.off1 = offsetof(struct e4defrag_options, donor_name),
.help = "File used as a block donor",
+ .category = FIO_OPT_C_ENGINE,
+ .group = FIO_OPT_G_E4DEFRAG,
},
{
.name = "inplace",
+ .lname = "In Place",
.type = FIO_OPT_INT,
.off1 = offsetof(struct e4defrag_options, inplace),
.minval = 0,
.maxval = 1,
.help = "Alloc and free space inside defrag event",
+ .category = FIO_OPT_C_ENGINE,
+ .group = FIO_OPT_G_E4DEFRAG,
},
{
.name = NULL,
ed = malloc(sizeof(*ed));
if (!ed) {
- td_verror(td, -ENOMEM, "io_queue_init");
+ td_verror(td, ENOMEM, "io_queue_init");
return 1;
}
memset(ed, 0 ,sizeof(*ed));
ed->donor_fd = open(donor_name, O_CREAT|O_WRONLY, 0644);
if (ed->donor_fd < 0) {
- td_verror(td, ed->donor_fd, "io_queue_init");
- log_err("Can't open donor file %s err:%d", ed->donor_fd);
+ td_verror(td, errno, "io_queue_init");
+ log_err("Can't open donor file %s err:%d\n", donor_name, ed->donor_fd);
free(ed);
return 1;
}
if (!o->inplace) {
- long long len = td->o.file_size_high - td->o.start_offset;
- r = fallocate(ed->donor_fd, 0, td->o.start_offset, len);
+ long long __len = td->o.file_size_high - td->o.start_offset;
+ r = fallocate(ed->donor_fd, 0, td->o.start_offset, __len);
if (r)
goto err;
}
goto err;
ed->bsz = stub.st_blksize;
- td->io_ops->data = ed;
+ td->io_ops_data = ed;
return 0;
err:
td_verror(td, errno, "io_queue_init");
static void fio_e4defrag_cleanup(struct thread_data *td)
{
- struct e4defrag_data *ed = td->io_ops->data;
+ struct e4defrag_data *ed = td->io_ops_data;
if (ed) {
if (ed->donor_fd >= 0)
close(ed->donor_fd);
unsigned long long len;
struct move_extent me;
struct fio_file *f = io_u->file;
- struct e4defrag_data *ed = td->io_ops->data;
+ struct e4defrag_data *ed = td->io_ops_data;
struct e4defrag_options *o = td->eo;
fio_ro_check(td, io_u);
* in order to satisfy strict read only access pattern
*/
if (io_u->ddir != DDIR_WRITE) {
- io_u->error = errno;
+ io_u->error = EINVAL;
return FIO_Q_COMPLETED;
}
if (o->inplace) {
ret = fallocate(ed->donor_fd, 0, io_u->offset, io_u->xfer_buflen);
- if (ret) {
- io_u->error = errno;
+ if (ret)
goto out;
- }
}
memset(&me, 0, sizeof(me));
ret = ioctl(f->fd, EXT4_IOC_MOVE_EXT, &me);
len = me.moved_len * ed->bsz;
- if (io_u->file && len >= 0 && ddir_rw(io_u->ddir))
- io_u->file->file_pos = io_u->offset + len;
-
if (len > io_u->xfer_buflen)
len = io_u->xfer_buflen;
if (len != io_u->xfer_buflen) {
- io_u->resid = io_u->xfer_buflen - len;
- io_u->error = 0;
+ if (len) {
+ io_u->resid = io_u->xfer_buflen - len;
+ io_u->error = 0;
+ } else {
+ /* access beyond i_size */
+ io_u->error = EINVAL;
+ }
}
if (ret)
io_u->error = errno;
-
- if (o->inplace) {
+
+ if (o->inplace)
ret = ftruncate(ed->donor_fd, 0);
- if (ret)
- io_u->error = errno;
- }
out:
- if (io_u->error)
- td_verror(td, errno, "xfer");
-
+ if (ret && !io_u->error)
+ io_u->error = errno;
return FIO_Q_COMPLETED;
}