IOR
aiori-DFS.c
Go to the documentation of this file.
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  */
4 /*
5  * Copyright (C) 2018-2020 Intel Corporation
6  * See the file COPYRIGHT for a complete copyright notice and license.
7  */
8 
9 /*
10  * This file implements the abstract I/O interface for DAOS FS API.
11  */
12 
13 #define _BSD_SOURCE
14 
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18 
19 #include <string.h>
20 #include <assert.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <dirent.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <libgen.h>
29 
30 #include <mpi.h>
31 #include <gurt/common.h>
32 #include <gurt/hash.h>
33 #include <daos.h>
34 #include <daos_fs.h>
35 
36 #include "aiori.h"
37 #include "utilities.h"
38 #include "iordef.h"
39 
40 dfs_t *dfs;
41 static daos_handle_t poh, coh;
42 static daos_oclass_id_t objectClass;
43 static daos_oclass_id_t dir_oclass;
44 static struct d_hash_table *dir_hash;
45 static bool dfs_init;
46 
47 struct aiori_dir_hdl {
48  d_list_t entry;
49  dfs_obj_t *oh;
50  char name[PATH_MAX];
51 };
52 
53 enum handleType {
57 };
58 
59 /************************** O P T I O N S *****************************/
60 typedef struct {
61  char *pool;
62 #if !defined(DAOS_API_VERSION_MAJOR) || DAOS_API_VERSION_MAJOR < 1
63  char *svcl;
64 #endif
65  char *group;
66  char *cont;
68  char *oclass;
69  char *dir_oclass;
70  char *prefix;
71  int destroy;
73 
74 static option_help * DFS_options(aiori_mod_opt_t ** init_backend_options,
75  aiori_mod_opt_t * init_values){
76  DFS_options_t * o = malloc(sizeof(DFS_options_t));
77 
78  if (init_values != NULL) {
79  memcpy(o, init_values, sizeof(DFS_options_t));
80  } else {
81  memset(o, 0, sizeof(DFS_options_t));
82  /* initialize the options properly */
83  o->chunk_size = 1048576;
84  }
85 
86  *init_backend_options = (aiori_mod_opt_t *) o;
87 
88  option_help h [] = {
89  {0, "dfs.pool", "pool uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o->pool},
90 #if !defined(DAOS_API_VERSION_MAJOR) || DAOS_API_VERSION_MAJOR < 1
91  {0, "dfs.svcl", "pool SVCL", OPTION_OPTIONAL_ARGUMENT, 's', &o->svcl},
92 #endif
93  {0, "dfs.group", "server group", OPTION_OPTIONAL_ARGUMENT, 's', &o->group},
94  {0, "dfs.cont", "DFS container uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o->cont},
95  {0, "dfs.chunk_size", "chunk size", OPTION_OPTIONAL_ARGUMENT, 'd', &o->chunk_size},
96  {0, "dfs.oclass", "object class", OPTION_OPTIONAL_ARGUMENT, 's', &o->oclass},
97  {0, "dfs.dir_oclass", "directory object class", OPTION_OPTIONAL_ARGUMENT, 's',
98  &o->dir_oclass},
99  {0, "dfs.prefix", "mount prefix", OPTION_OPTIONAL_ARGUMENT, 's', &o->prefix},
100  {0, "dfs.destroy", "Destroy DFS Container", OPTION_FLAG, 'd', &o->destroy},
102  };
103 
104  option_help * help = malloc(sizeof(h));
105  memcpy(help, h, sizeof(h));
106  return help;
107 }
108 
109 /**************************** P R O T O T Y P E S *****************************/
110 static void DFS_Init(aiori_mod_opt_t *);
111 static void DFS_Finalize(aiori_mod_opt_t *);
112 static aiori_fd_t *DFS_Create(char *, int, aiori_mod_opt_t *);
113 static aiori_fd_t *DFS_Open(char *, int, aiori_mod_opt_t *);
116 static void DFS_Close(aiori_fd_t *, aiori_mod_opt_t *);
117 static void DFS_Delete(char *, aiori_mod_opt_t *);
118 static char* DFS_GetVersion();
119 static void DFS_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
120 static void DFS_Sync(aiori_mod_opt_t *);
122 static int DFS_Statfs (const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *);
123 static int DFS_Stat (const char *, struct stat *, aiori_mod_opt_t *);
124 static int DFS_Mkdir (const char *, mode_t, aiori_mod_opt_t *);
125 static int DFS_Rmdir (const char *, aiori_mod_opt_t *);
126 static int DFS_Access (const char *, int, aiori_mod_opt_t *);
127 static option_help * DFS_options();
129 static int DFS_check_params(aiori_mod_opt_t *);
130 
131 /************************** D E C L A R A T I O N S ***************************/
132 
134  .name = "DFS",
135  .initialize = DFS_Init,
136  .finalize = DFS_Finalize,
137  .create = DFS_Create,
138  .open = DFS_Open,
139  .xfer = DFS_Xfer,
140  .close = DFS_Close,
141  .delete = DFS_Delete,
142  .get_version = DFS_GetVersion,
143  .fsync = DFS_Fsync,
144  .sync = DFS_Sync,
145  .get_file_size = DFS_GetFileSize,
146  .xfer_hints = DFS_init_xfer_options,
147  .statfs = DFS_Statfs,
148  .mkdir = DFS_Mkdir,
149  .rmdir = DFS_Rmdir,
150  .access = DFS_Access,
151  .stat = DFS_Stat,
152  .get_options = DFS_options,
153  .check_params = DFS_check_params,
154  .enable_mdtest = true,
155 };
156 
157 /***************************** F U N C T I O N S ******************************/
158 
159 /* For DAOS methods. */
160 #define DCHECK(rc, format, ...) \
161 do { \
162  int _rc = (rc); \
163  \
164  if (_rc != 0) { \
165  fprintf(stderr, "ERROR (%s:%d): %d: %d: " \
166  format"\n", __FILE__, __LINE__, rank, _rc, \
167  ##__VA_ARGS__); \
168  fflush(stderr); \
169  exit(-1); \
170  } \
171 } while (0)
172 
173 #define INFO(level, format, ...) \
174 do { \
175  if (verbose >= level) \
176  printf("[%d] "format"\n", rank, ##__VA_ARGS__); \
177 } while (0)
178 
179 #define GERR(format, ...) \
180 do { \
181  fprintf(stderr, format"\n", ##__VA_ARGS__); \
182  MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error"); \
183 } while (0)
184 
186 
188 {
189  hints = params;
190 }
191 
193  DFS_options_t *o = (DFS_options_t *) options;
194 
195  if (o->pool == NULL || o->cont == NULL)
196  ERR("Invalid pool or container options\n");
197 
198 #if !defined(DAOS_API_VERSION_MAJOR) || DAOS_API_VERSION_MAJOR < 1
199  if (o->svcl == NULL)
200  ERR("Invalid SVCL\n");
201 #endif
202  return 0;
203 }
204 
205 static inline struct aiori_dir_hdl *
206 hdl_obj(d_list_t *rlink)
207 {
208  return container_of(rlink, struct aiori_dir_hdl, entry);
209 }
210 
211 static bool
212 key_cmp(struct d_hash_table *htable, d_list_t *rlink,
213  const void *key, unsigned int ksize)
214 {
215  struct aiori_dir_hdl *hdl = hdl_obj(rlink);
216 
217  return (strcmp(hdl->name, (const char *)key) == 0);
218 }
219 
220 static void
221 rec_free(struct d_hash_table *htable, d_list_t *rlink)
222 {
223  struct aiori_dir_hdl *hdl = hdl_obj(rlink);
224 
225  assert(d_hash_rec_unlinked(&hdl->entry));
226  dfs_release(hdl->oh);
227  free(hdl);
228 }
229 
230 static d_hash_table_ops_t hdl_hash_ops = {
231  .hop_key_cmp = key_cmp,
232  .hop_rec_free = rec_free
233 };
234 
235 /* Distribute process 0's pool or container handle to others. */
236 static void
238 {
239  d_iov_t global;
240  int rc;
241 
242  global.iov_buf = NULL;
243  global.iov_buf_len = 0;
244  global.iov_len = 0;
245 
246  assert(type == POOL_HANDLE || type == CONT_HANDLE || type == DFS_HANDLE);
247  if (rank == 0) {
248  /* Get the global handle size. */
249  if (type == POOL_HANDLE)
250  rc = daos_pool_local2global(poh, &global);
251  else if (type == CONT_HANDLE)
252  rc = daos_cont_local2global(coh, &global);
253  else
254  rc = dfs_local2global(dfs, &global);
255  DCHECK(rc, "Failed to get global handle size");
256  }
257 
258  MPI_CHECK(MPI_Bcast(&global.iov_buf_len, 1, MPI_UINT64_T, 0, testComm),
259  "Failed to bcast global handle buffer size");
260 
261  global.iov_len = global.iov_buf_len;
262  global.iov_buf = malloc(global.iov_buf_len);
263  if (global.iov_buf == NULL)
264  ERR("Failed to allocate global handle buffer");
265 
266  if (rank == 0) {
267  if (type == POOL_HANDLE)
268  rc = daos_pool_local2global(poh, &global);
269  else if (type == CONT_HANDLE)
270  rc = daos_cont_local2global(coh, &global);
271  else
272  rc = dfs_local2global(dfs, &global);
273  DCHECK(rc, "Failed to create global handle");
274  }
275 
276  MPI_CHECK(MPI_Bcast(global.iov_buf, global.iov_buf_len, MPI_BYTE, 0, testComm),
277  "Failed to bcast global pool handle");
278 
279  if (rank != 0) {
280  if (type == POOL_HANDLE)
281  rc = daos_pool_global2local(global, &poh);
282  else if (type == CONT_HANDLE)
283  rc = daos_cont_global2local(poh, global, &coh);
284  else
285  rc = dfs_global2local(poh, coh, 0, global, &dfs);
286  DCHECK(rc, "Failed to get local handle");
287  }
288 
289  free(global.iov_buf);
290 }
291 
292 static int
293 parse_filename(const char *path, char **_obj_name, char **_cont_name)
294 {
295  char *f1 = NULL;
296  char *f2 = NULL;
297  char *fname = NULL;
298  char *cont_name = NULL;
299  int rc = 0;
300 
301  if (path == NULL || _obj_name == NULL || _cont_name == NULL)
302  return -EINVAL;
303 
304  if (strcmp(path, "/") == 0) {
305  *_cont_name = strdup("/");
306  if (*_cont_name == NULL)
307  return -ENOMEM;
308  *_obj_name = NULL;
309  return 0;
310  }
311 
312  f1 = strdup(path);
313  if (f1 == NULL) {
314  rc = -ENOMEM;
315  goto out;
316  }
317 
318  f2 = strdup(path);
319  if (f2 == NULL) {
320  rc = -ENOMEM;
321  goto out;
322  }
323 
324  fname = basename(f1);
325  cont_name = dirname(f2);
326 
327  if (cont_name[0] == '.' || cont_name[0] != '/') {
328  char cwd[1024];
329 
330  if (getcwd(cwd, 1024) == NULL) {
331  rc = -ENOMEM;
332  goto out;
333  }
334 
335  if (strcmp(cont_name, ".") == 0) {
336  cont_name = strdup(cwd);
337  if (cont_name == NULL) {
338  rc = -ENOMEM;
339  goto out;
340  }
341  } else {
342  char *new_dir = calloc(strlen(cwd) + strlen(cont_name)
343  + 1, sizeof(char));
344  if (new_dir == NULL) {
345  rc = -ENOMEM;
346  goto out;
347  }
348 
349  strcpy(new_dir, cwd);
350  if (cont_name[0] == '.') {
351  strcat(new_dir, &cont_name[1]);
352  } else {
353  strcat(new_dir, "/");
354  strcat(new_dir, cont_name);
355  }
356  cont_name = new_dir;
357  }
358  *_cont_name = cont_name;
359  } else {
360  *_cont_name = strdup(cont_name);
361  if (*_cont_name == NULL) {
362  rc = -ENOMEM;
363  goto out;
364  }
365  }
366 
367  *_obj_name = strdup(fname);
368  if (*_obj_name == NULL) {
369  free(*_cont_name);
370  *_cont_name = NULL;
371  rc = -ENOMEM;
372  goto out;
373  }
374 
375 out:
376  if (f1)
377  free(f1);
378  if (f2)
379  free(f2);
380  return rc;
381 }
382 
383 static void
384 share_file_handle(dfs_obj_t **file, MPI_Comm comm)
385 {
386  d_iov_t global;
387  int rc;
388 
389  global.iov_buf = NULL;
390  global.iov_buf_len = 0;
391  global.iov_len = 0;
392 
393  if (rank == 0) {
394  rc = dfs_obj_local2global(dfs, *file, &global);
395  DCHECK(rc, "Failed to get global handle size");
396  }
397 
398  MPI_CHECK(MPI_Bcast(&global.iov_buf_len, 1, MPI_UINT64_T, 0, testComm),
399  "Failed to bcast global handle buffer size");
400 
401  global.iov_len = global.iov_buf_len;
402  global.iov_buf = malloc(global.iov_buf_len);
403  if (global.iov_buf == NULL)
404  ERR("Failed to allocate global handle buffer");
405 
406  if (rank == 0) {
407  rc = dfs_obj_local2global(dfs, *file, &global);
408  DCHECK(rc, "Failed to create global handle");
409  }
410 
411  MPI_CHECK(MPI_Bcast(global.iov_buf, global.iov_buf_len, MPI_BYTE, 0, testComm),
412  "Failed to bcast global pool handle");
413 
414  if (rank != 0) {
415  rc = dfs_obj_global2local(dfs, 0, global, file);
416  DCHECK(rc, "Failed to get local handle");
417  }
418 
419  free(global.iov_buf);
420 }
421 
422 static dfs_obj_t *
423 lookup_insert_dir(const char *name, mode_t *mode)
424 {
425  struct aiori_dir_hdl *hdl;
426  d_list_t *rlink;
427  int rc;
428 
429  rlink = d_hash_rec_find(dir_hash, name, strlen(name));
430  if (rlink != NULL) {
431  hdl = hdl_obj(rlink);
432  return hdl->oh;
433  }
434 
435  hdl = calloc(1, sizeof(struct aiori_dir_hdl));
436  if (hdl == NULL)
437  GERR("failed to alloc dir handle");
438 
439  strncpy(hdl->name, name, PATH_MAX-1);
440  hdl->name[PATH_MAX-1] = '\0';
441 
442  rc = dfs_lookup(dfs, name, O_RDWR, &hdl->oh, mode, NULL);
443  if (rc)
444  return NULL;
445  if (mode && S_ISREG(*mode))
446  return hdl->oh;
447 
448  rc = d_hash_rec_insert(dir_hash, hdl->name, strlen(hdl->name),
449  &hdl->entry, true);
450  DCHECK(rc, "Failed to insert dir handle in hashtable");
451 
452  return hdl->oh;
453 }
454 
455 static void
457 {
458  DFS_options_t *o = (DFS_options_t *)options;
459  int rc;
460 
462  if (dfs_init)
463  return;
464 
466  if (o->pool == NULL || o->cont == NULL)
467  return;
468 
469 #if !defined(DAOS_API_VERSION_MAJOR) || DAOS_API_VERSION_MAJOR < 1
470  if (o->svcl == NULL)
471  return;
472 #endif
473 
474  rc = daos_init();
475  DCHECK(rc, "Failed to initialize daos");
476 
477  if (o->oclass) {
478  objectClass = daos_oclass_name2id(o->oclass);
479  if (objectClass == OC_UNKNOWN)
480  GERR("Invalid DAOS object class %s\n", o->oclass);
481  }
482 
483  if (o->dir_oclass) {
484  dir_oclass = daos_oclass_name2id(o->dir_oclass);
485  if (dir_oclass == OC_UNKNOWN)
486  GERR("Invalid DAOS directory object class %s\n", o->dir_oclass);
487  }
488 
489  rc = d_hash_table_create(0, 16, NULL, &hdl_hash_ops, &dir_hash);
490  DCHECK(rc, "Failed to initialize dir hashtable");
491 
492  if (rank == 0) {
493  uuid_t pool_uuid, co_uuid;
494  daos_pool_info_t pool_info;
495  daos_cont_info_t co_info;
496 
497  rc = uuid_parse(o->pool, pool_uuid);
498  DCHECK(rc, "Failed to parse 'Pool uuid': %s", o->pool);
499 
500  rc = uuid_parse(o->cont, co_uuid);
501  DCHECK(rc, "Failed to parse 'Cont uuid': %s", o->cont);
502 
503  INFO(VERBOSE_1, "Pool uuid = %s", o->pool);
504  INFO(VERBOSE_1, "DFS Container namespace uuid = %s", o->cont);
505 
506 #if !defined(DAOS_API_VERSION_MAJOR) || DAOS_API_VERSION_MAJOR < 1
507  d_rank_list_t *svcl = NULL;
508 
509  svcl = daos_rank_list_parse(o->svcl, ":");
510  if (svcl == NULL)
511  ERR("Failed to allocate svcl");
512  INFO(VERBOSE_1, "Pool svcl = %s", o->svcl);
513 
515  rc = daos_pool_connect(pool_uuid, o->group, svcl, DAOS_PC_RW,
516  &poh, &pool_info, NULL);
517  d_rank_list_free(svcl);
518 #else
519  rc = daos_pool_connect(pool_uuid, o->group, DAOS_PC_RW,
520  &poh, &pool_info, NULL);
521 #endif
522  DCHECK(rc, "Failed to connect to pool");
523 
524  rc = daos_cont_open(poh, co_uuid, DAOS_COO_RW, &coh, &co_info,
525  NULL);
526  /* If NOEXIST we create it */
527  if (rc == -DER_NONEXIST) {
528  INFO(VERBOSE_1, "Creating DFS Container ...\n");
529 
530  rc = dfs_cont_create(poh, co_uuid, NULL, &coh, NULL);
531  if (rc)
532  DCHECK(rc, "Failed to create container");
533  } else if (rc) {
534  DCHECK(rc, "Failed to create container");
535  }
536 
537  rc = dfs_mount(poh, coh, O_RDWR, &dfs);
538  DCHECK(rc, "Failed to mount DFS namespace");
539  }
540 
544 
545  if (o->prefix) {
546  rc = dfs_set_prefix(dfs, o->prefix);
547  DCHECK(rc, "Failed to set DFS Prefix");
548  }
549  dfs_init = true;
550 }
551 
552 static void
554 {
555  DFS_options_t *o = (DFS_options_t *)options;
556  int rc;
557 
558  MPI_Barrier(testComm);
559  d_hash_table_destroy(dir_hash, true /* force */);
560 
561  rc = dfs_umount(dfs);
562  DCHECK(rc, "Failed to umount DFS namespace");
563  MPI_Barrier(testComm);
564 
565  rc = daos_cont_close(coh, NULL);
566  DCHECK(rc, "Failed to close container %s (%d)", o->cont, rc);
567  MPI_Barrier(testComm);
568 
569  if (o->destroy) {
570  if (rank == 0) {
571  uuid_t uuid;
572  double t1, t2;
573 
574  INFO(VERBOSE_1, "Destroying DFS Container: %s\n", o->cont);
575  uuid_parse(o->cont, uuid);
576  t1 = MPI_Wtime();
577  rc = daos_cont_destroy(poh, uuid, 1, NULL);
578  t2 = MPI_Wtime();
579  if (rc == 0)
580  INFO(VERBOSE_1, "Container Destroy time = %f secs", t2-t1);
581  }
582 
583  MPI_Bcast(&rc, 1, MPI_INT, 0, testComm);
584  if (rc) {
585  if (rank == 0)
586  DCHECK(rc, "Failed to destroy container %s (%d)", o->cont, rc);
587  MPI_Abort(MPI_COMM_WORLD, -1);
588  }
589  }
590 
591  if (rank == 0)
592  INFO(VERBOSE_1, "Disconnecting from DAOS POOL\n");
593 
594  rc = daos_pool_disconnect(poh, NULL);
595  DCHECK(rc, "Failed to disconnect from pool");
596 
597  MPI_CHECK(MPI_Barrier(testComm), "barrier error");
598 
599  if (rank == 0)
600  INFO(VERBOSE_1, "Finalizing DAOS..\n");
601 
602  rc = daos_fini();
603  DCHECK(rc, "Failed to finalize DAOS");
604 
606  o->pool = NULL;
607 #if !defined(DAOS_API_VERSION_MAJOR) || DAOS_API_VERSION_MAJOR < 1
608  o->svcl = NULL;
609 #endif
610  o->group = NULL;
611  o->cont = NULL;
612  o->chunk_size = 1048576;
613  o->oclass = NULL;
614  o->dir_oclass = NULL;
615  o->prefix = NULL;
616  o->destroy = 0;
617  objectClass = 0;
618  dir_oclass = 0;
619  dfs_init = false;
620 }
621 
622 /*
623  * Create and open a file through the DFS interface.
624  */
625 static aiori_fd_t *
626 DFS_Create(char *testFileName, int flags, aiori_mod_opt_t *param)
627 {
628  DFS_options_t *o = (DFS_options_t*) param;
629  char *name = NULL, *dir_name = NULL;
630  dfs_obj_t *obj = NULL, *parent = NULL;
631  mode_t mode = 0664;
632  int fd_oflag = 0;
633  int rc;
634 
635  rc = parse_filename(testFileName, &name, &dir_name);
636  DCHECK(rc, "Failed to parse path %s", testFileName);
637  assert(dir_name);
638  assert(name);
639 
640  mode = S_IFREG | mode;
641  if (hints->filePerProc || rank == 0) {
642  fd_oflag |= O_CREAT | O_RDWR | O_EXCL;
643 
644  parent = lookup_insert_dir(dir_name, NULL);
645  if (parent == NULL)
646  GERR("Failed to lookup parent dir");
647 
648  rc = dfs_open(dfs, parent, name, mode, fd_oflag,
649  objectClass, o->chunk_size, NULL, &obj);
650  DCHECK(rc, "dfs_open() of %s Failed", name);
651  }
652 
653  if (!hints->filePerProc) {
655  }
656 
657  if (name)
658  free(name);
659  if (dir_name)
660  free(dir_name);
661 
662  return (aiori_fd_t *)(obj);
663 }
664 
665 /*
666  * Open a file through the DFS interface.
667  */
668 static aiori_fd_t *
669 DFS_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
670 {
671  DFS_options_t *o = (DFS_options_t*) param;
672  char *name = NULL, *dir_name = NULL;
673  dfs_obj_t *obj = NULL, *parent = NULL;
674  mode_t mode = 0664;
675  int fd_oflag = 0;
676  int rc;
677 
678  fd_oflag |= O_RDWR;
679  mode = S_IFREG | flags;
680 
681  rc = parse_filename(testFileName, &name, &dir_name);
682  DCHECK(rc, "Failed to parse path %s", testFileName);
683  assert(dir_name);
684  assert(name);
685 
686  if (hints->filePerProc || rank == 0) {
687  parent = lookup_insert_dir(dir_name, NULL);
688  if (parent == NULL)
689  GERR("Failed to lookup parent dir");
690 
691  rc = dfs_open(dfs, parent, name, mode, fd_oflag, objectClass,
692  o->chunk_size, NULL, &obj);
693  DCHECK(rc, "dfs_open() of %s Failed", name);
694  }
695 
696  if (!hints->filePerProc) {
698  }
699 
700  if (name)
701  free(name);
702  if (dir_name)
703  free(dir_name);
704 
705  return (aiori_fd_t *)(obj);
706 }
707 
708 /*
709  * Write or read access to file using the DFS interface.
710  */
711 static IOR_offset_t
712 DFS_Xfer(int access, aiori_fd_t *file, IOR_size_t *buffer, IOR_offset_t length,
713  IOR_offset_t off, aiori_mod_opt_t *param)
714 {
715  int xferRetries = 0;
716  long long remaining = (long long)length;
717  char *ptr = (char *)buffer;
718  daos_size_t ret;
719  int rc;
720  dfs_obj_t *obj;
721 
722  obj = (dfs_obj_t *)file;
723 
724  while (remaining > 0) {
725  d_iov_t iov;
726  d_sg_list_t sgl;
727 
729  sgl.sg_nr = 1;
730  sgl.sg_nr_out = 0;
731  d_iov_set(&iov, (void *)ptr, remaining);
732  sgl.sg_iovs = &iov;
733 
734  /* write/read file */
735  if (access == WRITE) {
736  rc = dfs_write(dfs, obj, &sgl, off, NULL);
737  if (rc) {
738  fprintf(stderr, "dfs_write() failed (%d)\n", rc);
739  return -1;
740  }
741  ret = remaining;
742  } else {
743  rc = dfs_read(dfs, obj, &sgl, off, &ret, NULL);
744  if (rc || ret == 0)
745  fprintf(stderr, "dfs_read() failed(%d)\n", rc);
746  }
747 
748  if (ret < remaining) {
749  if (hints->singleXferAttempt == TRUE)
750  exit(-1);
751  if (xferRetries > MAX_RETRY)
752  ERR("too many retries -- aborting");
753  }
754 
755  assert(ret >= 0);
756  assert(ret <= remaining);
757  remaining -= ret;
758  ptr += ret;
759  xferRetries++;
760  }
761 
762  return (length);
763 }
764 
765 /*
766  * Perform fsync().
767  */
768 static void
770 {
771  /* no cache in DFS, so this is a no-op currently */
772  dfs_sync(dfs);
773  return;
774 }
775 
776 /*
777  * Perform sync() on the dfs mount.
778  */
779 static void
781 {
782  /* no cache in DFS, so this is a no-op currently */
783  dfs_sync(dfs);
784  return;
785 }
786 
787 /*
788  * Close a file through the DFS interface.
789  */
790 static void
792 {
793  dfs_release((dfs_obj_t *)fd);
794 }
795 
796 /*
797  * Delete a file through the DFS interface.
798  */
799 static void
800 DFS_Delete(char *testFileName, aiori_mod_opt_t * param)
801 {
802  char *name = NULL, *dir_name = NULL;
803  dfs_obj_t *parent = NULL;
804  int rc;
805 
806  rc = parse_filename(testFileName, &name, &dir_name);
807  DCHECK(rc, "Failed to parse path %s", testFileName);
808 
809  assert(dir_name);
810  assert(name);
811 
812  parent = lookup_insert_dir(dir_name, NULL);
813  if (parent == NULL)
814  GERR("Failed to lookup parent dir");
815 
816  rc = dfs_remove(dfs, parent, name, false, NULL);
817  DCHECK(rc, "dfs_remove() of %s Failed", name);
818 
819  if (name)
820  free(name);
821  if (dir_name)
822  free(dir_name);
823 }
824 
825 static char* DFS_GetVersion()
826 {
827  static char ver[1024] = {};
828 
829  sprintf(ver, "%s", "DAOS");
830  return ver;
831 }
832 
833 /*
834  * Use DFS stat() to return aggregate file size.
835  */
836 static IOR_offset_t
837 DFS_GetFileSize(aiori_mod_opt_t * test, char *testFileName)
838 {
839  dfs_obj_t *obj;
840  MPI_Comm comm;
841  daos_size_t fsize;
842  int rc;
843 
844  if (hints->filePerProc == TRUE) {
845  comm = MPI_COMM_SELF;
846  } else {
847  comm = testComm;
848  }
849 
850  if (hints->filePerProc || rank == 0) {
851  rc = dfs_lookup(dfs, testFileName, O_RDONLY, &obj, NULL, NULL);
852  if (rc) {
853  fprintf(stderr, "dfs_lookup() of %s Failed (%d)", testFileName, rc);
854  return -1;
855  }
856 
857  rc = dfs_get_size(dfs, obj, &fsize);
858  dfs_release(obj);
859  if (rc)
860  return -1;
861  }
862 
863  if (!hints->filePerProc) {
864  rc = MPI_Bcast(&fsize, 1, MPI_UINT64_T, 0, comm);
865  if (rc)
866  return rc;
867  }
868 
869  return (fsize);
870 }
871 
872 static int
873 DFS_Statfs(const char *path, ior_aiori_statfs_t *sfs, aiori_mod_opt_t * param)
874 {
875  return 0;
876 }
877 
878 static int
879 DFS_Mkdir(const char *path, mode_t mode, aiori_mod_opt_t * param)
880 {
881  dfs_obj_t *parent = NULL;
882  char *name = NULL, *dir_name = NULL;
883  int rc;
884 
885  rc = parse_filename(path, &name, &dir_name);
886  DCHECK(rc, "Failed to parse path %s", path);
887 
888  assert(dir_name);
889  if (!name)
890  return 0;
891 
892  parent = lookup_insert_dir(dir_name, NULL);
893  if (parent == NULL)
894  GERR("Failed to lookup parent dir");
895 
896  rc = dfs_mkdir(dfs, parent, name, mode, dir_oclass);
897  DCHECK(rc, "dfs_mkdir() of %s Failed", name);
898 
899  if (name)
900  free(name);
901  if (dir_name)
902  free(dir_name);
903  return rc;
904 }
905 
906 static int
907 DFS_Rmdir(const char *path, aiori_mod_opt_t * param)
908 {
909  dfs_obj_t *parent = NULL;
910  char *name = NULL, *dir_name = NULL;
911  int rc;
912 
913  rc = parse_filename(path, &name, &dir_name);
914  DCHECK(rc, "Failed to parse path %s", path);
915 
916  assert(dir_name);
917  assert(name);
918 
919  parent = lookup_insert_dir(dir_name, NULL);
920  if (parent == NULL)
921  GERR("Failed to lookup parent dir");
922 
923  rc = dfs_remove(dfs, parent, name, false, NULL);
924  DCHECK(rc, "dfs_remove() of %s Failed", name);
925 
926  if (name)
927  free(name);
928  if (dir_name)
929  free(dir_name);
930  if (rc)
931  return -1;
932  return rc;
933 }
934 
935 static int
936 DFS_Access(const char *path, int mode, aiori_mod_opt_t * param)
937 {
938  dfs_obj_t *obj = NULL;
939  mode_t fmode;
940 
941  obj = lookup_insert_dir(path, &fmode);
942  if (obj == NULL)
943  return -1;
944 
946  if (S_ISREG(fmode))
947  dfs_release(obj);
948 
949  return 0;
950 }
951 
952 static int
953 DFS_Stat(const char *path, struct stat *buf, aiori_mod_opt_t * param)
954 {
955  dfs_obj_t *parent = NULL;
956  char *name = NULL, *dir_name = NULL;
957  int rc;
958 
959  rc = parse_filename(path, &name, &dir_name);
960  DCHECK(rc, "Failed to parse path %s", path);
961 
962  assert(dir_name);
963  assert(name);
964 
965  parent = lookup_insert_dir(dir_name, NULL);
966  if (parent == NULL)
967  GERR("Failed to lookup parent dir");
968 
969  rc = dfs_stat(dfs, parent, name, buf);
970 
971  if (name)
972  free(name);
973  if (dir_name)
974  free(dir_name);
975  if (rc)
976  return -1;
977  return rc;
978 }
static void HandleDistribute(enum handleType type)
Definition: aiori-DFS.c:237
static void rec_free(struct d_hash_table *htable, d_list_t *rlink)
Definition: aiori-DFS.c:221
handleType
Definition: aiori-DFS.c:53
static struct aiori_dir_hdl * hdl_obj(d_list_t *rlink)
Definition: aiori-DFS.c:206
#define LAST_OPTION
Definition: option.h:39
CURLcode rc
Definition: aiori-S3-4c.c:111
char * svcl
Definition: aiori-DFS.c:63
#define DCHECK(rc, format,...)
Definition: aiori-DFS.c:160
struct benchmark_options o
Definition: md-workbench.c:128
static daos_handle_t coh
Definition: aiori-DFS.c:41
dfs_obj_t * oh
Definition: aiori-DFS.c:49
dfs_t * dfs
Definition: aiori-DFS.c:40
static int parse_filename(const char *path, char **_obj_name, char **_cont_name)
Definition: aiori-DFS.c:293
static d_hash_table_ops_t hdl_hash_ops
Definition: aiori-DFS.c:230
#define GERR(format,...)
Definition: aiori-DFS.c:179
static IOR_offset_t DFS_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *)
Definition: aiori-DFS.c:712
static aiori_fd_t * DFS_Create(char *, int, aiori_mod_opt_t *)
Definition: aiori-DFS.c:626
#define MPI_CHECK(MPI_STATUS, MSG)
Definition: aiori-debug.h:127
#define WRITE
Definition: iordef.h:86
static void share_file_handle(dfs_obj_t **file, MPI_Comm comm)
Definition: aiori-DFS.c:384
static int DFS_Access(const char *, int, aiori_mod_opt_t *)
Definition: aiori-DFS.c:936
static void DFS_Finalize(aiori_mod_opt_t *)
Definition: aiori-DFS.c:553
char * dir_oclass
Definition: aiori-DFS.c:69
#define INFO(level, format,...)
Definition: aiori-DFS.c:173
static aiori_xfer_hint_t * hints
Definition: aiori-DFS.c:185
static struct d_hash_table * dir_hash
Definition: aiori-DFS.c:44
MPI_Comm testComm
Definition: utilities.c:71
static option_help options[]
Definition: aiori-CEPHFS.c:54
#define PATH_MAX
Definition: iordef.h:103
static void DFS_Sync(aiori_mod_opt_t *)
Definition: aiori-DFS.c:780
static daos_oclass_id_t dir_oclass
Definition: aiori-DFS.c:43
static IOR_offset_t DFS_GetFileSize(aiori_mod_opt_t *, char *)
Definition: aiori-DFS.c:837
int singleXferAttempt
Definition: aiori.h:75
static int DFS_Mkdir(const char *, mode_t, aiori_mod_opt_t *)
Definition: aiori-DFS.c:879
static void DFS_init_xfer_options(aiori_xfer_hint_t *)
Definition: aiori-DFS.c:187
#define MAX_RETRY
Definition: iordef.h:101
static option_help * DFS_options(aiori_mod_opt_t **init_backend_options, aiori_mod_opt_t *init_values)
Definition: aiori-DFS.c:74
static bool dfs_init
Definition: aiori-DFS.c:45
static daos_handle_t poh
Definition: aiori-DFS.c:41
char * pool
Definition: aiori-DFS.c:61
static void DFS_Delete(char *, aiori_mod_opt_t *)
Definition: aiori-DFS.c:800
static daos_oclass_id_t objectClass
Definition: aiori-DFS.c:42
char * oclass
Definition: aiori-DFS.c:68
ior_aiori_t dfs_aiori
Definition: aiori-DFS.c:133
long long int IOR_size_t
Definition: iordef.h:110
static char * DFS_GetVersion()
Definition: aiori-DFS.c:825
static void DFS_Close(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-DFS.c:791
static int DFS_Statfs(const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *)
Definition: aiori-DFS.c:873
static dfs_obj_t * lookup_insert_dir(const char *name, mode_t *mode)
Definition: aiori-DFS.c:423
static int DFS_Stat(const char *, struct stat *, aiori_mod_opt_t *)
Definition: aiori-DFS.c:953
char * prefix
Definition: aiori-DFS.c:70
static void DFS_Fsync(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-DFS.c:769
int chunk_size
Definition: aiori-DFS.c:67
d_list_t entry
Definition: aiori-DFS.c:48
static void DFS_Init(aiori_mod_opt_t *)
Definition: aiori-DFS.c:456
#define ERR(MSG)
Definition: aiori-debug.h:92
char name[PATH_MAX]
Definition: aiori-DFS.c:50
#define VERBOSE_1
Definition: iordef.h:93
static aiori_fd_t * DFS_Open(char *, int, aiori_mod_opt_t *)
Definition: aiori-DFS.c:669
char * name
Definition: aiori.h:88
int filePerProc
Definition: aiori.h:65
long long int IOR_offset_t
Definition: iordef.h:109
char * group
Definition: aiori-DFS.c:65
static int DFS_Rmdir(const char *, aiori_mod_opt_t *)
Definition: aiori-DFS.c:907
int rank
Definition: utilities.c:68
#define TRUE
Definition: iordef.h:66
static bool key_cmp(struct d_hash_table *htable, d_list_t *rlink, const void *key, unsigned int ksize)
Definition: aiori-DFS.c:212
static int DFS_check_params(aiori_mod_opt_t *)
Definition: aiori-DFS.c:192
char * cont
Definition: aiori-DFS.c:66
#define NULL
Definition: iordef.h:70