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