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