KMR
kmrfefs.c
Go to the documentation of this file.
1 /* kmrfefs.c (2014-02-04) */
2 /* Copyright (C) 2012-2016 RIKEN AICS */
3 
4 /** \file kmrfefs.c Lustre File-System (or Fujitsu FEFS) Support. The
5  definitions of IOCTL are changed to match the Fujitsu Extended
6  File-System (FEFS) version of the Lustre. THERE IS NO WARRANTY
7  THE VALUES ARE OK. This only works with Linux. */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 //#include <stropts.h>
16 #include <stdint.h>
17 #include <limits.h>
18 #include <assert.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/ioctl.h>
22 #if defined(__SVR4)
23 #include <sys/ioccom.h>
24 #endif
25 #include "kmrfefs.h"
26 
27 #define MIN(a,b) (((a)<(b))?(a):(b))
28 #define MAX(a,b) (((a)>(b))?(a):(b))
29 
30 /* Magic Numbers and IOCTL (structures). LOV_USER_MAGIC_OST_INDEX is
31  Fujitsu FEFS extension. */
32 
33 #define KMR_LOV_MAGIC_V1 0x0BD10BD0
34 #define KMR_LOV_MAGIC_V3 0x0BD30BD0
35 #define KMR_LOV_USER_MAGIC_OST_INDEX 0x0BD70BD0
36 #define KMR_LOV_PATTERN_RAID0 0x001
37 
38 #define KMR_OST_MAX_PRECREATE 20000
39 
40 struct kmr_lov_md {
41  uint32_t magic;
42  uint32_t pattern;
43  uint64_t id;
44  uint64_t gr;
45  uint32_t stripe_size;
46  uint16_t stripe_count;
47  uint16_t stripe_offset;
48 };
49 
50 struct kmr_lov_ost {
51  uint64_t id;
52  uint64_t gr;
53  uint32_t gen;
54  uint32_t idx;
55 };
56 
58  struct kmr_lov_md md;
59  struct kmr_lov_ost o[KMR_OST_MAX_PRECREATE];
60 };
61 
63  struct stat st;
64  struct kmr_lov_md md;
65  uint16_t o[KMR_OST_MAX_PRECREATE];
66 };
67 
68 #define KMR_IOC_MDC_GETFILESTRIPE _IOWR('i', 21, struct kmr_lov_md_ost *)
69 #define KMR_IOC_MDC_GETINFO _IOWR('i', 23, struct kmr_lov_md_ostidx *)
70 
71 /** Gets the OBDIDX information on the file or directory. FILE be
72  null for directory. It fills STRIPE, which contains stripe size,
73  count, offset, and an obdidx array. It returns non-zero on error:
74  1 for unsupported OS, 2 malloc failure, 3 open failure, 4 ioctl
75  failure (not Lustre FS), 5 bad magic, 6 bad version (V3), and 7
76  bad pattern. Note the structure and the _IOWR definitions are
77  changed to match the arguments of the Fujitsu FEFS. See the
78  source "cb_getstripe()", near "ioctl(_,LL_IOC_LOV_GETSTRIPE,...)"
79  in "liblustreapi.c". */
80 
81 int
82 kmr_fefs_get_stripe(const char *dir, const char *file,
83  struct kmr_fefs_stripe *stripe,
84  int *err, _Bool debug_and_dump)
85 {
86 #if defined(__linux__)
87  int cc;
88  size_t sz = MAX(sizeof(struct kmr_lov_md_ost),
89  sizeof(struct kmr_lov_md_ostidx));
90  void *b = malloc(sz);
91  if (b == 0) {
92  *err = errno;
93  if (debug_and_dump) {
94  perror("malloc(lov_user_md)");
95  }
96  /* malloc fails. */
97  return 2;
98  }
99  struct kmr_lov_md_ost *lov1 = b;
100  struct kmr_lov_md_ostidx *lov7 = b;
101  int fd = -1;
102  do {
103  fd = open(dir, O_RDONLY);
104  } while (fd == -1 && errno == EINTR);
105  if (fd == -1) {
106  *err = errno;
107  if (debug_and_dump) {
108  char ee[80];
109  snprintf(ee, sizeof(ee), "open(%s)", dir);
110  perror(ee);
111  }
112  /* open fails. */
113  return 3;
114  }
115  do {
116  if (file != 0) {
117  strcpy((void *)lov1, file);
118  cc = ioctl(fd, KMR_IOC_MDC_GETFILESTRIPE, (void *)lov1);
119  } else {
120  cc = ioctl(fd, KMR_IOC_MDC_GETINFO, (void *)lov7);
121  }
122  } while (cc == -1 && errno == EINTR);
123  if (cc == -1) {
124  *err = errno;
125  if (debug_and_dump) {
126  char ee[80];
127  snprintf(ee, sizeof(ee), "ioctl(%s|%s)",
128  dir, (file == 0 ? "." : file));
129  perror(ee);
130  }
131  /* ioctl fails (Not Lustre FS). */
132  return 4;
133  }
134  cc = close(fd);
135  /*ignore*/
136  struct kmr_lov_md *md;
137  if (file != 0) {
138  md = &lov1->md;
139  } else {
140  md = &lov7->md;
141  }
142  if (!(md->magic == KMR_LOV_MAGIC_V1
143  || md->magic == KMR_LOV_MAGIC_V3
144  || md->magic == KMR_LOV_USER_MAGIC_OST_INDEX)) {
145  /* Not Lustre FS. */
146  if (debug_and_dump) {
147  char ee[80];
148  snprintf(ee, sizeof(ee),
149  "Not Lustre FS (%s/%s), bad magic (%x)",
150  dir, (file == 0 ? "." : file), md->magic);
151  fprintf(stderr, "%s\n", ee);
152  }
153  /* Bad magic. */
154  *err = 0;
155  return 5;
156  }
157  if (md->magic == KMR_LOV_MAGIC_V3) {
158  if (debug_and_dump) {
159  char ee[80];
160  snprintf(ee, sizeof(ee),
161  "Lustre FS (%s/%s), bad version (%x)",
162  dir, (file == 0 ? "." : file), md->magic);
163  fprintf(stderr, "%s\n", ee);
164  }
165  /* Bad version. */
166  *err = 0;
167  return 6;
168  }
169  assert(md->magic == KMR_LOV_MAGIC_V1
170  || md->magic == KMR_LOV_USER_MAGIC_OST_INDEX);
171  if (md->pattern != KMR_LOV_PATTERN_RAID0) {
172  if (debug_and_dump) {
173  char ee[80];
174  snprintf(ee, sizeof(ee),
175  "Lustre FS (%s/%s), bad pattern (%x)",
176  dir, (file == 0 ? "." : file), md->pattern);
177  fprintf(stderr, "%s\n", ee);
178  }
179  /* Bad pattern. */
180  *err = 0;
181  return 7;
182  }
183  struct kmr_lov_ost *o1 = &lov1->o[0];
184  uint16_t *o7 = &lov7->o[0];
185  if (debug_and_dump) {
186  fprintf(stderr, "lov_user_md(%s)=\n", (file != 0 ? "file" : "dir"));
187  fprintf(stderr, "magic=%x\n", md->magic);
188  fprintf(stderr, "pattern=%x\n", md->pattern);
189  fprintf(stderr, "id=%lx\n", md->id);
190  fprintf(stderr, "gr=%lx\n", md->gr);
191  fprintf(stderr, "stripe_size=%ud\n", md->stripe_size);
192  fprintf(stderr, "stripe_count=%d\n", md->stripe_count);
193  fprintf(stderr, "stripe_offset=%d\n", md->stripe_offset);
194  if (md->magic == KMR_LOV_MAGIC_V1) {
195  for (int i = 0; i < md->stripe_count; i++) {
196  fprintf(stderr, "[%d] id=%lud gr=%lud gen=%ud idx=%ud\n",
197  i, o1[i].id, o1[i].gr, o1[i].gen, o1[i].idx);
198  }
199  } else if (md->magic == KMR_LOV_USER_MAGIC_OST_INDEX) {
200  for (int i = 0; i < md->stripe_count; i++) {
201  fprintf(stderr, "[%d] idx=%d\n", i, o7[i]);
202  }
203  } else {
204  assert(0);
205  }
206  }
207  assert(md->stripe_count < 20000);
208  stripe->s.size = md->stripe_size;
209  stripe->s.count = md->stripe_count;
210  stripe->s.offset = md->stripe_offset;
211  if (md->magic == KMR_LOV_MAGIC_V1) {
212  for (int i = 0; i < md->stripe_count; i++) {
213  assert(o1[i].idx < USHRT_MAX);
214  stripe->obdidx[i] = (uint16_t)o1[i].idx;
215  }
216  } else if (md->magic == KMR_LOV_USER_MAGIC_OST_INDEX) {
217  for (int i = 0; i < md->stripe_count; i++) {
218  stripe->obdidx[i] = o7[i];
219  }
220  } else {
221  assert(0);
222  }
223  free(b);
224  return 0;
225 #elif defined(__APPLE__) && defined(__MACH__)
226  /* OS unsupported */
227  return 1;
228 #elif defined(__SVR4)
229  /* OS unsupported */
230  return 1;
231 #else
232  /* OS unsupported */
233  return 1;
234 #endif
235 }
236 
237 /* TEST CODE. */
238 
239 #ifdef KMRLUSTEST
240 
241 static int
242 kmr_readin(char *f, char *b, int sz)
243 {
244  int cc;
245  int fd = open(f, O_RDONLY, 0);
246  assert(fd != -1);
247  int ii = 0;
248  while (ii < sz) {
249  cc = read(fd, &b[ii], (sz - ii));
250  assert(cc != -1);
251  if (cc == 0) {
252  break;
253  }
254  ii += cc;
255  }
256  close(fd);
257  if (ii < sz) {
258  b[ii] = 0;
259  } else {
260  b[sz - 1] = 0;
261  }
262  return 0;
263 }
264 
265 int
266 main(int argc, char **argv)
267 {
268  static char b[8 * 1024];
269  int cc;
270  MPI_Init(&argc, &argv);
271  int nprocs, rank;
272  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
273  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
274  MPI_Barrier(MPI_COMM_WORLD);
275 
276  struct kmr_fefs_stripe stripe;
277 
278  if (rank == 0) {
279  printf("print ost of shared directory on each rank.\n");
280  fflush(0);
281  }
282  usleep(200 * 1000);
283  MPI_Barrier(MPI_COMM_WORLD);
284 
285  for (int i = 0; i < nprocs; i++) {
286  if (rank == i) {
287  kmr_readin("/proc/tofu/position", b, sizeof(b));
288  printf("rank=%d position=%s\n", rank, b);
289 
290  cc = kmr_fefs_get_stripe(".", "a.out", &stripe, 0);
291  assert(cc == 0);
292  printf("[%04d] rankdirfile=./a.out stripe_count=%d\n",
293  rank, stripe.count);
294  for (int j = 0; j < stripe.count; j++) {
295  printf("[%04d] idx=%d\n", rank, stripe.obdidx[j]);
296  }
297  printf("\n");
298 
299  cc = kmr_fefs_get_stripe("..", 0, &stripe, 0);
300  assert(cc == 0);
301  printf("[%04d] sharedir=.. stripe_count=%d\n",
302  rank, stripe.count);
303  for (int j = 0; j < stripe.count; j++) {
304  printf("[%04d] idx=%d\n", rank, stripe.obdidx[j]);
305  }
306  printf("\n");
307  }
308  fflush(0);
309  usleep(200 * 1000);
310  MPI_Barrier(MPI_COMM_WORLD);
311  }
312 
313  if (rank == 0) {
314  int fd = open("../aho", O_WRONLY, O_CREAT, 0);
315  assert(fd != -1);
316  close(fd);
317 
318  cc = kmr_fefs_get_stripe("..", "aho", &stripe, 0);
319  assert(cc == 0);
320  printf("[%04d] sharedir=../aho stripe_count=%d\n",
321  rank, stripe.count);
322  for (int j = 0; j < stripe.count; j++) {
323  printf("[%04d] idx=%d\n", rank, stripe.obdidx[j]);
324  }
325  printf("\n");
326  }
327 
328  MPI_Barrier(MPI_COMM_WORLD);
329  MPI_Finalize();
330  return 0;
331 }
332 
333 #endif /*KMRLUSTEST*/
334 
335 /*
336 Copyright (C) 2012-2016 RIKEN AICS
337 This library is distributed WITHOUT ANY WARRANTY. This library can be
338 redistributed and/or modified under the terms of the BSD 2-Clause License.
339 */
Lustre Striping Information with OBDIDX.
Definition: kmrfefs.h:20
int kmr_fefs_get_stripe(const char *dir, const char *file, struct kmr_fefs_stripe *stripe, int *err, _Bool debug_and_dump)
Gets the OBDIDX information on the file or directory.
Definition: kmrfefs.c:82
Lustre File System (or Fujitsu FEFS) Support.