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