IOR
aiori-RADOS.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 * *
6 * (C) 2015 The University of Chicago *
7 * *
8 * See COPYRIGHT in top-level directory. *
9 * *
10 ********************************************************************************
11 *
12 * Implement abstract I/O interface for RADOS.
13 *
14 \******************************************************************************/
15 
16 #ifdef HAVE_CONFIG_H
17 # include "config.h"
18 #endif
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/stat.h>
23 #include <errno.h>
24 #include <rados/librados.h>
25 
26 #include "ior.h"
27 #include "iordef.h"
28 #include "aiori.h"
29 #include "utilities.h"
30 
31 #define RADOS_ERR(__err_str, __ret) do { \
32  errno = -__ret; \
33  ERR(__err_str); \
34 } while(0)
35 
36 /**************************** P R O T O T Y P E S *****************************/
37 
38 static void RADOS_Initialize(aiori_mod_opt_t *);
39 static void RADOS_Finalize(aiori_mod_opt_t *);
40 static aiori_fd_t *RADOS_Create(char *, int flags, aiori_mod_opt_t *);
41 static aiori_fd_t *RADOS_Open(char *, int flags, aiori_mod_opt_t *);
44 static void RADOS_Close(aiori_fd_t *, aiori_mod_opt_t *);
45 static void RADOS_Delete(char *, aiori_mod_opt_t *);
46 static void RADOS_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
48 static int RADOS_StatFS(const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *);
49 static int RADOS_MkDir(const char *, mode_t, aiori_mod_opt_t *);
50 static int RADOS_RmDir(const char *, aiori_mod_opt_t *);
51 static int RADOS_Access(const char *, int, aiori_mod_opt_t *);
52 static int RADOS_Stat(const char *, struct stat *, aiori_mod_opt_t *);
54 
55 /************************** O P T I O N S *****************************/
56 typedef struct {
57  char * user;
58  char * conf;
59  char * pool;
61 /***************************** F U N C T I O N S ******************************/
62 
63 static option_help * RADOS_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values){
64  RADOS_options_t * o = malloc(sizeof(RADOS_options_t));
65 
66  if (init_values != NULL){
67  memcpy(o, init_values, sizeof(RADOS_options_t));
68  }else{
69  memset(o, 0, sizeof(RADOS_options_t));
70  /* initialize the options properly */
71  o->user = NULL;
72  o->conf = NULL;
73  o->pool = NULL;
74  }
75 
76  *init_backend_options = (aiori_mod_opt_t*) o;
77 
78  option_help h [] = {
79  {0, "rados.user", "Username for the RADOS cluster", OPTION_OPTIONAL_ARGUMENT, 's', & o->user},
80  {0, "rados.conf", "Config file for the RADOS cluster", OPTION_OPTIONAL_ARGUMENT, 's', & o->conf},
81  {0, "rados.pool", "RADOS pool to use for I/O", OPTION_OPTIONAL_ARGUMENT, 's', & o->pool},
83  };
84  option_help * help = malloc(sizeof(h));
85  memcpy(help, h, sizeof(h));
86  return help;
87 }
88 
89 /************************** D E C L A R A T I O N S ***************************/
91  .name = "RADOS",
92  .name_legacy = NULL,
93  .initialize = RADOS_Initialize,
94  .finalize = RADOS_Finalize,
95  .create = RADOS_Create,
96  .open = RADOS_Open,
97  .xfer = RADOS_Xfer,
98  .close = RADOS_Close,
99  .delete = RADOS_Delete,
100  .get_version = aiori_get_version,
101  .fsync = RADOS_Fsync,
102  .get_file_size = RADOS_GetFileSize,
103  .statfs = RADOS_StatFS,
104  .mkdir = RADOS_MkDir,
105  .rmdir = RADOS_RmDir,
106  .access = RADOS_Access,
107  .stat = RADOS_Stat,
108  .get_options = RADOS_options,
109  .check_params = RADOS_check_params
110 };
111 
112 static rados_t rados_cluster; /* RADOS cluster handle */
113 static rados_ioctx_t rados_ioctx; /* I/O context for our pool in the RADOS cluster */
114 
115 /***************************** F U N C T I O N S ******************************/
116 
118  RADOS_options_t *o = (RADOS_options_t*) options;
119  if (!(o->user))
120  ERR("RADOS user must be specified");
121  if (!(o->conf))
122  ERR("RADOS conf must be specified");
123  if (!(o->pool))
124  ERR("RADOS pool must be specified");
125  return 0;
126 }
127 
129 {
130  RADOS_options_t *o = (RADOS_options_t*) options;
131  int ret;
132 
133  /* create RADOS cluster handle */
134  ret = rados_create(&rados_cluster, o->user);
135  if (ret)
136  RADOS_ERR("unable to create RADOS cluster handle", ret);
137 
138  /* set the handle using the Ceph config */
139  ret = rados_conf_read_file(rados_cluster, o->conf);
140  if (ret)
141  RADOS_ERR("unable to read RADOS config file", ret);
142 
143  /* connect to the RADOS cluster */
144  ret = rados_connect(rados_cluster);
145  if (ret)
146  RADOS_ERR("unable to connect to the RADOS cluster", ret);
147 
148  /* create an io context for the pool we are operating on */
149  ret = rados_ioctx_create(rados_cluster, o->pool, &rados_ioctx);
150  if (ret)
151  RADOS_ERR("unable to create an I/O context for the RADOS cluster", ret);
152 
153  return;
154 }
155 
157 {
158  /* ioctx destroy */
159  rados_ioctx_destroy(rados_ioctx);
160 
161  /* shutdown */
162  rados_shutdown(rados_cluster);
163 }
164 
165 static aiori_fd_t *RADOS_Create_Or_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
166 {
167  int ret;
168  char *oid;
169 
170  oid = strdup(testFileName);
171  if (!oid)
172  ERR("unable to allocate RADOS oid");
173 
174  if (flags & IOR_CREAT)
175  {
176  rados_write_op_t create_op;
177  int rados_create_flag;
178 
179  if (flags & IOR_EXCL)
180  rados_create_flag = LIBRADOS_CREATE_EXCLUSIVE;
181  else
182  rados_create_flag = LIBRADOS_CREATE_IDEMPOTENT;
183 
184  /* create a RADOS "write op" for creating the object */
185  create_op = rados_create_write_op();
186  rados_write_op_create(create_op, rados_create_flag, NULL);
187  ret = rados_write_op_operate(create_op, rados_ioctx, oid,
188  NULL, 0);
189  rados_release_write_op(create_op);
190  if (ret)
191  RADOS_ERR("unable to create RADOS object", ret);
192  }
193  else
194  {
195  /* XXX actually, we should probably assert oid existence here? */
196  }
197 
198  return (aiori_fd_t *)oid;
199 }
200 
201 static aiori_fd_t *RADOS_Create(char *testFileName, int flags, aiori_mod_opt_t *param)
202 {
203  return RADOS_Create_Or_Open(testFileName, flags, param);
204 }
205 
206 static aiori_fd_t *RADOS_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
207 {
208  return RADOS_Create_Or_Open(testFileName, flags, param);
209 }
210 
211 static IOR_offset_t RADOS_Xfer(int access, aiori_fd_t *fd, IOR_size_t * buffer,
212  IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * param)
213 {
214  int ret;
215  char *oid = (char *)fd;
216 
217  if (access == WRITE)
218  {
219  rados_write_op_t write_op;
220 
221  write_op = rados_create_write_op();
222  rados_write_op_write(write_op, (const char *)buffer,
223  length, offset);
224  ret = rados_write_op_operate(write_op, rados_ioctx,
225  oid, NULL, 0);
226  rados_release_write_op(write_op);
227  if (ret)
228  RADOS_ERR("unable to write RADOS object", ret);
229  }
230  else /* READ */
231  {
232  int read_ret;
233  size_t bytes_read;
234  rados_read_op_t read_op;
235 
236  read_op = rados_create_read_op();
237  rados_read_op_read(read_op, offset, length, (char *)buffer,
238  &bytes_read, &read_ret);
239  ret = rados_read_op_operate(read_op, rados_ioctx, oid, 0);
240  rados_release_read_op(read_op);
241  if (ret || read_ret || ((IOR_offset_t)bytes_read != length))
242  RADOS_ERR("unable to read RADOS object", ret);
243  }
244 
245  return length;
246 }
247 
248 static void RADOS_Fsync(aiori_fd_t *fd, aiori_mod_opt_t * param)
249 {
250  return;
251 }
252 
253 static void RADOS_Close(aiori_fd_t *fd, aiori_mod_opt_t * param)
254 {
255  char *oid = (char *)fd;
256 
257  /* object does not need to be "closed" */
258  free(oid);
259 
260  return;
261 }
262 
263 static void RADOS_Delete(char *testFileName, aiori_mod_opt_t * param)
264 {
265  int ret;
266  char *oid = testFileName;
267  rados_write_op_t remove_op;
268 
269  /* remove the object */
270  remove_op = rados_create_write_op();
271  rados_write_op_remove(remove_op);
272  ret = rados_write_op_operate(remove_op, rados_ioctx,
273  oid, NULL, 0);
274  rados_release_write_op(remove_op);
275  if (ret)
276  RADOS_ERR("unable to remove RADOS object", ret);
277 
278  return;
279 }
280 
281 static IOR_offset_t RADOS_GetFileSize(aiori_mod_opt_t *param, char *testFileName)
282 {
283  int ret;
284  char *oid = testFileName;
285  rados_read_op_t stat_op;
286  uint64_t oid_size;
287  int stat_ret;
288  IOR_offset_t aggSizeFromStat, tmpMin, tmpMax, tmpSum;
289 
290  /* stat the object */
291  stat_op = rados_create_read_op();
292  rados_read_op_stat(stat_op, &oid_size, NULL, &stat_ret);
293  ret = rados_read_op_operate(stat_op, rados_ioctx, oid, 0);
294  rados_release_read_op(stat_op);
295  if (ret || stat_ret)
296  RADOS_ERR("unable to stat RADOS object", stat_ret);
297  aggSizeFromStat = oid_size;
298 
299  return aggSizeFromStat;
300 }
301 
302 static int RADOS_StatFS(const char *oid, ior_aiori_statfs_t *stat_buf,
303  aiori_mod_opt_t * param)
304 {
305  WARN("statfs not supported in RADOS backend!");
306  return -1;
307 }
308 
309 static int RADOS_MkDir(const char *oid, mode_t mode, aiori_mod_opt_t * param)
310 {
311  WARN("mkdir not supported in RADOS backend!");
312  return -1;
313 }
314 
315 static int RADOS_RmDir(const char *oid, aiori_mod_opt_t * param)
316 {
317  WARN("rmdir not supported in RADOS backend!");
318  return -1;
319 }
320 
321 static int RADOS_Access(const char *oid, int mode, aiori_mod_opt_t * param)
322 {
323  rados_read_op_t read_op;
324  int ret;
325  int prval;
326  uint64_t oid_size;
327 
328  /* use read_op stat to check for oid existence */
329  read_op = rados_create_read_op();
330  rados_read_op_stat(read_op, &oid_size, NULL, &prval);
331  ret = rados_read_op_operate(read_op, rados_ioctx, oid, 0);
332  rados_release_read_op(read_op);
333 
334  if (ret | prval)
335  return -1;
336  else
337  return 0;
338 }
339 
340 static int RADOS_Stat(const char *oid, struct stat *buf, aiori_mod_opt_t * param)
341 {
342  WARN("stat not supported in RADOS backend!");
343  return -1;
344 }
static IOR_offset_t RADOS_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:211
static int RADOS_Access(const char *, int, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:321
#define LAST_OPTION
Definition: option.h:39
static IOR_offset_t RADOS_GetFileSize(aiori_mod_opt_t *, char *)
Definition: aiori-RADOS.c:281
static int RADOS_MkDir(const char *, mode_t, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:309
static aiori_fd_t * RADOS_Create_Or_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
Definition: aiori-RADOS.c:165
static void RADOS_Delete(char *, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:263
static void RADOS_Initialize(aiori_mod_opt_t *)
Definition: aiori-RADOS.c:128
static rados_t rados_cluster
Definition: aiori-RADOS.c:112
struct benchmark_options o
Definition: md-workbench.c:133
#define RADOS_ERR(__err_str, __ret)
Definition: aiori-RADOS.c:31
static aiori_fd_t * RADOS_Create(char *, int flags, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:201
static int RADOS_Stat(const char *, struct stat *, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:340
ior_aiori_t rados_aiori
Definition: aiori-RADOS.c:90
static void RADOS_Fsync(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:248
static int RADOS_StatFS(const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:302
#define WRITE
Definition: iordef.h:100
#define IOR_CREAT
Definition: aiori.h:32
#define IOR_EXCL
Definition: aiori.h:34
char * aiori_get_version()
Definition: aiori.c:235
static option_help options[]
Definition: aiori-CEPHFS.c:59
static aiori_fd_t * RADOS_Open(char *, int flags, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:206
static rados_ioctx_t rados_ioctx
Definition: aiori-RADOS.c:113
#define WARN(MSG)
Definition: aiori-debug.h:45
static int RADOS_RmDir(const char *, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:315
static int RADOS_check_params(aiori_mod_opt_t *options)
Definition: aiori-RADOS.c:117
static option_help * RADOS_options(aiori_mod_opt_t **init_backend_options, aiori_mod_opt_t *init_values)
Definition: aiori-RADOS.c:63
static void RADOS_Finalize(aiori_mod_opt_t *)
Definition: aiori-RADOS.c:156
long long int IOR_size_t
Definition: iordef.h:124
static void RADOS_Close(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-RADOS.c:253
#define ERR(MSG)
Definition: aiori-debug.h:75
char * name
Definition: aiori.h:88
long long int IOR_offset_t
Definition: iordef.h:123
#define NULL
Definition: iordef.h:84