|
| 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, ¤t_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 | +}; |
0 commit comments