Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[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  */
82 static int test1(void)
83 {
84         int i;
85         int rc;
86         struct hsm_copytool_private *ctdata;
87
88         for (i = 0; i < 2000; i++) {
89                 rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
90                                                  0, NULL, 0);
91                 ASSERTF(rc == 0,
92                         "llapi_hsm_copytool_register failed: %s, loop=%d",
93                         strerror(-rc), i);
94
95                 rc = llapi_hsm_copytool_unregister(&ctdata);
96                 ASSERTF(rc == 0,
97                         "llapi_hsm_copytool_unregister failed: %s, loop=%d",
98                         strerror(-rc), i);
99         }
100
101         return 0;
102 }
103
104 /* Re-register */
105 static int test2(void)
106 {
107         int rc;
108         struct hsm_copytool_private *ctdata1;
109         struct hsm_copytool_private *ctdata2;
110
111         rc = llapi_hsm_copytool_register(&ctdata1, fsmountdir, 0, NULL, 0);
112         ASSERTF(rc == 0, "llapi_hsm_copytool_register failed: %s",
113                 strerror(-rc));
114
115         rc = llapi_hsm_copytool_register(&ctdata2, fsmountdir, 0, NULL, 0);
116         ASSERTF(rc == 0, "llapi_hsm_copytool_register failed: %s",
117                 strerror(-rc));
118
119         rc = llapi_hsm_copytool_unregister(&ctdata2);
120         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
121                 strerror(-rc));
122
123         rc = llapi_hsm_copytool_unregister(&ctdata1);
124         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
125                 strerror(-rc));
126
127         return 0;
128 }
129
130 /* Bad parameters to llapi_hsm_copytool_register(). */
131 static int test3(void)
132 {
133         int rc;
134         struct hsm_copytool_private *ctdata;
135         int archives[33];
136         int count = sizeof(archives) / sizeof(*archives);
137
138         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 1, NULL, 0);
139         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
140                 strerror(-rc));
141
142         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, count, NULL, 0);
143         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
144                 strerror(-rc));
145
146         if (is_bitmap) {
147                 int i;
148
149                 for (i = 0; i < count; i++)
150                         archives[i] = i + 1;
151                 rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
152                                                  count, archives, 0);
153                 ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
154                         strerror(-rc));
155         }
156
157 #if 0
158         /* BUG? Should that fail or not? */
159         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, -1, NULL, 0);
160         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
161                 strerror(-rc));
162 #endif
163
164         memset(archives, -1, sizeof(archives));
165         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 1, archives, 0);
166         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_register error: %s",
167                 strerror(-rc));
168
169         rc = llapi_hsm_copytool_register(&ctdata, "/tmp", 0, NULL, 0);
170         ASSERTF(rc == -ENOENT, "llapi_hsm_copytool_register error: %s",
171                 strerror(-rc));
172
173         return 0;
174 }
175
176 /* Bad parameters to llapi_hsm_copytool_unregister(). */
177 static int test4(void)
178 {
179         int rc;
180
181         rc = llapi_hsm_copytool_unregister(NULL);
182         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_unregister error: %s",
183                 strerror(-rc));
184
185         return 0;
186 }
187
188 /* Test llapi_hsm_copytool_recv in non blocking mode */
189 static int test5(void)
190 {
191         int rc;
192         int i;
193         struct hsm_copytool_private *ctdata;
194         struct hsm_action_list  *hal;
195         int msgsize;
196
197         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
198                                          0, NULL, O_NONBLOCK);
199         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
200                 strerror(-rc));
201
202         /* Hopefully there is nothing lingering */
203         for (i = 0; i < 1000; i++) {
204                 rc = llapi_hsm_copytool_recv(ctdata, &hal, &msgsize);
205                 ASSERTF(rc == -EAGAIN, "llapi_hsm_copytool_recv error: %s",
206                         strerror(-rc));
207         }
208
209         rc = llapi_hsm_copytool_unregister(&ctdata);
210         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
211                 strerror(-rc));
212
213         return 0;
214 }
215
216 /* Test llapi_hsm_copytool_recv with bogus parameters */
217 static int test6(void)
218 {
219         struct hsm_copytool_private *ctdata;
220         struct hsm_action_list *hal;
221         int rc;
222         int msgsize;
223
224         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir, 0, NULL, 0);
225         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
226                 strerror(-rc));
227
228         rc = llapi_hsm_copytool_recv(NULL, &hal, &msgsize);
229         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
230                 strerror(-rc));
231
232         rc = llapi_hsm_copytool_recv(ctdata, NULL, &msgsize);
233         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
234                 strerror(-rc));
235
236         rc = llapi_hsm_copytool_recv(ctdata, &hal, NULL);
237         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
238                 strerror(-rc));
239
240         rc = llapi_hsm_copytool_recv(ctdata, NULL, NULL);
241         ASSERTF(rc == -EINVAL, "llapi_hsm_copytool_recv error: %s",
242                 strerror(-rc));
243
244         rc = llapi_hsm_copytool_unregister(&ctdata);
245         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
246                 strerror(-rc));
247
248         return 0;
249 }
250
251 /* Test polling (without actual traffic) */
252 static int test7(void)
253 {
254         int rc;
255         struct hsm_copytool_private *ctdata;
256         struct hsm_action_list  *hal;
257         int msgsize;
258         int fd;
259         struct pollfd fds[1];
260
261         rc = llapi_hsm_copytool_register(&ctdata, fsmountdir,
262                                          0, NULL, O_NONBLOCK);
263         ASSERTF(rc == 0, "llapi_hsm_copytool_register failed: %s",
264                 strerror(-rc));
265
266         fd = llapi_hsm_copytool_get_fd(ctdata);
267         ASSERTF(fd >= 0, "llapi_hsm_copytool_get_fd failed: %s",
268                 strerror(-rc));
269
270         /* Ensure it's read-only */
271         rc = write(fd, &rc, 1);
272         ASSERTF(rc == -1 && errno == EBADF, "write error: %d, %s",
273                 rc, strerror(errno));
274
275         rc = llapi_hsm_copytool_recv(ctdata, &hal, &msgsize);
276         ASSERTF(rc == -EAGAIN, "llapi_hsm_copytool_recv error: %s",
277                 strerror(-rc));
278
279         fds[0].fd = fd;
280         fds[0].events = POLLIN;
281         rc = poll(fds, 1, 10);
282         ASSERTF(rc == 0, "poll failed: %d, %s",
283                 rc, strerror(errno)); /* no event */
284
285         rc = llapi_hsm_copytool_unregister(&ctdata);
286         ASSERTF(rc == 0, "llapi_hsm_copytool_unregister failed: %s",
287                 strerror(-rc));
288
289         return 0;
290 }
291
292 /* Create the testfile of a given length. It returns a valid file 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          */
309         fd = creat(testfile, 0700);
310         ASSERTF(fd >= 0, "create failed for '%s': %s",
311                 testfile, strerror(errno));
312
313         rc = ftruncate(fd, length);
314         ASSERTF(rc == 0, "ftruncate failed for '%s': %s",
315                 testfile, strerror(errno));
316
317         return fd;
318 }
319
320 /* Test llapi_hsm_state_get. */
321 static void test50(void)
322 {
323         struct hsm_user_state hus;
324         int rc;
325         int fd;
326
327         fd = create_testfile(100);
328
329         /* With fd variant */
330         rc = llapi_hsm_state_get_fd(fd, &hus);
331         ASSERTF(rc == 0, "llapi_hsm_state_get_fd failed: %s", strerror(-rc));
332         ASSERTF(hus.hus_states == 0, "state=%u", hus.hus_states);
333
334         rc = llapi_hsm_state_get_fd(fd, NULL);
335         ASSERTF(rc == -EFAULT, "llapi_hsm_state_get_fd error: %s",
336                 strerror(-rc));
337
338         rc = close(fd);
339         ASSERTF(rc == 0, "close failed: %s", strerror(errno));
340
341         /* Without fd */
342         rc = llapi_hsm_state_get(testfile, &hus);
343         ASSERTF(rc == 0, "llapi_hsm_state_get failed: %s", strerror(-rc));
344         ASSERTF(hus.hus_states == 0, "state=%u", hus.hus_states);
345
346         rc = llapi_hsm_state_get(testfile, NULL);
347         ASSERTF(rc == -EFAULT, "llapi_hsm_state_get error: %s",
348                 strerror(-rc));
349
350         memset(&hus, 0xaa, sizeof(hus));
351         rc = llapi_hsm_state_get(testfile, &hus);
352         ASSERTF(rc == 0, "llapi_hsm_state_get failed: %s", strerror(-rc));
353         ASSERTF(hus.hus_states == 0, "state=%u", hus.hus_states);
354         ASSERTF(hus.hus_archive_id == 0, "archive_id=%u", hus.hus_archive_id);
355         ASSERTF(hus.hus_in_progress_state == 0, "hus_in_progress_state=%u",
356                 hus.hus_in_progress_state);
357         ASSERTF(hus.hus_in_progress_action == 0, "hus_in_progress_action=%u",
358                 hus.hus_in_progress_action);
359 }
360
361 /* Test llapi_hsm_state_set. */
362 static void test51(void)
363 {
364         int rc;
365         int fd;
366         int i;
367         int test_count;
368         struct hsm_user_state hus;
369
370         fd = create_testfile(100);
371
372         rc = llapi_hsm_state_set_fd(fd, 0, 0, 0);
373         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
374
375         /* Set archive id */
376         if (is_bitmap)
377                 test_count = 32;
378         else
379                 test_count = 48;
380         for (i = 0; i <= test_count; i++) {
381                 rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, i);
382                 ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s",
383                         strerror(-rc));
384
385                 rc = llapi_hsm_state_get_fd(fd, &hus);
386                 ASSERTF(rc == 0, "llapi_hsm_state_get_fd failed: %s",
387                         strerror(-rc));
388                 ASSERTF(hus.hus_states == HS_EXISTS, "state=%u",
389                         hus.hus_states);
390                 ASSERTF(hus.hus_archive_id == i, "archive_id=%u, i=%d",
391                         hus.hus_archive_id, i);
392         }
393
394         if (is_bitmap) {
395                 /* Invalid archive numbers */
396                 rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 33);
397                 ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s",
398                         strerror(-rc));
399
400                 rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, 151);
401                 ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s",
402                         strerror(-rc));
403
404                 rc = llapi_hsm_state_set_fd(fd, HS_EXISTS, 0, -1789);
405                 ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s",
406                         strerror(-rc));
407         }
408
409         /* Settable flags, with respect of the HSM file state transition rules:
410          *      DIRTY without EXISTS: no dirty if no archive was created
411          *      DIRTY and RELEASED: a dirty file could not be released
412          *      RELEASED without ARCHIVED: do not release a non-archived file
413          *      LOST without ARCHIVED: cannot lost a non-archived file.
414          */
415         rc = llapi_hsm_state_set_fd(fd, HS_DIRTY, 0, 0);
416         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
417
418         rc = llapi_hsm_state_set_fd(fd, 0, HS_EXISTS, 0);
419         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd failed: %s",
420                 strerror(-rc));
421
422         rc = llapi_hsm_state_set_fd(fd, 0, HS_DIRTY, 0);
423         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
424
425         rc = llapi_hsm_state_set_fd(fd, 0, HS_EXISTS, 0);
426         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
427
428         rc = llapi_hsm_state_set_fd(fd, HS_DIRTY, 0, 0);
429         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd failed: %s",
430                 strerror(-rc));
431
432         rc = llapi_hsm_state_set_fd(fd, HS_RELEASED, 0, 0);
433         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd failed: %s",
434                 strerror(-rc));
435
436         rc = llapi_hsm_state_set_fd(fd, HS_LOST, 0, 0);
437         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd failed: %s",
438                 strerror(-rc));
439
440         rc = llapi_hsm_state_set_fd(fd, HS_ARCHIVED, 0, 0);
441         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
442
443         rc = llapi_hsm_state_set_fd(fd, HS_RELEASED, 0, 0);
444         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
445
446         rc = llapi_hsm_state_set_fd(fd, HS_LOST, 0, 0);
447         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
448
449         rc = llapi_hsm_state_set_fd(fd, HS_DIRTY|HS_EXISTS, 0, 0);
450         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd failed: %s",
451                 strerror(-rc));
452
453         rc = llapi_hsm_state_set_fd(fd, 0, HS_RELEASED, 0);
454         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
455
456         rc = llapi_hsm_state_set_fd(fd, HS_DIRTY|HS_EXISTS, 0, 0);
457         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
458
459         rc = llapi_hsm_state_set_fd(fd, 0, HS_ARCHIVED, 0);
460         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd failed: %s",
461                 strerror(-rc));
462
463         rc = llapi_hsm_state_set_fd(fd, 0, HS_LOST, 0);
464         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
465
466         rc = llapi_hsm_state_set_fd(fd, 0, HS_ARCHIVED, 0);
467         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
468
469         rc = llapi_hsm_state_set_fd(fd, HS_NORELEASE, 0, 0);
470         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
471
472         rc = llapi_hsm_state_set_fd(fd, 0, HS_NORELEASE, 0);
473         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
474
475         rc = llapi_hsm_state_set_fd(fd, HS_NOARCHIVE, 0, 0);
476         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
477
478         rc = llapi_hsm_state_set_fd(fd, 0, HS_NOARCHIVE, 0);
479         ASSERTF(rc == 0, "llapi_hsm_state_set_fd failed: %s", strerror(-rc));
480
481         /* Bogus flags for good measure. */
482         rc = llapi_hsm_state_set_fd(fd, 0x00080000, 0, 0);
483         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s", strerror(-rc));
484
485         rc = llapi_hsm_state_set_fd(fd, 0x80000000, 0, 0);
486         ASSERTF(rc == -EINVAL, "llapi_hsm_state_set_fd: %s", strerror(-rc));
487
488         close(fd);
489 }
490
491 /* Test llapi_hsm_current_action */
492 static void test52(void)
493 {
494         int rc;
495         int fd;
496         struct hsm_current_action hca;
497
498         /* No fd equivalent, so close it. */
499         fd = create_testfile(100);
500         close(fd);
501
502         rc = llapi_hsm_current_action(testfile, &hca);
503         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s", strerror(-rc));
504         ASSERTF(hca.hca_state, "hca_state=%u", hca.hca_state);
505         ASSERTF(hca.hca_action, "hca_state=%u", hca.hca_action);
506
507         rc = llapi_hsm_current_action(testfile, NULL);
508         ASSERTF(rc == -EFAULT, "llapi_hsm_current_action failed: %s",
509                 strerror(-rc));
510 }
511
512 /* Helper to simulate archiving a file. No actual data movement happens. */
513 static 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 static 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 static 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 static 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 static 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 static 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 be 8*length */
760         ASSERTF(hca.hca_location.length == 10*length,
761                 "length=%llu", (unsigned long long)hca.hca_location.length);
762 }
763
764 static void test105(void)
765 {
766         const size_t length = 1000;
767
768         helper_archiving(test105_progress, length);
769 }
770
771 /* Archive, with 1 empty report. */
772 static void test106_progress(struct hsm_copyaction_private *hcp, size_t length)
773 {
774         int rc;
775         struct hsm_extent he;
776         struct hsm_current_action hca;
777
778         he.offset = 0;
779         he.length = 0;
780         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
781         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
782                 strerror(-rc));
783
784         rc = llapi_hsm_current_action(testfile, &hca);
785         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
786                 strerror(-rc));
787         ASSERTF(hca.hca_state == HPS_RUNNING,
788                 "hca_state=%u", hca.hca_state);
789         ASSERTF(hca.hca_action == HUA_ARCHIVE,
790                 "hca_state=%u", hca.hca_action);
791         ASSERTF(hca.hca_location.length == 0,
792                 "length=%llu", (unsigned long long)hca.hca_location.length);
793 }
794
795 static void test106(void)
796 {
797         const size_t length = 1000;
798
799         helper_archiving(test106_progress, length);
800 }
801
802 /* Archive, with 1 bogus report. */
803 static void test107_progress(struct hsm_copyaction_private *hcp, size_t length)
804 {
805         int rc;
806         struct hsm_extent he;
807         struct hsm_current_action hca;
808
809         he.offset = -1;
810         he.length = 10;
811         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
812         ASSERTF(rc == -EINVAL, "llapi_hsm_action_progress error: %s",
813                 strerror(-rc));
814
815         rc = llapi_hsm_current_action(testfile, &hca);
816         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
817                 strerror(-rc));
818         ASSERTF(hca.hca_state == HPS_RUNNING,
819                 "hca_state=%u", hca.hca_state);
820         ASSERTF(hca.hca_action == HUA_ARCHIVE,
821                 "hca_state=%u", hca.hca_action);
822         ASSERTF(hca.hca_location.length == 0,
823                 "length=%llu", (unsigned long long)hca.hca_location.length);
824 }
825
826 static void test107(void)
827 {
828         const size_t length = 1000;
829
830         helper_archiving(test107_progress, length);
831 }
832
833 /* Archive, with same report, many times. */
834 static void test108_progress(struct hsm_copyaction_private *hcp, size_t length)
835 {
836         int rc;
837         struct hsm_extent he;
838         int i;
839         struct hsm_current_action hca;
840
841         for (i = 0; i < 1000; i++) {
842                 he.offset = 0;
843                 he.length = length;
844                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
845                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
846                         strerror(-rc));
847         }
848
849         rc = llapi_hsm_current_action(testfile, &hca);
850         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
851                 strerror(-rc));
852         ASSERTF(hca.hca_state == HPS_RUNNING,
853                 "hca_state=%u", hca.hca_state);
854         ASSERTF(hca.hca_action == HUA_ARCHIVE,
855                 "hca_state=%u", hca.hca_action);
856         ASSERTF(hca.hca_location.length == length,
857                 "length=%llu", (unsigned long long)hca.hca_location.length);
858 }
859
860 static void test108(void)
861 {
862         const size_t length = 1000;
863
864         helper_archiving(test108_progress, length);
865 }
866
867 /* Archive, 1 report, with large number. */
868 static void test109_progress(struct hsm_copyaction_private *hcp, size_t length)
869 {
870         int rc;
871         struct hsm_extent he;
872         struct hsm_current_action hca;
873
874         he.offset = 0;
875         he.length = 0xffffffffffffffffULL;
876         rc = llapi_hsm_action_progress(hcp, &he, length, 0);
877         ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
878                 strerror(-rc));
879
880         rc = llapi_hsm_current_action(testfile, &hca);
881         ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
882                 strerror(-rc));
883         ASSERTF(hca.hca_state == HPS_RUNNING,
884                 "hca_state=%u", hca.hca_state);
885         ASSERTF(hca.hca_action == HUA_ARCHIVE,
886                 "hca_state=%u", hca.hca_action);
887         ASSERTF(hca.hca_location.length == 0xffffffffffffffffULL,
888                 "length=%llu", (unsigned long long)hca.hca_location.length);
889 }
890
891 static void test109(void)
892 {
893         const size_t length = 1000;
894
895         helper_archiving(test109_progress, length);
896 }
897
898 /* Archive, with 10 reports, checking progress. */
899 static void test110_progress(struct hsm_copyaction_private *hcp, size_t length)
900 {
901         int rc;
902         int i;
903         struct hsm_extent he;
904         struct hsm_current_action hca;
905
906         for (i = 0; i < 10; i++) {
907                 he.offset = i*length/10;
908                 he.length = length/10;
909                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
910                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
911                         strerror(-rc));
912
913                 rc = llapi_hsm_current_action(testfile, &hca);
914                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
915                         strerror(-rc));
916                 ASSERTF(hca.hca_state == HPS_RUNNING,
917                         "hca_state=%u", hca.hca_state);
918                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
919                         "hca_state=%u", hca.hca_action);
920                 ASSERTF(hca.hca_location.length == (i+1)*length/10,
921                         "i=%d, length=%llu",
922                         i, (unsigned long long)hca.hca_location.length);
923         }
924 }
925
926 static void test110(void)
927 {
928         const size_t length = 1000;
929
930         helper_archiving(test110_progress, length);
931 }
932
933 /* Archive, with 10 reports in reverse order, checking progress. */
934 static void test111_progress(struct hsm_copyaction_private *hcp, size_t length)
935 {
936         int rc;
937         int i;
938         struct hsm_extent he;
939         struct hsm_current_action hca;
940
941         for (i = 0; i < 10; i++) {
942                 he.offset = (9-i)*length/10;
943                 he.length = length/10;
944                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
945                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
946                         strerror(-rc));
947
948                 rc = llapi_hsm_current_action(testfile, &hca);
949                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
950                         strerror(-rc));
951                 ASSERTF(hca.hca_state == HPS_RUNNING,
952                         "hca_state=%u", hca.hca_state);
953                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
954                         "hca_state=%u", hca.hca_action);
955                 ASSERTF(hca.hca_location.length == (i+1)*length/10,
956                         "i=%d, length=%llu",
957                         i, (unsigned long long)hca.hca_location.length);
958         }
959 }
960
961 static void test111(void)
962 {
963         const size_t length = 1000;
964
965         helper_archiving(test111_progress, length);
966 }
967
968 /* Archive, with 10 reports, and duplicating them, checking progress. */
969 static void test112_progress(struct hsm_copyaction_private *hcp, size_t length)
970 {
971         int rc;
972         int i;
973         struct hsm_extent he;
974         struct hsm_current_action hca;
975
976         for (i = 0; i < 10; i++) {
977                 he.offset = i*length/10;
978                 he.length = length/10;
979                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
980                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
981                         strerror(-rc));
982
983                 rc = llapi_hsm_current_action(testfile, &hca);
984                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
985                         strerror(-rc));
986                 ASSERTF(hca.hca_state == HPS_RUNNING,
987                         "hca_state=%u", hca.hca_state);
988                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
989                         "hca_state=%u", hca.hca_action);
990                 ASSERTF(hca.hca_location.length == (i+1)*length/10,
991                         "i=%d, length=%llu",
992                         i, (unsigned long long)hca.hca_location.length);
993         }
994
995         for (i = 0; i < 10; i++) {
996                 he.offset = i*length/10;
997                 he.length = length/10;
998                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
999                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
1000                         strerror(-rc));
1001
1002                 rc = llapi_hsm_current_action(testfile, &hca);
1003                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
1004                         strerror(-rc));
1005                 ASSERTF(hca.hca_state == HPS_RUNNING,
1006                         "hca_state=%u", hca.hca_state);
1007                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
1008                         "hca_state=%u", hca.hca_action);
1009                 ASSERTF(hca.hca_location.length == length,
1010                         "i=%d, length=%llu",
1011                         i, (unsigned long long)hca.hca_location.length);
1012         }
1013 }
1014
1015 static void test112(void)
1016 {
1017         const size_t length = 1000;
1018
1019         helper_archiving(test112_progress, length);
1020 }
1021
1022 /* Archive, with 9 reports, each covering 20%, so many overlap. */
1023 static void test113_progress(struct hsm_copyaction_private *hcp, size_t length)
1024 {
1025         int rc;
1026         int i;
1027         struct hsm_extent he;
1028         struct hsm_current_action hca;
1029
1030         for (i = 0; i < 9; i++) {
1031                 he.offset = i*length/10;
1032                 he.length = 2*length/10;
1033                 rc = llapi_hsm_action_progress(hcp, &he, length, 0);
1034                 ASSERTF(rc == 0, "llapi_hsm_action_progress failed: %s",
1035                         strerror(-rc));
1036
1037                 rc = llapi_hsm_current_action(testfile, &hca);
1038                 ASSERTF(rc == 0, "llapi_hsm_current_action failed: %s",
1039                         strerror(-rc));
1040                 ASSERTF(hca.hca_state == HPS_RUNNING,
1041                         "hca_state=%u", hca.hca_state);
1042                 ASSERTF(hca.hca_action == HUA_ARCHIVE,
1043                         "hca_state=%u", hca.hca_action);
1044                 ASSERTF(hca.hca_location.length == (i+2)*length/10,
1045                         "i=%d, length=%llu",
1046                         i, (unsigned long long)hca.hca_location.length);
1047         }
1048 }
1049
1050 static void test113(void)
1051 {
1052         const size_t length = 1000;
1053
1054         helper_archiving(test113_progress, length);
1055 }
1056
1057 static void usage(char *prog)
1058 {
1059         fprintf(stderr, "Usage: %s [-d lustre_dir]\n", prog);
1060         exit(EXIT_FAILURE);
1061 }
1062
1063 static void process_args(int argc, char *argv[])
1064 {
1065         int c;
1066
1067         while ((c = getopt(argc, argv, "bd:")) != -1) {
1068                 switch (c) {
1069                 case 'd':
1070                         lustre_dir = optarg;
1071                         break;
1072                 case 'b':
1073                         is_bitmap = true;
1074                         break;
1075                 case '?':
1076                 default:
1077                         fprintf(stderr, "Unknown option '%c'\n", optopt);
1078                         usage(argv[0]);
1079                         break;
1080                 }
1081         }
1082 }
1083
1084 int main(int argc, char *argv[])
1085 {
1086         char fsname[8 + 1];
1087         int rc;
1088
1089         process_args(argc, argv);
1090         if (lustre_dir == NULL)
1091                 lustre_dir = "/mnt/lustre";
1092
1093         rc = llapi_search_mounts(lustre_dir, 0, fsmountdir, fsname);
1094         if (rc != 0) {
1095                 fprintf(stderr, "Error: %s: not a Lustre filesystem\n",
1096                         lustre_dir);
1097                 return EXIT_FAILURE;
1098         }
1099
1100         /* Play nice with Lustre test scripts. Non-line buffered output
1101          * stream under I/O redirection may appear incorrectly.
1102          */
1103         setvbuf(stdout, NULL, _IOLBF, 0);
1104
1105         PERFORM(test1);
1106         PERFORM(test2);
1107         PERFORM(test3);
1108         PERFORM(test4);
1109         PERFORM(test5);
1110         PERFORM(test6);
1111         PERFORM(test7);
1112         PERFORM(test50);
1113         PERFORM(test51);
1114         PERFORM(test52);
1115         PERFORM(test100);
1116         PERFORM(test101);
1117         PERFORM(test102);
1118         PERFORM(test103);
1119         PERFORM(test104);
1120         PERFORM(test105);
1121         PERFORM(test106);
1122         PERFORM(test107);
1123         PERFORM(test108);
1124         PERFORM(test109);
1125         PERFORM(test110);
1126         PERFORM(test111);
1127         PERFORM(test112);
1128         PERFORM(test113);
1129
1130         return EXIT_SUCCESS;
1131 }