Whamcloud - gitweb
LU-6216 tests: compile fixes for PPC64, and for clang
[fs/lustre-release.git] / lustre / tests / llapi_hsm_test.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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22
23 /* Copyright 2014, 2015 Cray Inc, all rights reserved. */
24 /* Some portions are extracted from llapi_layout_test.c */
25
26 /* The purpose of this test is to check some HSM functions. HSM must
27  * be enabled before running it:
28  *   echo enabled > /proc/fs/lustre/mdt/lustre-MDT0000/hsm_control
29  */
30
31 /* All tests return 0 on success and non zero on error. The program will
32  * exit as soon a non zero error is returned. */
33
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <getopt.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <poll.h>
40 #include <time.h>
41
42 #include <lustre/lustreapi.h>
43
44 static char fsmountdir[PATH_MAX];      /* Lustre mountpoint */
45 static char *lustre_dir;               /* Test directory inside Lustre */
46
47 #define ERROR(fmt, ...)                                                 \
48         fprintf(stderr, "%s: %s:%d: %s: " fmt "\n",                     \
49                 program_invocation_short_name, __FILE__, __LINE__,      \
50                 __func__, ## __VA_ARGS__);
51
52 #define DIE(fmt, ...)                           \
53         do {                                    \
54                 ERROR(fmt, ## __VA_ARGS__);     \
55                 exit(EXIT_FAILURE);             \
56         } while (0)
57
58 #define ASSERTF(cond, fmt, ...)                                         \
59         do {                                                            \
60                 if (!(cond))                                            \
61                         DIE("assertion '%s' failed: "fmt,               \
62                             #cond, ## __VA_ARGS__);                     \
63         } while (0)                                                     \
64
65 #define PERFORM(testfn) \
66         do {                                                            \
67                 fprintf(stderr, "Starting test " #testfn " at %llu\n",  \
68                         (unsigned long long)time(NULL));                \
69                 testfn();                                               \
70                 fprintf(stderr, "Finishing test " #testfn " at %llu\n", \
71                        (unsigned long long)time(NULL));                 \
72         } while (0)
73
74 /* Register and unregister 2000 times. Ensures there is no fd leak
75  * since there is usually 1024 fd per process. */
76 int test1(void)
77 {
78         int i;
79         int rc;
80         struct hsm_copytool_private *ctdata;
81
82         for (i = 0; i < 2000; i++) {
83                 rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
84                                                  0, NULL, 0);
85                 ASSERTF(rc == 0,
86                         "llapi_hsm_copytool_register failed: %s, loop=%d",
87                         strerror(-rc), i);
88
89                 rc = llapi_hsm_copytool_unregister(&ctdata);
90                 ASSERTF(rc == 0,
91                         "llapi_hsm_copytool_unregister failed: %s, loop=%d",
92                         strerror(-rc), i);
93         }
94
95         return 0;
96 }
97
98 /* Re-register */
99 int test2(void)
100 {
101         int rc;
102         struct hsm_copytool_private *ctdata1;
103         struct hsm_copytool_private *ctdata2;
104
105         rc = llapi_hsm_copytool_register(&ctdata1, fsmountdir, 0, NULL, 0);
106         ASSERTF(rc == 0, "llapi_hsm_copytool_register failed: %s",
107                 strerror(-rc));
108
109         rc = llapi_hsm_copytool_register(&ctdata2, fsmountdir, 0, NULL, 0);
110         ASSERTF(rc == 0, "llapi_hsm_copytool_register failed: %s",
111                 strerror(-rc));
112
113         rc = llapi_hsm_copytool_unregister(&ctdata2);
114         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
115                 strerror(-rc));
116
117         rc = llapi_hsm_copytool_unregister(&ctdata1);
118         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
119                 strerror(-rc));
120
121         return 0;
122 }
123
124 /* Bad parameters to llapi_hsm_copytool_register(). */
125 int test3(void)
126 {
127         int rc;
128         struct hsm_copytool_private *ctdata;
129         int archives[33];
130
131         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 1, NULL, 0);
132         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
133                 strerror(-rc));
134
135         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 33, NULL, 0);
136         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
137                 strerror(-rc));
138
139         memset(archives, 1, sizeof(archives));
140         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 34, archives, 0);
141         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
142                 strerror(-rc));
143
144 #if 0
145         /* BUG? Should that fail or not? */
146         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, -1, NULL, 0);
147         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
148                 strerror(-rc));
149 #endif
150
151         memset(archives, -1, sizeof(archives));
152         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 1, archives, 0);
153         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
154                 strerror(-rc));
155
156         rc = llapi_hsm_copytool_register(&ctdata, "/tmp", 0, NULL, 0);
157         ASSERTF(rc == -ENOENT, "llapi_hsm_copytool_register error: %s",
158                 strerror(-rc));
159
160         return 0;
161 }
162
163 /* Bad parameters to llapi_hsm_copytool_unregister(). */
164 int test4(void)
165 {
166         int rc;
167
168         rc = llapi_hsm_copytool_unregister(NULL);
169         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_unregister error: %s",
170                 strerror(-rc));
171
172         return 0;
173 }
174
175 /* Test llapi_hsm_copytool_recv in non blocking mode */
176 int test5(void)
177 {
178         int rc;
179         int i;
180         struct hsm_copytool_private *ctdata;
181         struct hsm_action_list  *hal;
182         int msgsize;
183
184         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
185                                          0, NULL, O_NONBLOCK);
186         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
187                 strerror(-rc));
188
189         /* Hopefully there is nothing lingering */
190         for (i = 0; i < 1000; i++) {
191                 rc = llapi_hsm_copytool_recv(ctdata, &hal, &msgsize);
192                 ASSERTF(rc == -EWOULDBLOCK, "llapi_hsm_copytool_recv error: %s",
193                         strerror(-rc));
194         }
195
196         rc = llapi_hsm_copytool_unregister(&ctdata);
197         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
198                 strerror(-rc));
199
200         return 0;
201 }
202
203 /* Test llapi_hsm_copytool_recv with bogus parameters */
204 int test6(void)
205 {
206         struct hsm_copytool_private *ctdata;
207         struct hsm_action_list *hal;
208         int rc;
209         int msgsize;
210
211         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 0, NULL, 0);
212         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
213                 strerror(-rc));
214
215         rc = llapi_hsm_copytool_recv(NULL, &hal, &msgsize);
216         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
217                 strerror(-rc));
218
219         rc = llapi_hsm_copytool_recv(ctdata, NULL, &msgsize);
220         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
221                 strerror(-rc));
222
223         rc = llapi_hsm_copytool_recv(ctdata, &hal, NULL);
224         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
225                 strerror(-rc));
226
227         rc = llapi_hsm_copytool_recv(ctdata, NULL, NULL);
228         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
229                 strerror(-rc));
230
231         rc = llapi_hsm_copytool_unregister(&ctdata);
232         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
233                 strerror(-rc));
234
235         return 0;
236 }
237
238 /* Test polling (without actual traffic) */
239 int test7(void)
240 {
241         int rc;
242         struct hsm_copytool_private *ctdata;
243         struct hsm_action_list  *hal;
244         int msgsize;
245         int fd;
246         struct pollfd fds[1];
247
248         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
249                                          0, NULL, O_NONBLOCK);
250         ASSERTF(rc == 0, "llapi_hsm_copytool_register failed: %s",
251                 strerror(-rc));
252
253         fd = llapi_hsm_copytool_get_fd(ctdata);
254         ASSERTF(fd >= 0, "llapi_hsm_copytool_get_fd failed: %s",
255                 strerror(-rc));
256
257         /* Ensure it's read-only */
258         rc = write(fd, &rc, 1);
259         ASSERTF(rc == -1 && errno == EBADF, "write error: %d, %s",
260                 rc, strerror(errno));
261
262         rc = llapi_hsm_copytool_recv(ctdata, &hal, &msgsize);
263         ASSERTF(rc == -EWOULDBLOCK, "llapi_hsm_copytool_recv error: %s",
264                 strerror(-rc));
265
266         fds[0].fd = fd;
267         fds[0].events = POLLIN;
268         rc = poll(fds, 1, 10);
269         ASSERTF(rc == 0, "poll failed: %d, %s",
270                 rc, strerror(errno)); /* no event */
271
272         rc = llapi_hsm_copytool_unregister(&ctdata);
273         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
274                 strerror(-rc));
275
276         return 0;
277 }
278
279 /* Create the testfile of a given length. It returns a valid file
280  * descriptor. */
281 static char testfile[PATH_MAX];
282 static int create_testfile(size_t length)
283 {
284         int rc;
285         int fd;
286
287         rc = snprintf(testfile, sizeof(testfile), "%s/hsm_check_test",
288                       lustre_dir);
289         ASSERTF((rc > 0 && rc < sizeof(testfile)), "invalid name for testfile");
290
291         /* Remove old test file, if any. */
292         unlink(testfile);
293
294         /* Use truncate so we can create a file (almost) as big as we
295          * want, while taking 0 bytes of data. */
296         fd = creat(testfile, S_IRWXU);
297         ASSERTF(fd >= 0, "create failed for '%s': %s",
298                 testfile, strerror(errno));
299
300         rc = ftruncate(fd, length);
301         ASSERTF(rc == 0, "ftruncate failed for '%s': %s",
302                 testfile, strerror(errno));
303
304         return fd;
305 }
306
307 /* Test llapi_hsm_state_get. */
308 void test50(void)
309 {
310         struct hsm_user_state hus;
311         int rc;
312         int fd;
313
314         fd = create_testfile(100);
315
316         /* With fd variant */
317         rc = llapi_hsm_state_get_fd(fd, &hus);
318         ASSERTF(rc == 0, "llapi_hsm_state_get_fd failed: %s", strerror(-rc));
319         ASSERTF(hus.hus_states == 0, "state=%u", hus.hus_states);
320
321         rc = llapi_hsm_state_get_fd(fd, NULL);
322         ASSERTF(rc == -EFAULT, "llapi_hsm_state_get_fd error: %s",
323                 strerror(-rc));
324
325         rc = close(fd);
326         ASSERTF(rc == 0, "close failed: %s", strerror(errno));
327
328         /* Without fd */
329         rc = llapi_hsm_state_get(testfile, &hus);
330         ASSERTF(rc == 0, "llapi_hsm_state_get failed: %s", strerror(-rc));
331         ASSERTF(hus.hus_states == 0, "state=%u", hus.hus_states);
332
333         rc = llapi_hsm_state_get(testfile, NULL);
334         ASSERTF(rc == -EFAULT, "llapi_hsm_state_get error: %s",
335                 strerror(-rc));
336
337         memset(&hus, 0xaa, sizeof(hus));
338         rc = llapi_hsm_state_get(testfile, &hus);
339         ASSERTF(rc == 0, "llapi_hsm_state_get failed: %s", strerror(-rc));
340         ASSERTF(hus.hus_states == 0, "state=%u", hus.hus_states);
341         ASSERTF(hus.hus_archive_id == 0, "archive_id=%u", hus.hus_archive_id);
342         ASSERTF(hus.hus_in_progress_state == 0, "hus_in_progress_state=%u",
343                 hus.hus_in_progress_state);
344         ASSERTF(hus.hus_in_progress_action == 0, "hus_in_progress_action=%u",
345                 hus.hus_in_progress_action);
346 }
347
348 /* Test llapi_hsm_state_set. */
349 void test51(void)
350 {
351         int rc;
352         int fd;
353         int i;
354         struct hsm_user_state hus;
355
356         fd = create_testfile(100);
357
358         rc = llapi_hsm_state_set_fd(fd, 0, 0, 0);
359         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
360
361         /* Set archive id */
362         for (i = 0; i <= 32; i++) {
363                 rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, i);
364                 ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s",
365                         strerror(-rc));
366
367                 rc = llapi_hsm_state_get_fd(fd, &hus);
368                 ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s",
369                         strerror(-rc));
370                 ASSERTF(hus.hus_states == HS_EXISTS, "state=%u",
371                         hus.hus_states);
372                 ASSERTF(hus.hus_archive_id == i, "archive_id=%u, i=%d",
373                         hus.hus_archive_id, i);
374         }
375
376         /* Bugs following. This should not succeed. Builds the following file:
377          *
378          *   $ ../utils/lfs hsm_state /mnt/lustre/hsm_check_test
379          *
380          *   /mnt/lustre/hsm_check_test: (0x8008007d) released exists
381          *     archived never_release never_archive lost_from_hsm,
382          *     archive_id:-1789
383          */
384
385         /* Invalid archive numbers */
386         rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 33);
387         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
388
389         rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 151);
390         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
391
392         rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, -1789);
393         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
394
395         /* Setable + Unsettable flags */
396         rc = llapi_hsm_state_set_fd(fd, HS_DIRTY, 0, 0);
397         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
398
399         rc = llapi_hsm_state_set_fd(fd, 0, HS_DIRTY, 0);
400         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
401
402         rc = llapi_hsm_state_set_fd(fd, HS_ARCHIVED, 0, 0);
403         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
404
405         rc = llapi_hsm_state_set_fd(fd, HS_RELEASED, 0, 0);
406         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
407
408         rc = llapi_hsm_state_set_fd(fd, HS_NORELEASE, 0, 0);
409         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
410
411         rc = llapi_hsm_state_set_fd(fd, HS_NOARCHIVE, 0, 0);
412         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
413
414         rc = llapi_hsm_state_set_fd(fd, HS_LOST, 0, 0);
415         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
416
417         /* Bogus flags for good measure. */
418         rc = llapi_hsm_state_set_fd(fd, 0x00080000, 0, 0);
419         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
420
421         rc = llapi_hsm_state_set_fd(fd, 0x80000000, 0, 0);
422         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
423
424         close(fd);
425 }
426
427 /* Test llapi_hsm_current_action */
428 void test52(void)
429 {
430         int rc;
431         int fd;
432         struct hsm_current_action hca;
433
434         /* No fd equivalent, so close it. */
435         fd = create_testfile(100);
436         close(fd);
437
438         rc = llapi_hsm_current_action(testfile, &hca);
439         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s", strerror(-rc));
440         ASSERTF(hca.hca_state, "hca_state=%u", hca.hca_state);
441         ASSERTF(hca.hca_action, "hca_state=%u", hca.hca_action);
442
443         rc = llapi_hsm_current_action(testfile, NULL);
444         ASSERTF(rc == -EFAULT, "llapi_hsm_current_action failed: %s",
445                 strerror(-rc));
446 }
447
448 /* Helper to simulate archiving a file. No actual data movement
449  * happens. */
450 void helper_archiving(void (*progress)
451                       (struct hsm_copyaction_private *hcp, size_t length),
452                       const size_t length)
453 {
454         int rc;
455         int fd;
456         struct hsm_copytool_private *ctdata;
457         struct hsm_user_request *hur;
458         struct hsm_action_list  *hal;
459         struct hsm_action_item  *hai;
460         int                      msgsize;
461         struct hsm_copyaction_private *hcp;
462         struct hsm_user_state hus;
463
464         fd = create_testfile(length);
465
466         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
467                                          0, NULL, 0);
468         ASSERTF(rc == 0, "llapi_hsm_copytool_register failed: %s",
469                 strerror(-rc));
470
471         /* Create and send the archive request. */
472         hur = llapi_hsm_user_request_alloc(1, 0);
473         ASSERTF(hur != NULL, "llapi_hsm_user_request_alloc returned NULL");
474
475         hur->hur_request.hr_action = HUA_ARCHIVE;
476         hur->hur_request.hr_archive_id = 1;
477         hur->hur_request.hr_flags = 0;
478         hur->hur_request.hr_itemcount = 1;
479         hur->hur_request.hr_data_len = 0;
480         hur->hur_user_item[0].hui_extent.length = -1;
481
482         rc = llapi_fd2fid(fd, &hur->hur_user_item[0].hui_fid);
483         ASSERTF(rc == 0, "llapi_fd2fid failed: %s", strerror(-rc));
484
485         close(fd);
486
487         rc = llapi_hsm_request(testfile, hur);
488         ASSERTF(rc == 0, "llapi_hsm_request failed: %s", strerror(-rc));
489
490         free(hur);
491
492         /* Read the request */
493         rc = llapi_hsm_copytool_recv(ctdata, &hal, &msgsize);
494         ASSERTF(rc == 0, "llapi_hsm_copytool_recv failed: %s", strerror(-rc));
495         ASSERTF(hal->hal_count == 1, "hal_count=%d", hal->hal_count);
496
497         hai = hai_first(hal);
498         ASSERTF(hai != NULL, "hai_first returned NULL");
499         ASSERTF(hai->hai_action == HSMA_ARCHIVE,
500                 "hai_action=%d", hai->hai_action);
501
502         /* "Begin" archiving */
503         hcp = NULL;
504         rc = llapi_hsm_action_begin(&hcp, ctdata, hai, -1, 0, false);
505         ASSERTF(rc == 0, "llapi_hsm_action_begin failed: %s", strerror(-rc));
506         ASSERTF(hcp != NULL, "hcp is NULL");
507
508         if (progress)
509                 progress(hcp, length);
510
511         /* Done archiving */
512         rc = llapi_hsm_action_end(&hcp, &hai->hai_extent, 0, 0);
513         ASSERTF(rc == 0, "llapi_hsm_action_end failed: %s", strerror(-rc));
514         ASSERTF(hcp == NULL, "hcp is NULL");
515
516         /* Close HSM client */
517         rc = llapi_hsm_copytool_unregister(&ctdata);
518         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
519                 strerror(-rc));
520
521         /* Final check */
522         rc = llapi_hsm_state_get(testfile, &hus);
523         ASSERTF(rc == 0, "llapi_hsm_state_get failed: %s", strerror(-rc));
524         ASSERTF(hus.hus_states == (HS_EXISTS | HS_ARCHIVED),
525                 "state=%u", hus.hus_states);
526 }
527
528 /* Simple archive. No progress. */
529 void test100(void)
530 {
531         const size_t length = 100;
532
533         helper_archiving(NULL, length);
534 }
535
536 /* Archive, with a report every byte. */
537 static void test101_progress(struct hsm_copyaction_private *hcp, size_t length)
538 {
539         int i;
540         int rc;
541         struct hsm_extent he;
542         struct hsm_current_action hca;
543
544         /* Report progress. 1 byte at a time :) */
545         for (i = 0; i < length; i++) {
546                 he.offset = i;
547                 he.length = 1;
548                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
549                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
550                         strerror(-rc));
551         }
552
553         rc = llapi_hsm_current_action(testfile, &hca);
554         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
555                 strerror(-rc));
556         ASSERTF(hca.hca_state == HPS_RUNNING,
557                 "hca_state=%u", hca.hca_state);
558         ASSERTF(hca.hca_action == HUA_ARCHIVE,
559                 "hca_state=%u", hca.hca_action);
560         ASSERTF(hca.hca_location.length == length,
561                 "length=%llu", (unsigned long long)hca.hca_location.length);
562 }
563
564 void test101(void)
565 {
566         const size_t length = 1000;
567
568         helper_archiving(test101_progress, length);
569 }
570
571 /* Archive, with a report every byte, backwards. */
572 static void test102_progress(struct hsm_copyaction_private *hcp, size_t length)
573 {
574         int i;
575         int rc;
576         struct hsm_extent he;
577         struct hsm_current_action hca;
578
579         /* Report progress. 1 byte at a time :) */
580         for (i = length-1; i >= 0; i--) {
581                 he.offset = i;
582                 he.length = 1;
583                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
584                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
585                         strerror(-rc));
586         }
587
588         rc = llapi_hsm_current_action(testfile, &hca);
589         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
590                 strerror(-rc));
591         ASSERTF(hca.hca_state == HPS_RUNNING,
592                 "hca_state=%u", hca.hca_state);
593         ASSERTF(hca.hca_action == HUA_ARCHIVE,
594                 "hca_state=%u", hca.hca_action);
595         ASSERTF(hca.hca_location.length == length,
596                 "length=%llu", (unsigned long long)hca.hca_location.length);
597 }
598
599 void test102(void)
600 {
601         const size_t length = 1000;
602
603         helper_archiving(test102_progress, length);
604 }
605
606 /* Archive, with a single report. */
607 static void test103_progress(struct hsm_copyaction_private *hcp, size_t length)
608 {
609         int rc;
610         struct hsm_extent he;
611         struct hsm_current_action hca;
612
613         he.offset = 0;
614         he.length = length;
615         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
616         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
617                 strerror(-rc));
618
619         rc = llapi_hsm_current_action(testfile, &hca);
620         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
621                 strerror(-rc));
622         ASSERTF(hca.hca_state == HPS_RUNNING,
623                 "hca_state=%u", hca.hca_state);
624         ASSERTF(hca.hca_action == HUA_ARCHIVE,
625                 "hca_state=%u", hca.hca_action);
626         ASSERTF(hca.hca_location.length == length,
627                 "length=%llu", (unsigned long long)hca.hca_location.length);
628 }
629
630 void test103(void)
631 {
632         const size_t length = 1000;
633
634         helper_archiving(test103_progress, length);
635 }
636
637 /* Archive, with 2 reports. */
638 static void test104_progress(struct hsm_copyaction_private *hcp, size_t length)
639 {
640         int rc;
641         struct hsm_extent he;
642         struct hsm_current_action hca;
643
644         he.offset = 0;
645         he.length = length/2;
646         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
647         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
648                 strerror(-rc));
649
650         he.offset = length/2;
651         he.length = length/2;
652         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
653         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
654                 strerror(-rc));
655
656         rc = llapi_hsm_current_action(testfile, &hca);
657         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
658                 strerror(-rc));
659         ASSERTF(hca.hca_state == HPS_RUNNING,
660                 "hca_state=%u", hca.hca_state);
661         ASSERTF(hca.hca_action == HUA_ARCHIVE,
662                 "hca_state=%u", hca.hca_action);
663         ASSERTF(hca.hca_location.length == length,
664                 "length=%llu", (unsigned long long)hca.hca_location.length);
665 }
666
667 void test104(void)
668 {
669         const size_t length = 1000;
670
671         helper_archiving(test104_progress, length);
672 }
673
674 /* Archive, with 1 bogus report. */
675 static void test105_progress(struct hsm_copyaction_private *hcp, size_t length)
676 {
677         int rc;
678         struct hsm_extent he;
679         struct hsm_current_action hca;
680
681         he.offset = 2*length;
682         he.length = 10*length;
683         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
684         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
685                 strerror(-rc));
686
687         rc = llapi_hsm_current_action(testfile, &hca);
688         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
689                 strerror(-rc));
690         ASSERTF(hca.hca_state == HPS_RUNNING,
691                 "hca_state=%u", hca.hca_state);
692         ASSERTF(hca.hca_action == HUA_ARCHIVE,
693                 "hca_state=%u", hca.hca_action);
694
695         /* BUG - offset should be 2*length, or length should
696          * be 8*length */
697         ASSERTF(hca.hca_location.length == 10*length,
698                 "length=%llu", (unsigned long long)hca.hca_location.length);
699 }
700
701 void test105(void)
702 {
703         const size_t length = 1000;
704
705         helper_archiving(test105_progress, length);
706 }
707
708 /* Archive, with 1 empty report. */
709 static void test106_progress(struct hsm_copyaction_private *hcp, size_t length)
710 {
711         int rc;
712         struct hsm_extent he;
713         struct hsm_current_action hca;
714
715         he.offset = 0;
716         he.length = 0;
717         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
718         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
719                 strerror(-rc));
720
721         rc = llapi_hsm_current_action(testfile, &hca);
722         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
723                 strerror(-rc));
724         ASSERTF(hca.hca_state == HPS_RUNNING,
725                 "hca_state=%u", hca.hca_state);
726         ASSERTF(hca.hca_action == HUA_ARCHIVE,
727                 "hca_state=%u", hca.hca_action);
728         ASSERTF(hca.hca_location.length == 0,
729                 "length=%llu", (unsigned long long)hca.hca_location.length);
730 }
731
732 void test106(void)
733 {
734         const size_t length = 1000;
735
736         helper_archiving(test106_progress, length);
737 }
738
739 /* Archive, with 1 bogus report. */
740 static void test107_progress(struct hsm_copyaction_private *hcp, size_t length)
741 {
742         int rc;
743         struct hsm_extent he;
744         struct hsm_current_action hca;
745
746         he.offset = -1;
747         he.length = 10;
748         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
749         ASSERTF(rc == -EINVAL, "llapi_hsm_action_progress error: %s",
750                 strerror(-rc));
751
752         rc = llapi_hsm_current_action(testfile, &hca);
753         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
754                 strerror(-rc));
755         ASSERTF(hca.hca_state == HPS_RUNNING,
756                 "hca_state=%u", hca.hca_state);
757         ASSERTF(hca.hca_action == HUA_ARCHIVE,
758                 "hca_state=%u", hca.hca_action);
759         ASSERTF(hca.hca_location.length == 0,
760                 "length=%llu", (unsigned long long)hca.hca_location.length);
761 }
762
763 void test107(void)
764 {
765         const size_t length = 1000;
766
767         helper_archiving(test107_progress, length);
768 }
769
770 /* Archive, with same report, many times. */
771 static void test108_progress(struct hsm_copyaction_private *hcp, size_t length)
772 {
773         int rc;
774         struct hsm_extent he;
775         int i;
776         struct hsm_current_action hca;
777
778         for (i = 0; i < 1000; i++) {
779                 he.offset = 0;
780                 he.length = length;
781                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
782                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
783                         strerror(-rc));
784         }
785
786         rc = llapi_hsm_current_action(testfile, &hca);
787         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
788                 strerror(-rc));
789         ASSERTF(hca.hca_state == HPS_RUNNING,
790                 "hca_state=%u", hca.hca_state);
791         ASSERTF(hca.hca_action == HUA_ARCHIVE,
792                 "hca_state=%u", hca.hca_action);
793         ASSERTF(hca.hca_location.length == length,
794                 "length=%llu", (unsigned long long)hca.hca_location.length);
795 }
796
797 void test108(void)
798 {
799         const size_t length = 1000;
800
801         helper_archiving(test108_progress, length);
802 }
803
804 /* Archive, 1 report, with large number. */
805 static void test109_progress(struct hsm_copyaction_private *hcp, size_t length)
806 {
807         int rc;
808         struct hsm_extent he;
809         struct hsm_current_action hca;
810
811         he.offset = 0;
812         he.length = 0xffffffffffffffffULL;
813         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
814         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
815                 strerror(-rc));
816
817         rc = llapi_hsm_current_action(testfile, &hca);
818         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
819                 strerror(-rc));
820         ASSERTF(hca.hca_state == HPS_RUNNING,
821                 "hca_state=%u", hca.hca_state);
822         ASSERTF(hca.hca_action == HUA_ARCHIVE,
823                 "hca_state=%u", hca.hca_action);
824         ASSERTF(hca.hca_location.length == 0xffffffffffffffffULL,
825                 "length=%llu", (unsigned long long)hca.hca_location.length);
826 }
827
828 void test109(void)
829 {
830         const size_t length = 1000;
831
832         helper_archiving(test109_progress, length);
833 }
834
835 /* Archive, with 10 reports, checking progress. */
836 static void test110_progress(struct hsm_copyaction_private *hcp, size_t length)
837 {
838         int rc;
839         int i;
840         struct hsm_extent he;
841         struct hsm_current_action hca;
842
843         for (i = 0; i < 10; i++) {
844                 he.offset = i*length/10;
845                 he.length = length/10;
846                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
847                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
848                         strerror(-rc));
849
850                 rc = llapi_hsm_current_action(testfile, &hca);
851                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
852                         strerror(-rc));
853                 ASSERTF(hca.hca_state == HPS_RUNNING,
854                         "hca_state=%u", hca.hca_state);
855                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
856                         "hca_state=%u", hca.hca_action);
857                 ASSERTF(hca.hca_location.length == (i+1)*length/10,
858                         "i=%d, length=%llu",
859                         i, (unsigned long long)hca.hca_location.length);
860         }
861 }
862
863 void test110(void)
864 {
865         const size_t length = 1000;
866
867         helper_archiving(test110_progress, length);
868 }
869
870 /* Archive, with 10 reports in reverse order, checking progress. */
871 static void test111_progress(struct hsm_copyaction_private *hcp, size_t length)
872 {
873         int rc;
874         int i;
875         struct hsm_extent he;
876         struct hsm_current_action hca;
877
878         for (i = 0; i < 10; i++) {
879                 he.offset = (9-i)*length/10;
880                 he.length = length/10;
881                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
882                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
883                         strerror(-rc));
884
885                 rc = llapi_hsm_current_action(testfile, &hca);
886                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
887                         strerror(-rc));
888                 ASSERTF(hca.hca_state == HPS_RUNNING,
889                         "hca_state=%u", hca.hca_state);
890                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
891                         "hca_state=%u", hca.hca_action);
892                 ASSERTF(hca.hca_location.length == (i+1)*length/10,
893                         "i=%d, length=%llu",
894                         i, (unsigned long long)hca.hca_location.length);
895         }
896 }
897
898 void test111(void)
899 {
900         const size_t length = 1000;
901
902         helper_archiving(test111_progress, length);
903 }
904
905 /* Archive, with 10 reports, and duplicating them, checking
906  * progress. */
907 static void test112_progress(struct hsm_copyaction_private *hcp, size_t length)
908 {
909         int rc;
910         int i;
911         struct hsm_extent he;
912         struct hsm_current_action hca;
913
914         for (i = 0; i < 10; i++) {
915                 he.offset = i*length/10;
916                 he.length = length/10;
917                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
918                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
919                         strerror(-rc));
920
921                 rc = llapi_hsm_current_action(testfile, &hca);
922                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
923                         strerror(-rc));
924                 ASSERTF(hca.hca_state == HPS_RUNNING,
925                         "hca_state=%u", hca.hca_state);
926                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
927                         "hca_state=%u", hca.hca_action);
928                 ASSERTF(hca.hca_location.length == (i+1)*length/10,
929                         "i=%d, length=%llu",
930                         i, (unsigned long long)hca.hca_location.length);
931         }
932
933         for (i = 0; i < 10; i++) {
934                 he.offset = i*length/10;
935                 he.length = length/10;
936                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
937                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
938                         strerror(-rc));
939
940                 rc = llapi_hsm_current_action(testfile, &hca);
941                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
942                         strerror(-rc));
943                 ASSERTF(hca.hca_state == HPS_RUNNING,
944                         "hca_state=%u", hca.hca_state);
945                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
946                         "hca_state=%u", hca.hca_action);
947                 ASSERTF(hca.hca_location.length == length,
948                         "i=%d, length=%llu",
949                         i, (unsigned long long)hca.hca_location.length);
950         }
951 }
952
953 void test112(void)
954 {
955         const size_t length = 1000;
956
957         helper_archiving(test112_progress, length);
958 }
959
960 static void usage(char *prog)
961 {
962         fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog);
963         exit(EXIT_FAILURE);
964 }
965
966 static void process_args(int argc, char *argv[])
967 {
968         int c;
969
970         while ((c = getopt(argc, argv, "d:")) != -1) {
971                 switch (c) {
972                 case 'd':
973                         lustre_dir = optarg;
974                         break;
975                 case '?':
976                 default:
977                         fprintf(stderr, "Unknown option '%c'\n", optopt);
978                         usage(argv[0]);
979                         break;
980                 }
981         }
982 }
983
984 int main(int argc, char *argv[])
985 {
986         char fsname[8];
987         int rc;
988
989         process_args(argc, argv);
990         if (lustre_dir == NULL)
991                 lustre_dir = "/mnt/lustre";
992
993         rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
994         if (rc != 0) {
995                 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
996                         lustre_dir);
997                 return EXIT_FAILURE;
998         }
999
1000         /* Play nice with Lustre test scripts. Non-line buffered output
1001          * stream under I/O redirection may appear incorrectly. */
1002         setvbuf(stdout, NULL, _IOLBF, 0);
1003
1004         PERFORM(test1);
1005         PERFORM(test2);
1006         PERFORM(test3);
1007         PERFORM(test4);
1008         PERFORM(test5);
1009         PERFORM(test6);
1010         PERFORM(test7);
1011         PERFORM(test50);
1012         PERFORM(test51);
1013         PERFORM(test52);
1014         PERFORM(test100);
1015         PERFORM(test101);
1016         PERFORM(test102);
1017         PERFORM(test103);
1018         PERFORM(test104);
1019         PERFORM(test105);
1020         PERFORM(test106);
1021         PERFORM(test107);
1022         PERFORM(test108);
1023         PERFORM(test109);
1024         PERFORM(test110);
1025         PERFORM(test111);
1026         PERFORM(test112);
1027
1028         return EXIT_SUCCESS;
1029 }