Whamcloud - gitweb
LU-6245 tests: remove libcfs.h from test applications
[fs/lustre-release.git] / lustre / tests / iam_ut.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lustre/tests/iam_ut.c
35  *
36  * iam_ut.c
37  * iam unit-tests
38  *
39  * Author: Nikita Danilov <nikita@clusterfs.com>
40  */
41
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <fcntl.h>
46 #include <string.h>
47 #include <errno.h>
48 #include <assert.h>
49
50 #include <sys/types.h>
51
52 #ifdef HAVE_ENDIAN_H
53 #include <endian.h>
54 #endif
55
56 enum {
57         /*
58          * Maximal format name length.
59          */
60         DX_FMT_NAME_LEN    = 16
61 };
62
63 struct iam_uapi_info {
64         __u16 iui_keysize;
65         __u16 iui_recsize;
66         __u16 iui_ptrsize;
67         __u16 iui_height;
68         char  iui_fmt_name[DX_FMT_NAME_LEN];
69 };
70
71 struct iam_uapi_op {
72         void *iul_key;
73         void *iul_rec;
74 };
75
76 struct iam_uapi_it {
77         struct iam_uapi_op iui_op;
78         __u16              iui_state;
79 };
80
81 enum iam_ioctl_cmd {
82         IAM_IOC_INIT     = _IOW('i', 1, struct iam_uapi_info),
83         IAM_IOC_GETINFO  = _IOR('i', 2, struct iam_uapi_info),
84         IAM_IOC_INSERT   = _IOR('i', 3, struct iam_uapi_op),
85         IAM_IOC_LOOKUP   = _IOWR('i', 4, struct iam_uapi_op),
86         IAM_IOC_DELETE   = _IOR('i', 5, struct iam_uapi_op),
87         IAM_IOC_IT_START = _IOR('i', 6, struct iam_uapi_it),
88         IAM_IOC_IT_NEXT  = _IOW('i', 7, struct iam_uapi_it),
89         IAM_IOC_IT_STOP  = _IOR('i', 8, struct iam_uapi_it),
90
91         IAM_IOC_POLYMORPH = _IOR('i', 9, unsigned long)
92 };
93
94 static void usage(void)
95 {
96         printf("usage: iam_ut [-v] [-h] file\n");
97 }
98
99 static int doop(int fd, const void *key, const void *rec,
100                 int cmd, const char *name)
101 {
102         int result;
103
104         struct iam_uapi_op op = {
105                 .iul_key = key,
106                 .iul_rec = rec
107         };
108         result = ioctl(fd, cmd, &op);
109         if (result != 0)
110                 fprintf(stderr, "ioctl(%s): %i/%i (%m)\n", name, result, errno);
111         return result;
112 }
113
114 static int doit(int fd, const void *key, const void *rec,
115                 int cmd, const char *name)
116 {
117         int result;
118
119         struct iam_uapi_it it = {
120                 .iui_op = {
121                         .iul_key = key,
122                         .iul_rec = rec
123                 },
124                 .iui_state = 0
125         };
126
127         assert((void *)&it == (void *)&it.iui_op);
128
129         result = ioctl(fd, cmd, &it);
130         if (result != 0)
131                 fprintf(stderr, "ioctl(%s): %i/%i (%m)\n", name, result, errno);
132         else
133                 result = it.iui_state;
134         return result;
135 }
136
137 static int insert(int fd, const void *key, const void *rec)
138 {
139         return doop(fd, key, rec, IAM_IOC_INSERT, "IAM_IOC_INSERT");
140 }
141
142 static int lookup(int fd, const void *key, void *rec)
143 {
144         return doop(fd, key, rec, IAM_IOC_LOOKUP, "IAM_IOC_LOOKUP");
145 }
146
147 static int delete(int fd, const void *key, void *rec)
148 {
149         return doop(fd, key, rec, IAM_IOC_DELETE, "IAM_IOC_DELETE");
150 }
151
152 static int rec_is_nul_term(int recsize)
153 {
154         return recsize == 255;
155 }
156
157 static void print_rec(const unsigned char *rec, int nr)
158 {
159         int i;
160
161         for (i = 0; i < nr; ++i) {
162                 printf("%c", rec[i]);
163                 if (rec_is_nul_term(nr) && rec[i] == 0)
164                         break;
165         }
166         printf("|    |");
167         for (i = 0; i < nr; ++i) {
168                 printf("%x", rec[i]);
169                 if (rec_is_nul_term(nr) && rec[i] == 0)
170                         break;
171         }
172         printf("\n");
173 }
174
175 enum op {
176         OP_TEST,
177         OP_INSERT,
178         OP_LOOKUP,
179         OP_DELETE,
180         OP_IT_START,
181         OP_IT_NEXT,
182         OP_IT_STOP
183 };
184
185 unsigned char hex2dec(unsigned char hex)
186 {
187         if ('0' <= hex && hex <= '9') {
188                 return hex - '0';
189         } else if ('a' <= hex && hex <= 'f') {
190                 return hex - 'a' + 10;
191         } else if ('A' <= hex && hex <= 'F') {
192                 return hex - 'A' + 10;
193         } else {
194                 fprintf(stderr, "Wrong hex digit '%c'\n", hex);
195                 exit(1);
196         }
197 }
198
199 unsigned char *packdigit(unsigned char *number)
200 {
201         unsigned char *area;
202         unsigned char *scan;
203
204         area = calloc(strlen(number) / 2 + 2, sizeof area[0]);
205         if (area != NULL) {
206                 for (scan = area; *number; number += 2, scan++)
207                         *scan = (hex2dec(number[0]) << 4) | hex2dec(number[1]);
208         }
209         return area;
210 }
211
212 int main(int argc, char **argv)
213 {
214         int i;
215         int rc;
216         int opt;
217         int keysize;
218         int recsize;
219         int N = 0x10000;
220         int verbose = 0;
221         int doinit = 1;
222         int keynul = 1;
223         int recnul = 1;
224
225         void *(*copier)(void *, void *, size_t);
226
227         enum op op;
228
229         char *key;
230         char *rec;
231
232         char *key_opt;
233         char *rec_opt;
234
235         struct iam_uapi_info ua;
236
237         setbuf(stdout, NULL);
238         setbuf(stderr, NULL);
239
240         key_opt = NULL;
241         rec_opt = NULL;
242
243         op = OP_TEST;
244
245         do {
246                 opt = getopt(argc, argv, "vilk:K:N:r:R:dsSnP:");
247                 switch (opt) {
248                 case 'v':
249                         verbose++;
250                 case -1:
251                         break;
252                 case 'K':
253                         key_opt = packdigit(optarg);
254                         keynul = 0;
255                         break;
256                 case 'k':
257                         key_opt = optarg;
258                         break;
259                 case 'N':
260                         N = atoi(optarg);
261                         break;
262                 case 'R':
263                         rec_opt = packdigit(optarg);
264                         recnul = 0;
265                         break;
266                 case 'r':
267                         rec_opt = optarg;
268                         break;
269                 case 'i':
270                         op = OP_INSERT;
271                         break;
272                 case 'l':
273                         op = OP_LOOKUP;
274                         break;
275                 case 'd':
276                         op = OP_DELETE;
277                         break;
278                 case 's':
279                         op = OP_IT_START;
280                         break;
281                 case 'S':
282                         op = OP_IT_STOP;
283                         doinit = 0;
284                         break;
285                 case 'n':
286                         op = OP_IT_NEXT;
287                         doinit = 0;
288                         break;
289                 case 'P': {
290                         unsigned long mode;
291
292                         mode = strtoul(optarg, NULL, 0);
293                         rc = ioctl(0, IAM_IOC_POLYMORPH, mode);
294                         if (rc == -1)
295                                 perror("IAM_IOC_POLYMORPH");
296                         return 0;
297                 }
298                 case '?':
299                 default:
300                         fprintf(stderr, "Unable to parse options.");
301                 case 'h':
302                         usage();
303                         return 0;
304                 }
305         } while (opt != -1);
306
307         if (doinit) {
308                 rc = ioctl(0, IAM_IOC_INIT, &ua);
309                 if (rc != 0) {
310                         fprintf(stderr, "ioctl(IAM_IOC_INIT): %i (%m)\n", rc);
311                         return 1;
312                 }
313         }
314         rc = ioctl(0, IAM_IOC_GETINFO, &ua);
315         if (rc != 0) {
316                 fprintf(stderr, "ioctl(IAM_IOC_GETATTR): %i (%m)\n", rc);
317                 return 1;
318         }
319
320         keysize = ua.iui_keysize;
321         recsize = ua.iui_recsize;
322         if (verbose > 0)
323                 printf("keysize: %i, recsize: %i, ptrsize: %i, "
324                        "height: %i, name: %s\n",
325                        keysize, recsize, ua.iui_ptrsize,
326                        ua.iui_height, ua.iui_fmt_name);
327
328         key = calloc(keysize + 1, sizeof key[0]);
329         rec = calloc(recsize + 1, sizeof rec[0]);
330
331         if (key == NULL || rec == NULL) {
332                 fprintf(stderr, "cannot allocate memory\n");
333                 rc = 1;
334                 goto out;
335         }
336
337         copier = keynul ? &strncpy : &memcpy;
338         copier(key, key_opt ? : "RIVERRUN", keysize + 1);
339         if (keynul == 0) {
340                 free(key_opt);
341                 key_opt = NULL;
342         }
343         copier = recnul ? &strncpy : &memcpy;
344         copier(rec, rec_opt ? : "PALEFIRE", recsize + 1);
345         if (recnul == 0) {
346                 free(rec_opt);
347                 rec_opt = NULL;
348         }
349
350         if (op == OP_INSERT) {
351                 rc = doop(0, key, rec, IAM_IOC_INSERT, "IAM_IOC_INSERT");
352                 goto out;
353         } else if (op == OP_DELETE) {
354                 rc = doop(0, key, rec, IAM_IOC_DELETE, "IAM_IOC_DELETE");
355                 goto out;
356         } else if (op == OP_LOOKUP) {
357                 rc = doop(0, key, rec, IAM_IOC_LOOKUP, "IAM_IOC_LOOKUP");
358                 if (rc == 0)
359                         print_rec(rec, recsize);
360                 goto out;
361         } else if (op == OP_IT_START) {
362                 rc = doop(0, key, rec, IAM_IOC_IT_START, "IAM_IOC_IT_START");
363                 if (rc == 0) {
364                         print_rec(key, keysize);
365                         print_rec(rec, recsize);
366                 }
367                 goto out;
368         } else if (op == OP_IT_STOP) {
369                 rc = doop(0, key, rec, IAM_IOC_IT_STOP, "IAM_IOC_IT_STOP");
370                 goto out;
371         } else if (op == OP_IT_NEXT) {
372                 rc = doop(0, key, rec, IAM_IOC_IT_NEXT, "IAM_IOC_IT_NEXT");
373                 if (rc == 0) {
374                         print_rec(key, keysize);
375                         print_rec(rec, recsize);
376                 }
377                 goto out;
378         }
379
380         rc = insert(0, key, rec);
381         if (rc != 0) {
382                 rc = 1;
383                 goto out;
384         }
385
386         rc = insert(0, "DAEDALUS", "FINNEGAN");
387         if (rc != 0) {
388                 rc = 1;
389                 goto out;
390         }
391
392         rc = insert(0, "DAEDALUS", "FINNEGAN");
393         if (errno != EEXIST) {
394                 if (rc == 0)
395                         fprintf(stderr, "Duplicate key not detected!\n");
396                 if (rc != 0) {
397                         rc = 1;
398                         goto out;
399                 }
400         }
401
402         rc = lookup(0, "RIVERRUN", rec);
403         if (rc != 0) {
404                 rc = 1;
405                 goto out;
406         }
407
408         print_rec(rec, recsize);
409
410         for (i = 0; i < N; ++i) {
411                 memset(key, 0, keysize + 1);
412                 memset(rec, 0, recsize + 1);
413                 snprintf(key, keysize + 1, "y-%x-x", i);
414                 snprintf(rec, recsize + 1, "p-%x-q", 1000 - i);
415                 rc = insert(0, key, rec);
416                 if (rc != 0) {
417                         rc = 1;
418                         goto out;
419                 }
420                 if (verbose > 1)
421                         printf("key %#x inserted\n", i);
422         }
423
424         rc = 0;
425
426 out:
427         if (key) {
428                 free(key);
429         }
430         if (rec) {
431                 free(rec);
432         }
433         return rc;
434 }