Merge branch 'filestat1' of https://github.com/kusumi/fio
[fio.git] / engines / filestat.c
CommitLineData
73ccd14e
SF
1/*
2 * filestat engine
3 *
4 * IO engine that doesn't do any IO, just stat files and tracks the latency
5 * of the file stat.
6 */
7#include <stdio.h>
8#include <fcntl.h>
9#include <errno.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <unistd.h>
13#include "../fio.h"
c446eff0 14#include "../optgroup.h"
73ccd14e
SF
15
16struct fc_data {
17 enum fio_ddir stat_ddir;
18};
19
c446eff0
TK
20struct filestat_options {
21 void *pad;
22 unsigned int lstat;
23};
24
25static struct fio_option options[] = {
26 {
27 .name = "lstat",
28 .lname = "lstat",
29 .type = FIO_OPT_BOOL,
30 .off1 = offsetof(struct filestat_options, lstat),
31 .help = "Use lstat(2) to measure lookup/getattr performance",
32 .def = "0",
33 .category = FIO_OPT_C_ENGINE,
34 .group = FIO_OPT_G_FILESTAT,
35 },
36 {
37 .name = NULL,
38 },
39};
40
73ccd14e
SF
41static int stat_file(struct thread_data *td, struct fio_file *f)
42{
c446eff0 43 struct filestat_options *o = td->eo;
73ccd14e
SF
44 struct timespec start;
45 int do_lat = !td->o.disable_lat;
46 struct stat statbuf;
47 int ret;
48
49 dprint(FD_FILE, "fd stat %s\n", f->file_name);
50
51 if (f->filetype != FIO_TYPE_FILE) {
52 log_err("fio: only files are supported\n");
53 return 1;
54 }
55 if (!strcmp(f->file_name, "-")) {
56 log_err("fio: can't read/write to stdin/out\n");
57 return 1;
58 }
59
60 if (do_lat)
61 fio_gettime(&start, NULL);
62
c446eff0
TK
63 if (o->lstat)
64 ret = lstat(f->file_name, &statbuf);
65 else
66 ret = stat(f->file_name, &statbuf);
73ccd14e
SF
67
68 if (ret == -1) {
69 char buf[FIO_VERROR_SIZE];
70 int e = errno;
71
c446eff0
TK
72 snprintf(buf, sizeof(buf), "%sstat(%s)",
73 o->lstat ? "l" : "", f->file_name);
73ccd14e
SF
74 td_verror(td, e, buf);
75 return 1;
76 }
77
78 if (do_lat) {
79 struct fc_data *data = td->io_ops_data;
80 uint64_t nsec;
81
82 nsec = ntime_since_now(&start);
b2a432bf 83 add_clat_sample(td, data->stat_ddir, nsec, 0, 0, 0);
73ccd14e
SF
84 }
85
86 return 0;
87}
88
89static enum fio_q_status queue_io(struct thread_data *td, struct io_u fio_unused *io_u)
90{
91 return FIO_Q_COMPLETED;
92}
93
94static int init(struct thread_data *td)
95{
96 struct fc_data *data;
97
98 data = calloc(1, sizeof(*data));
99
100 if (td_read(td))
101 data->stat_ddir = DDIR_READ;
102 else if (td_write(td))
103 data->stat_ddir = DDIR_WRITE;
104
105 td->io_ops_data = data;
106 return 0;
107}
108
109static void cleanup(struct thread_data *td)
110{
111 struct fc_data *data = td->io_ops_data;
112
113 free(data);
114}
115
116static int stat_invalidate(struct thread_data *td, struct fio_file *f)
117{
118 /* do nothing because file not opened */
119 return 0;
120}
121
122static struct ioengine_ops ioengine = {
123 .name = "filestat",
124 .version = FIO_IOOPS_VERSION,
125 .init = init,
126 .cleanup = cleanup,
127 .queue = queue_io,
128 .invalidate = stat_invalidate,
129 .get_file_size = generic_get_file_size,
130 .open_file = stat_file,
131 .flags = FIO_SYNCIO | FIO_FAKEIO |
132 FIO_NOSTATS | FIO_NOFILEHASH,
c446eff0
TK
133 .options = options,
134 .option_struct_size = sizeof(struct filestat_options),
73ccd14e
SF
135};
136
137static void fio_init fio_filestat_register(void)
138{
139 register_ioengine(&ioengine);
140}
141
142static void fio_exit fio_filestat_unregister(void)
143{
144 unregister_ioengine(&ioengine);
145}