Skip to content

Commit ba1d1ae

Browse files
author
Sergey Truschev
committed
fio: add xattr ioengines
The patch introduce ioengines that allow to measure extended attributes access: filesetxattr for xattrs value setting, filegetxattr - for lookup. Signed-off-by: Sergei Truschev <[email protected]>
1 parent 1eb3ade commit ba1d1ae

File tree

6 files changed

+316
-15
lines changed

6 files changed

+316
-15
lines changed

HOWTO.rst

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,6 +2332,18 @@ I/O engine
23322332
This engine is to measure file lookup and meta data access.
23332333
Example job file: filestat-ioengine.fio.
23342334

2335+
**filesetxattr**
2336+
Simply set files extended attributes via setxattr(). You need to set 'filesize'
2337+
and 'nrfiles', so that files will be created.
2338+
This engine is to measure extended attributes access.
2339+
Example job file: filexattr-ioengine.fio.
2340+
2341+
**filelistxattr**
2342+
Simply list and then get all files extended attributes via listxattr and getxattr.
2343+
You need to set 'filesize' and 'nrfiles', so that files will be created.
2344+
This engine is to measure extended attributes access.
2345+
Example job file: filexattr-ioengine.fio.
2346+
23352347
**filedelete**
23362348
Simply delete the files by unlink() and do no I/O to them. You need to set 'filesize'
23372349
and 'nrfiles', so that the files will be created.
@@ -4854,17 +4866,21 @@ writes in the example above). In the order listed, they denote:
48544866
For file and directory operation engines, **clat** denotes the time
48554867
to complete one file or directory operation.
48564868

4857-
**filecreate engine**:the time cost to create a new file
4869+
**filecreate engine**: the time cost to create a new file
48584870

4859-
**filestat engine**: the time cost to look up an existing file
4871+
**filestat engine**: the time cost to look up an existing file
48604872

4861-
**filedelete engine**:the time cost to delete a file
4873+
**filesetxattr engine**:the time cost to set a bunch of file extended attributes
48624874

4863-
**dircreate engine**: the time cost to create a new directory
4875+
**filestat engine**: the time cost to look up all file extended attributes
48644876

4865-
**dirstat engine**: the time cost to look up an existing directory
4877+
**filedelete engine**: the time cost to delete a file
48664878

4867-
**dirdelete engine**: the time cost to delete a directory
4879+
**dircreate engine**: the time cost to create a new directory
4880+
4881+
**dirstat engine**: the time cost to look up an existing directory
4882+
4883+
**dirdelete engine**: the time cost to delete a directory
48684884

48694885
**lat**
48704886
Total latency. Same names as slat and clat, this denotes the time from
@@ -4896,17 +4912,19 @@ writes in the example above). In the order listed, they denote:
48964912
fundamental index to denote the performance.
48974913
It means how many files or directories can be operated per second.
48984914

4899-
**filecreate engine**:number of files can be created per second
4915+
**filecreate engine**: number of files can be created per second
4916+
4917+
**filestat engine**: number of files can be looked up per second
49004918

4901-
**filestat engine**: number of files can be looked up per second
4919+
**filesetxattr engine**: number of files for which extended attributes can been set per second
49024920

4903-
**filedelete engine**:number of files can be deleted per second
4921+
**filelistxattr engine**:number of all file extended attributes fetches per second
49044922

4905-
**dircreate engine**: number of directories can be created per second
4923+
**dircreate engine**: number of directories can be created per second
49064924

4907-
**dirstat engine**: number of directories can be looked up per second
4925+
**dirstat engine**: number of directories can be looked up per second
49084926

4909-
**dirdelete engine**: number of directories can be deleted per second
4927+
**dirdelete engine**: number of directories can be deleted per second
49104928

49114929
**lat (nsec/usec/msec)**
49124930
The distribution of I/O completion latencies. This is the time from when

engines/fileoperations.c

Lines changed: 250 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <errno.h>
1111
#include <sys/types.h>
1212
#include <sys/stat.h>
13+
#ifndef _WIN32
14+
#include <sys/xattr.h>
15+
#endif
1316
#include <unistd.h>
1417
#include "../fio.h"
1518
#include "../optgroup.h"
@@ -31,13 +34,47 @@ struct filestat_options {
3134
unsigned int stat_type;
3235
};
3336

37+
struct xattr_options {
38+
void* pad;
39+
int size;
40+
int count;
41+
};
42+
3443
enum {
3544
FIO_FILESTAT_STAT = 1,
3645
FIO_FILESTAT_LSTAT = 2,
3746
FIO_FILESTAT_STATX = 3,
3847
};
3948

40-
static struct fio_option options[] = {
49+
#ifndef _WIN32
50+
static struct fio_option xattr_options[] = {
51+
{
52+
.name = "xattr_size",
53+
.lname = "xattr_size",
54+
.type = FIO_OPT_INT,
55+
.off1 = offsetof(struct xattr_options, size),
56+
.help = "Specify the size of the extended attribute to be set.",
57+
.def = "512",
58+
.category = FIO_OPT_C_ENGINE,
59+
.group = FIO_OPT_G_FILEXATTR,
60+
},
61+
{
62+
.name = "xattr_count",
63+
.lname = "xattr_count",
64+
.type = FIO_OPT_INT,
65+
.off1 = offsetof(struct xattr_options, count),
66+
.help = "Specify the number of the extended attributes to be set.",
67+
.def = "1",
68+
.category = FIO_OPT_C_ENGINE,
69+
.group = FIO_OPT_G_FILEXATTR,
70+
},
71+
{
72+
.name = NULL,
73+
}
74+
};
75+
#endif
76+
77+
static struct fio_option stat_options[] = {
4178
{
4279
.name = "stat_type",
4380
.lname = "stat_type",
@@ -206,6 +243,178 @@ static int stat_file(struct thread_data *td, struct fio_file *f)
206243
return 0;
207244
}
208245

246+
#ifndef _WIN32
247+
static int file_setxattr(struct thread_data *td, struct fio_file *f)
248+
{
249+
struct xattr_options *o = td->eo;
250+
struct timespec start;
251+
int attrcount;
252+
char attrname[256];
253+
char *attrval;
254+
int ret;
255+
256+
dprint(FD_FILE, "fd setxattr %s, count = %i, size = %i\n", f->file_name,
257+
o->count, o->size);
258+
259+
if (f->filetype != FIO_TYPE_FILE) {
260+
log_err("fio: only files are supported\n");
261+
return 1;
262+
}
263+
if (!strcmp(f->file_name, "-")) {
264+
log_err("fio: can't read/write to stdin/out\n");
265+
return 1;
266+
}
267+
268+
if (!td->o.disable_lat)
269+
fio_gettime(&start, NULL);
270+
271+
attrcount = o->count;
272+
while (attrcount > 0) {
273+
attrval = malloc(o->size);
274+
snprintf(attrname, 256, "user.fio_xattr_%i", attrcount--);
275+
#ifdef __linux__
276+
ret = setxattr(f->file_name, attrname, attrval, o->size, 0);
277+
#elif defined (__APPLE__)
278+
ret = setxattr(f->file_name, attrname, attrval, o->size, 0, 0);
279+
#else
280+
ret = -1;
281+
#endif
282+
free(attrval);
283+
284+
if (ret == -1) {
285+
char buf[FIO_VERROR_SIZE];
286+
int e = errno;
287+
288+
snprintf(buf, sizeof(buf), "setxattr(%s)", f->file_name);
289+
td_verror(td, e, buf);
290+
return 1;
291+
}
292+
}
293+
294+
if (!td->o.disable_lat) {
295+
struct fc_data *data = td->io_ops_data;
296+
uint64_t nsec;
297+
298+
nsec = ntime_since_now(&start);
299+
add_clat_sample(td, data->stat_ddir, nsec, 0, NULL);
300+
}
301+
302+
return 0;
303+
}
304+
305+
static int file_listxattr(struct thread_data *td, struct fio_file *f)
306+
{
307+
struct timespec start;
308+
309+
ssize_t buflen;
310+
ssize_t vallen;
311+
size_t namelen;
312+
char *attrname;
313+
char *attrbuf;
314+
char *attrval;
315+
316+
const char *errfn;
317+
char buf[FIO_VERROR_SIZE];
318+
int e;
319+
320+
dprint(FD_FILE, "fd listxattr %s\n", f->file_name);
321+
322+
if (f->filetype != FIO_TYPE_FILE) {
323+
log_err("fio: only files are supported\n");
324+
return 1;
325+
}
326+
if (!strcmp(f->file_name, "-")) {
327+
log_err("fio: can't read/write to stdin/out\n");
328+
return 1;
329+
}
330+
331+
if (!td->o.disable_lat)
332+
fio_gettime(&start, NULL);
333+
334+
#ifdef __linux__
335+
buflen = listxattr(f->file_name, NULL, 0);
336+
#elif defined (__APPLE__)
337+
buflen = listxattr(f->file_name, NULL, 0, 0);
338+
#else
339+
buflen = -1;
340+
#endif
341+
if (buflen == -1) {
342+
errfn = "listxattr";
343+
goto err;
344+
} else if (buflen == 0) {
345+
return 0;
346+
}
347+
348+
attrbuf = malloc(buflen);
349+
#ifdef __linux__
350+
buflen = listxattr(f->file_name, attrbuf, buflen);
351+
#elif defined (__APPLE__)
352+
buflen = listxattr(f->file_name, attrbuf, buflen, 0);
353+
#else
354+
buflen = -1;
355+
#endif
356+
if (buflen == -1) {
357+
errfn = "listxattr";
358+
goto err_cleanup;
359+
}
360+
361+
attrname = attrbuf;
362+
while (buflen > 0) {
363+
#ifdef __linux__
364+
vallen = getxattr(f->file_name, attrname, NULL, 0);
365+
#elif defined (__APPLE__)
366+
vallen = getxattr(f->file_name, attrname, NULL, 0, 0, 0);
367+
#else
368+
vallen = -1;
369+
#endif
370+
if (vallen == -1) {
371+
errfn = "getxattr";
372+
goto err_cleanup;
373+
}
374+
375+
if (vallen > 0) {
376+
attrval = malloc(vallen);
377+
#ifdef __linux__
378+
vallen = getxattr(f->file_name, attrname, attrval, vallen);
379+
#elif defined (__APPLE__)
380+
vallen = getxattr(f->file_name, attrname, attrval, vallen, 0, 0);
381+
#else
382+
vallen = -1;
383+
#endif
384+
free(attrval);
385+
if (vallen == -1) {
386+
errfn = "getxattr";
387+
goto err_cleanup;
388+
}
389+
}
390+
391+
namelen = strlen(attrname) + 1;
392+
buflen -= namelen;
393+
attrname += namelen;
394+
}
395+
396+
free(attrbuf);
397+
398+
if (!td->o.disable_lat) {
399+
struct fc_data *data = td->io_ops_data;
400+
uint64_t nsec;
401+
402+
nsec = ntime_since_now(&start);
403+
add_clat_sample(td, data->stat_ddir, nsec, 0, NULL);
404+
}
405+
406+
return 0;
407+
408+
err_cleanup:
409+
free(attrbuf);
410+
err:
411+
e = errno;
412+
snprintf(buf, sizeof(buf), "%s(%s)", errfn, f->file_name);
413+
td_verror(td, e, buf);
414+
return 1;
415+
}
416+
#endif
417+
209418
static int delete_file(struct thread_data *td, struct fio_file *f)
210419
{
211420
struct timespec start;
@@ -341,7 +550,7 @@ static struct ioengine_ops ioengine_filestat = {
341550
.open_file = stat_file,
342551
.flags = FIO_SYNCIO | FIO_FAKEIO |
343552
FIO_NOSTATS | FIO_NOFILEHASH,
344-
.options = options,
553+
.options = stat_options,
345554
.option_struct_size = sizeof(struct filestat_options),
346555
};
347556

@@ -385,7 +594,7 @@ static struct ioengine_ops ioengine_dirstat = {
385594
.unlink_file = remove_dir,
386595
.flags = FIO_DISKLESSIO | FIO_SYNCIO | FIO_FAKEIO |
387596
FIO_NOSTATS | FIO_NOFILEHASH,
388-
.options = options,
597+
.options = stat_options,
389598
.option_struct_size = sizeof(struct filestat_options),
390599
};
391600

@@ -404,6 +613,36 @@ static struct ioengine_ops ioengine_dirdelete = {
404613
FIO_NOSTATS | FIO_NOFILEHASH,
405614
};
406615

616+
#ifndef _WIN32
617+
static struct ioengine_ops ioengine_filesetxattr = {
618+
.name = "filesetxattr",
619+
.version = FIO_IOOPS_VERSION,
620+
.init = init,
621+
.cleanup = cleanup,
622+
.queue = queue_io,
623+
.invalidate = invalidate_do_nothing,
624+
.get_file_size = generic_get_file_size,
625+
.open_file = file_setxattr,
626+
.flags = FIO_SYNCIO | FIO_FAKEIO |
627+
FIO_NOSTATS | FIO_NOFILEHASH,
628+
.options = xattr_options,
629+
.option_struct_size = sizeof(struct xattr_options),
630+
};
631+
632+
static struct ioengine_ops ioengine_filelistxattr = {
633+
.name = "filelistxattr",
634+
.version = FIO_IOOPS_VERSION,
635+
.init = init,
636+
.invalidate = invalidate_do_nothing,
637+
.cleanup = cleanup,
638+
.queue = queue_io,
639+
.get_file_size = generic_get_file_size,
640+
.open_file = file_listxattr,
641+
.flags = FIO_SYNCIO | FIO_FAKEIO |
642+
FIO_NOSTATS | FIO_NOFILEHASH,
643+
};
644+
#endif
645+
407646
static void fio_init fio_fileoperations_register(void)
408647
{
409648
register_ioengine(&ioengine_filecreate);
@@ -412,6 +651,10 @@ static void fio_init fio_fileoperations_register(void)
412651
register_ioengine(&ioengine_dircreate);
413652
register_ioengine(&ioengine_dirstat);
414653
register_ioengine(&ioengine_dirdelete);
654+
#ifndef _WIN32
655+
register_ioengine(&ioengine_filesetxattr);
656+
register_ioengine(&ioengine_filelistxattr);
657+
#endif
415658
}
416659

417660
static void fio_exit fio_fileoperations_unregister(void)
@@ -422,4 +665,8 @@ static void fio_exit fio_fileoperations_unregister(void)
422665
unregister_ioengine(&ioengine_dircreate);
423666
unregister_ioengine(&ioengine_dirstat);
424667
unregister_ioengine(&ioengine_dirdelete);
668+
#ifndef _WIN32
669+
unregister_ioengine(&ioengine_filesetxattr);
670+
unregister_ioengine(&ioengine_filelistxattr);
671+
#endif
425672
}

0 commit comments

Comments
 (0)