#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <err.h>
+#include <linux/lustre/lustre_idl.h>
#include <lustre/lustreapi.h>
-#define syserr(exp, str, args...) \
-do { \
- if (exp) \
- err(EXIT_FAILURE, str, ##args); \
+#define syserr(exp, str, args...) \
+do { \
+ if (exp) \
+ errx(EXIT_FAILURE, "%d: "str, __LINE__, ##args); \
} while (0)
-#define syserrx(exp, str, args...) \
-do { \
- if (exp) \
- errx(EXIT_FAILURE, str, ##args); \
+#define syserrx(exp, str, args...) \
+do { \
+ if (exp) \
+ errx(EXIT_FAILURE, "%d: "str, __LINE__, ##args); \
} while (0)
#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
free(buf);
}
-static size_t add_tids(unsigned int *ids, size_t count, char *arg)
+static size_t add_tids(__u16 *ids, size_t count, char *arg)
{
while (*arg) {
char *end;
int c;
int i;
- unsigned int ids[4096] = { 0 };
+ __u16 ids[4096] = { 0 };
size_t count = 0;
ssize_t result;
fprintf(stdout, "ostlayoutversion: %u\n", layout_version);
}
+enum resync_errors {
+ AFTER_RESYNC_START = 1 << 0,
+ INVALID_IDS = 1 << 1,
+ ZERO_RESYNC_IDS = 1 << 2,
+ DELAY_BEFORE_COPY = 1 << 3,
+ OPEN_TEST_FILE = 1 << 4,
+};
+
+static enum resync_errors resync_parse_error(const char *err)
+{
+ struct {
+ const char *loc;
+ enum resync_errors error;
+ } cmds[] = {
+ { "resync_start", AFTER_RESYNC_START },
+ { "invalid_ids", INVALID_IDS },
+ { "zero_resync_ids", ZERO_RESYNC_IDS },
+ { "delay_before_copy", DELAY_BEFORE_COPY },
+ { "open_test_file", OPEN_TEST_FILE },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cmds); i++)
+ if (strcmp(err, cmds[i].loc) == 0)
+ return cmds[i].error;
+
+ fprintf(stderr, "unknown error string: %s\n", err);
+ return -1;
+}
+
+static void mirror_resync(int argc, char *argv[])
+{
+ const char *fname;
+ int error_inject = 0;
+ int fd;
+ int c;
+ int rc;
+ int delay = 2;
+ int idx;
+
+ struct llapi_layout *layout;
+ struct ll_ioc_lease *ioc;
+ struct llapi_resync_comp comp_array[1024] = { { 0 } };
+ size_t comp_size = 0;
+ uint32_t flr_state;
+ uint64_t start;
+ uint64_t end;
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, "e:d:")) != -1) {
+ switch (c) {
+ case 'e':
+ error_inject |= resync_parse_error(optarg);
+ break;
+ case 'd':
+ delay = atol(optarg);
+ break;
+ default:
+ errx(1, "unknown option: '%s'", argv[optind - 1]);
+ }
+ }
+
+ if (argc > optind + 1)
+ errx(1, "too many files");
+ if (argc == optind)
+ errx(1, "no file name given");
+
+ fname = argv[optind];
+ fd = open_file(fname);
+
+ /* set the lease on the file */
+ ioc = calloc(sizeof(*ioc) + sizeof(__u32) * 4096, 1);
+ syserr(ioc == NULL, "no memory");
+
+ ioc->lil_mode = LL_LEASE_WRLCK;
+ ioc->lil_flags = LL_LEASE_RESYNC;
+ rc = llapi_lease_set(fd, ioc);
+ if (rc < 0)
+ free(ioc);
+ syserr(rc < 0, "llapi_lease_set resync");
+
+ if (error_inject & AFTER_RESYNC_START) {
+ free(ioc);
+ syserrx(1, "hit by error injection");
+ }
+
+ layout = llapi_layout_get_by_fd(fd, 0);
+ if (layout == NULL)
+ free(ioc);
+ syserr(layout == NULL, "llapi_layout_get_by_fd");
+
+ rc = llapi_layout_flags_get(layout, &flr_state);
+ if (rc)
+ free(ioc);
+ syserr(rc, "llapi_layout_flags_get");
+
+ flr_state &= LCM_FL_FLR_MASK;
+ if (flr_state != LCM_FL_WRITE_PENDING &&
+ flr_state != LCM_FL_SYNC_PENDING) {
+ free(ioc);
+ syserrx(true, "file state error: %d", flr_state);
+ }
+
+ if (error_inject & DELAY_BEFORE_COPY)
+ sleep(delay);
+
+ comp_size = llapi_mirror_find_stale(layout, comp_array,
+ ARRAY_SIZE(comp_array), NULL, 0);
+
+ printf("%s: found %zd stale components\n", fname, comp_size);
+
+ /* get the read range [start, end) */
+ start = comp_array[0].lrc_start;
+ end = comp_array[0].lrc_end;
+ for (idx = 1; idx < comp_size; idx++) {
+ if (comp_array[idx].lrc_start < start)
+ start = comp_array[idx].lrc_start;
+ if (end < comp_array[idx].lrc_end)
+ end = comp_array[idx].lrc_end;
+ }
+
+ rc = llapi_lease_check(fd);
+ if (rc != LL_LEASE_WRLCK) {
+ free(ioc);
+ syserr(rc != LL_LEASE_WRLCK, "lost lease lock");
+ }
+
+ rc = llapi_mirror_resync_many(fd, layout, comp_array, comp_size, start,
+ end);
+ if (rc < 0)
+ free(ioc);
+ syserrx(rc < 0, "llapi_mirror_resync_many");
+
+ /* prepare ioc for lease put */
+ ioc->lil_mode = LL_LEASE_UNLCK;
+ ioc->lil_flags = LL_LEASE_RESYNC_DONE;
+ ioc->lil_count = 0;
+ for (idx = 0; idx < comp_size; idx++) {
+ if (comp_array[idx].lrc_synced) {
+ ioc->lil_ids[ioc->lil_count] = comp_array[idx].lrc_id;
+ ioc->lil_count++;
+ }
+ }
+
+ if (error_inject & ZERO_RESYNC_IDS)
+ ioc->lil_count = 0;
+
+ if (error_inject & INVALID_IDS && ioc->lil_count > 0)
+ ioc->lil_ids[ioc->lil_count - 1] = 567; /* inject error */
+
+ llapi_layout_free(layout);
+
+ if (error_inject & OPEN_TEST_FILE) /* break lease */
+ close(open(argv[optind], O_RDONLY));
+
+ rc = llapi_lease_set(fd, ioc);
+ syserr(rc <= 0, "llapi_lease_set resync failed");
+ if (rc <= 0)
+ llapi_lease_release(fd);
+
+ free(ioc);
+ close(fd);
+}
+
static void usage_wrapper(int argc, char *argv[])
{
usage();
{ "dump", mirror_dump, "dump mirror: <-i id> [-o file] FILE" },
{ "copy", mirror_copy, "copy mirror: <-i id> <-t id1,id2> FILE" },
{ "data_version", mirror_ost_lv, "ost layout version: <-i id> FILE" },
+ { "resync", mirror_resync,
+ "resync mirrors: [-e error] [-d delay] FILE" },
{ "help", usage_wrapper, "print helper message" },
};