Skip to content

Commit 68ef955

Browse files
ggoersGeorg Görs
and
Georg Görs
authored
new IOR-Backend that uses libnfs (#511)
* new backend libnfs prepared (without implementation) * use url for specifing nfs server, path and options * use newest Version from libnfs * integration tests for the libnfs backend * README for the libnfs-integration tests --------- Co-authored-by: Georg Görs <[email protected]>
1 parent ceb3b86 commit 68ef955

10 files changed

+885
-0
lines changed

README_LIBNFS

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Building
2+
--------
3+
If libnfs is installed in a standard location, you can use the following commands:
4+
5+
./bootstrap
6+
./configure --with-libnfs
7+
8+
If you have installed libnfs in a custom location or compiled it by yourself, you need to specify the include directory and the library path by setting the CFLAGS and LDFLAGS variables:
9+
10+
./bootstrap
11+
./configure [other options] --with-libnfs CFLAGS="-I /path/to/libnfs/include" LDFLAGS="-L /path/to/libnfs/lib"
12+
13+
If you compiled libnfs by yourself, don't forget to add the library path to the $LD_LIBRARY_PATH environment variable, or copy the library to the same directory as the executable.
14+
15+
Running
16+
-------
17+
18+
./ior -a LIBNFS [ior_options] [libnfs_options]
19+
./mdtest -a LIBNFS [ior_options] [libnfs_options]
20+
21+
Options
22+
-------
23+
24+
required:
25+
--libnfs.url
26+
A URL in RFC2224 style defining the nfs server, the path where the Benchmark will run und other options. For all options and URL Examples see the README of the libnfs Repo https://raw.githubusercontent.com/sahlberg/libnfs/refs/heads/master/README .

configure.ac

+17
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,23 @@ AM_COND_IF([USE_CEPHFS_AIORI],[
334334
AC_DEFINE([USE_CEPHFS_AIORI], [], [Build CEPHFS backend AIORI])
335335
])
336336

337+
# libnfs Backend
338+
AC_ARG_WITH([libnfs],
339+
[AS_HELP_STRING([--with-libnfs],
340+
[support IO with libnfs backend @<:@default=no@:>@])],
341+
[],
342+
[with_libnfs=no])
343+
AM_CONDITIONAL([USE_LIBNFS_AIORI], [test x$with_libnfs != xno])
344+
AS_IF([test "x$with_libnfs" != xno], [
345+
AC_DEFINE([USE_LIBNFS_AIORI], [], [Build libnfs backend AIORI using libnfs])
346+
# a path to the installation directory is passed -> setup include directory and lib path
347+
# if no argument is passed or explicit "yes" -> use standard install location
348+
AS_IF([test "x$with_libnfs" != xyes], [
349+
LDFLAGS="$LDFLAGS -L$with_libnfs/lib/x86_64-linux-gnu"
350+
CPPFLAGS="$CPPFLAGS -I$with_libnfs/include"
351+
])
352+
])
353+
337354
# DAOS-FS Backend (DFS)
338355
AC_ARG_WITH([daos],
339356
[AS_HELP_STRING([--with-daos],

src/Makefile.am

+4
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ extraSOURCES += aiori-CEPHFS.c
9999
extraLDADD += -lcephfs
100100
endif
101101

102+
if USE_LIBNFS_AIORI
103+
extraSOURCES += aiori-LIBNFS.c
104+
extraLDADD += -lnfs
105+
endif
102106

103107
if USE_DAOS_AIORI
104108
extraSOURCES += aiori-DFS.c

src/aiori-LIBNFS.c

+308
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
/******************************************************************************\
2+
*
3+
* Implement abstract I/O interface for libnfs (a user space nfs library).
4+
*
5+
\******************************************************************************/
6+
7+
#include <stdlib.h>
8+
#include <stdint.h>
9+
#include <inttypes.h>
10+
#include <fcntl.h>
11+
#include <errno.h>
12+
#include <nfsc/libnfs.h>
13+
#include "aiori-LIBNFS.h"
14+
#include "aiori.h"
15+
#include "aiori-debug.h"
16+
17+
static struct nfs_context *nfs_context;
18+
19+
static struct nfs_url *nfs_url;
20+
21+
static struct aiori_xfer_hint_t *hint_parameter;
22+
23+
/******************************************************************************\
24+
*
25+
* Helper Functions
26+
*
27+
\******************************************************************************/
28+
29+
int Map_IOR_Open_Flags_To_LIBNFS_Flags(int ior_open_flags) {
30+
int libnfs_flags = 0;
31+
if (ior_open_flags & IOR_RDONLY) {
32+
libnfs_flags |= O_RDONLY;
33+
}
34+
35+
if (ior_open_flags & IOR_WRONLY) {
36+
libnfs_flags |= O_WRONLY;
37+
}
38+
39+
if (ior_open_flags & IOR_RDWR) {
40+
libnfs_flags |= O_RDWR;
41+
}
42+
43+
if (ior_open_flags & IOR_APPEND) {
44+
libnfs_flags |= O_APPEND;
45+
}
46+
47+
if (ior_open_flags & IOR_CREAT) {
48+
libnfs_flags |= O_CREAT;
49+
}
50+
51+
if (ior_open_flags & IOR_TRUNC) {
52+
libnfs_flags |= O_TRUNC;
53+
}
54+
55+
return libnfs_flags;
56+
}
57+
58+
/******************************************************************************\
59+
*
60+
* Implementation of the Backend-Interface.
61+
*
62+
\******************************************************************************/
63+
64+
char *LIBNFS_GetVersion(){
65+
return "Version 1.0";
66+
}
67+
68+
aiori_fd_t *LIBNFS_Open(char *file_path, int ior_flags, aiori_mod_opt_t *) {
69+
struct nfsfh *newFileFh;
70+
int libnfs_flags = Map_IOR_Open_Flags_To_LIBNFS_Flags(ior_flags);
71+
int open_result = nfs_open(nfs_context, file_path, libnfs_flags, &newFileFh);
72+
if (open_result) {
73+
ERRF("Error while opening the file %s \n nfs error: %s\n", file_path, nfs_get_error(nfs_context));
74+
}
75+
76+
return (aiori_fd_t *)newFileFh;
77+
}
78+
79+
void LIBNFS_Close(aiori_fd_t * file_descriptor, aiori_mod_opt_t * module_options) {
80+
struct nfsfh *file = (struct nfsfh *)file_descriptor;
81+
int close_result = nfs_close(nfs_context, file);
82+
if (close_result) {
83+
ERRF("Error while closing a file \n nfs error: %s\n", nfs_get_error(nfs_context));
84+
}
85+
}
86+
87+
aiori_fd_t *LIBNFS_Create(char *file_path, int ior_flags, aiori_mod_opt_t *)
88+
{
89+
struct nfsfh *newFileFh;
90+
int libnfs_flags = Map_IOR_Open_Flags_To_LIBNFS_Flags(ior_flags);
91+
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
92+
int open_result = nfs_open2(nfs_context, file_path, libnfs_flags, mode, &newFileFh);
93+
nfs_chmod(nfs_context, file_path, mode);
94+
if (open_result) {
95+
ERRF("Error while creating the file %s \n nfs error: %s\n", file_path, nfs_get_error(nfs_context));
96+
}
97+
98+
return (aiori_fd_t *)newFileFh;
99+
}
100+
101+
void LIBNFS_Remove(char* file_path, aiori_mod_opt_t * module_options) {
102+
int unlink_result = nfs_unlink(nfs_context, file_path);
103+
if (unlink_result) {
104+
ERRF("Error while unlinking the file %s \n nfs error: %s\n", file_path, nfs_get_error(nfs_context));
105+
}
106+
}
107+
108+
IOR_offset_t LIBNFS_Xfer(
109+
int access,
110+
aiori_fd_t *file_descriptor,
111+
IOR_size_t *buffer,
112+
IOR_offset_t size,
113+
IOR_offset_t offset,
114+
aiori_mod_opt_t * module_options) {
115+
116+
struct nfsfh *file = (struct nfsfh *)file_descriptor;
117+
uint64_t current_offset;
118+
nfs_lseek(nfs_context, file, offset, SEEK_SET, &current_offset);
119+
if (current_offset != offset) {
120+
ERRF("Error while calling lseek... expected offset: %lld but current offset: %" PRIu64 "\n nfs error: %s\n", offset, current_offset, nfs_get_error(nfs_context));
121+
}
122+
123+
if (access == WRITE) {
124+
int write_result = nfs_write(nfs_context, file, (void *)buffer, (uint64_t)size);
125+
if (write_result < 0) {
126+
ERRF("Error while writing to file \n nfs error: %s\n", nfs_get_error(nfs_context));
127+
}
128+
129+
return write_result;
130+
}
131+
132+
if (access == READ) {
133+
int read_result = nfs_read(nfs_context, file, (void*)buffer, (size_t)size);
134+
if (read_result < 0) {
135+
ERRF("Error while reading to file \n nfs error: %s\n", nfs_get_error(nfs_context));
136+
}
137+
138+
return read_result;
139+
}
140+
141+
return (IOR_offset_t)0;
142+
}
143+
144+
void LIBNFS_XferHints(aiori_xfer_hint_t * params) {
145+
hint_parameter = params;
146+
}
147+
148+
int LIBNFS_MakeDirectory(const char *path, mode_t mode, aiori_mod_opt_t * module_options) {
149+
if (nfs_mkdir2(nfs_context, path, mode)) {
150+
ERRF("Error while creating directory \n nfs error: %s\n", nfs_get_error(nfs_context));
151+
}
152+
153+
return 0;
154+
}
155+
156+
int LIBNFS_RemoveDirectory(const char *path, aiori_mod_opt_t * module_options) {
157+
if (nfs_rmdir(nfs_context, path)) {
158+
ERRF("Error while removing directory \n nfs error: %s\n", nfs_get_error(nfs_context));
159+
}
160+
161+
return 0;
162+
}
163+
164+
int LIBNFS_Stat(const char *path, struct stat *stat, aiori_mod_opt_t * module_options) {
165+
struct nfs_stat_64 nfs_stat;
166+
int stat_result = nfs_stat64(nfs_context, path, &nfs_stat);
167+
if (stat_result) {
168+
if (-stat_result == ENOENT) {
169+
return ENOENT;
170+
}
171+
172+
ERRF("Error while calling stat on path %s \n nfs error: %s\n", path, nfs_get_error(nfs_context));
173+
}
174+
175+
stat->st_blksize = nfs_stat.nfs_blksize;
176+
stat->st_blocks = nfs_stat.nfs_blocks;
177+
stat->st_size = nfs_stat.nfs_size;
178+
stat->st_gid = nfs_stat.nfs_gid;
179+
stat->st_uid = nfs_stat.nfs_uid;
180+
stat->st_dev = nfs_stat.nfs_dev;
181+
stat->st_rdev = nfs_stat.nfs_rdev;
182+
stat->st_ino = nfs_stat.nfs_ino;
183+
stat->st_mode = nfs_stat.nfs_mode;
184+
stat->st_nlink = nfs_stat.nfs_nlink;
185+
stat->st_atime = nfs_stat.nfs_atime;
186+
stat->st_mtime = nfs_stat.nfs_mtime;
187+
stat->st_ctime = nfs_stat.nfs_ctime;
188+
return 0;
189+
}
190+
191+
int LIBNFS_StatFS(const char *path, ior_aiori_statfs_t *stat, aiori_mod_opt_t * module_options) {
192+
struct nfs_statvfs_64 stat_fs;
193+
int stat_result = nfs_statvfs64(nfs_context, path, &stat_fs);
194+
if (stat_result) {
195+
ERRF("Error while calling statfs on path %s \n nfs error: %s\n", path, nfs_get_error(nfs_context));
196+
return stat_result;
197+
}
198+
199+
stat->f_bavail = stat_fs.f_bavail;
200+
stat->f_bfree = stat_fs.f_bfree;
201+
stat->f_blocks = stat_fs.f_blocks;
202+
stat->f_bsize = stat_fs.f_bsize;
203+
stat->f_ffree = stat_fs.f_ffree;
204+
stat->f_files = stat_fs.f_files;
205+
206+
return 0;
207+
}
208+
209+
void LIBNFS_FSync(aiori_fd_t *file_descriptor, aiori_mod_opt_t * module_options) {
210+
struct nfsfh *file = (struct nfsfh *)file_descriptor;
211+
if (nfs_fsync(nfs_context, file)) {
212+
ERRF("Error while calling fsync \n nfs error: %s\n", nfs_get_error(nfs_context));
213+
}
214+
}
215+
216+
int LIBNFS_Access(const char *path, int mode, aiori_mod_opt_t *module_options) {
217+
return nfs_access(nfs_context, path, mode);
218+
}
219+
220+
IOR_offset_t LIBNFS_GetFileSize(aiori_mod_opt_t *module_options, char *path) {
221+
struct nfs_stat_64 nfs_stat;
222+
int stat_result = nfs_stat64(nfs_context, path, &nfs_stat);
223+
if (stat_result) {
224+
ERRF("Error while calling stat on path %s (to evaluate the file size) \n nfs error: %s\n", path, nfs_get_error(nfs_context));
225+
}
226+
227+
return (IOR_offset_t)nfs_stat.nfs_size;
228+
}
229+
230+
option_help *LIBNFS_GetOptions(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t* init_values) {
231+
libnfs_options_t *libnfs_options = malloc(sizeof(libnfs_options_t));
232+
if (init_values != NULL) {
233+
memcpy(libnfs_options, init_values, sizeof(libnfs_options_t));
234+
} else {
235+
memset(libnfs_options, 0, sizeof(libnfs_options_t));
236+
}
237+
238+
*init_backend_options = (aiori_mod_opt_t *) libnfs_options;
239+
240+
option_help h [] = {
241+
{0, "libnfs.url", "The URL (RFC2224) specifing the server, path and options", OPTION_REQUIRED_ARGUMENT, 's', &libnfs_options->url},
242+
LAST_OPTION
243+
};
244+
245+
option_help * help = malloc(sizeof(h));
246+
memcpy(help, h, sizeof(h));
247+
return help;
248+
}
249+
250+
void LIBNFS_Initialize(aiori_mod_opt_t * options) {
251+
if (nfs_context || nfs_url)
252+
{
253+
return;
254+
}
255+
256+
libnfs_options_t *libnfs_options = (libnfs_options_t *)options;
257+
nfs_context = nfs_init_context();
258+
if (!nfs_context) {
259+
ERRF("Error while creating the nfs context \n nfs error: %s\n", nfs_get_error(nfs_context));
260+
}
261+
262+
nfs_url = nfs_parse_url_full(nfs_context, libnfs_options->url);
263+
if (!nfs_url) {
264+
ERRF("Error while parsing the argument libnfs.url \n nfs error: %s\n", nfs_get_error(nfs_context));
265+
}
266+
267+
int mount_result = nfs_mount(nfs_context, nfs_url->server, nfs_url->path);
268+
if (mount_result) {
269+
ERRF("Error while mounting nfs server: %s, path: %s \n nfs error: %s\n", nfs_url->server, nfs_url->path, nfs_get_error(nfs_context));
270+
}
271+
}
272+
273+
void LIBNFS_Finalize(aiori_mod_opt_t * options) {
274+
if (nfs_context) {
275+
nfs_destroy_context(nfs_context);
276+
nfs_context = NULL;
277+
}
278+
279+
if (nfs_url) {
280+
nfs_destroy_url(nfs_url);
281+
nfs_url = NULL;
282+
}
283+
}
284+
285+
ior_aiori_t libnfs_aiori = {
286+
.name = "LIBNFS",
287+
.name_legacy = NULL,
288+
.get_version = LIBNFS_GetVersion,
289+
.open = LIBNFS_Open,
290+
.close = LIBNFS_Close,
291+
.create = LIBNFS_Create,
292+
.remove = LIBNFS_Remove,
293+
.xfer = LIBNFS_Xfer,
294+
.xfer_hints = LIBNFS_XferHints,
295+
.mkdir = LIBNFS_MakeDirectory,
296+
.rmdir = LIBNFS_RemoveDirectory,
297+
.stat = LIBNFS_Stat,
298+
.statfs = LIBNFS_StatFS,
299+
.sync = NULL,
300+
.fsync = LIBNFS_FSync,
301+
.access = LIBNFS_Access,
302+
.get_file_size = LIBNFS_GetFileSize,
303+
.get_options = LIBNFS_GetOptions,
304+
.check_params = NULL,
305+
.initialize = LIBNFS_Initialize,
306+
.finalize = LIBNFS_Finalize,
307+
.enable_mdtest = true,
308+
};

src/aiori-LIBNFS.h

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef _AIORI_LIBNFS_H
2+
#define _AIORI_LIBNFS_H
3+
4+
/************************** O P T I O N S *****************************/
5+
6+
typedef struct {
7+
char *url;
8+
} libnfs_options_t;
9+
10+
#endif

src/aiori.c

+3
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ ior_aiori_t *available_aiori[] = {
9292
#endif
9393
#ifdef USE_FINCHFS_AIORI
9494
&finchfs_aiori,
95+
#endif
96+
#ifdef USE_LIBNFS_AIORI
97+
&libnfs_aiori,
9598
#endif
9699
NULL
97100
};

0 commit comments

Comments
 (0)