#define SESSION_NAME "hacksm_migrate"
+static struct {
+ unsigned wait_time;
+} options = {
+ .wait_time = 100,
+};
+
static struct {
dm_sessid_t sid;
+ dm_token_t token;
} dmapi = {
.sid = DM_NO_SESSION
};
static void hsm_term_handler(int signal)
{
+ if (!DM_TOKEN_EQ(dmapi.token,DM_NO_TOKEN)) {
+ dm_respond_event(dmapi.sid, dmapi.token, DM_RESP_CONTINUE, 0, 0, NULL);
+ dmapi.token = DM_NO_TOKEN;
+ }
printf("Got signal %d - exiting\n", signal);
exit(1);
}
void *hanp = NULL;
size_t hlen = 0;
dm_attrname_t attrname;
- dm_token_t token = DM_NO_TOKEN;
char buf[0x1000];
size_t rlen;
struct stat st;
int fd;
int retval = 1;
+ dmapi.token = DM_NO_TOKEN;
+
ret = dm_path_to_handle(discard_const(path), &hanp, &hlen);
if (ret != 0) {
printf("dm_path_to_handle failed for %s - %s\n", path, strerror(errno));
exit(1);
}
- ret = dm_create_userevent(dmapi.sid, 0, NULL, &token);
+ ret = dm_create_userevent(dmapi.sid, 0, NULL, &dmapi.token);
if (ret != 0) {
printf("dm_create_userevent failed for %s - %s\n", path, strerror(errno));
exit(1);
/* getting an exclusive right then downgrading seems to be much more reliable
then going straight to a shared right */
- ret = dm_request_right(dmapi.sid, hanp, hlen, token, DM_RR_WAIT, DM_RIGHT_EXCL);
+ ret = dm_request_right(dmapi.sid, hanp, hlen, dmapi.token, DM_RR_WAIT, DM_RIGHT_EXCL);
if (ret != 0) {
printf("dm_request_right failed for %s - %s\n", path, strerror(errno));
goto respond;
}
- ret = dm_downgrade_right(dmapi.sid, hanp, hlen, token);
+ ret = dm_downgrade_right(dmapi.sid, hanp, hlen, dmapi.token);
if (ret != 0) {
printf("dm_downgrade_right failed for %s - %s\n", path, strerror(errno));
goto respond;
memset(attrname.an_chars, 0, DM_ATTR_NAME_SIZE);
strncpy((char*)attrname.an_chars, HSM_ATTRNAME, DM_ATTR_NAME_SIZE);
- ret = dm_get_dmattr(dmapi.sid, hanp, hlen, token, &attrname,
+ ret = dm_get_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname,
sizeof(h), &h, &rlen);
if (ret != 0 && errno != ENOENT) {
printf("dm_get_dmattr failed for %s - %s\n", path, strerror(errno));
}
ofs = 0;
- while ((ret = dm_read_invis(dmapi.sid, hanp, hlen, token, ofs, sizeof(buf), buf)) > 0) {
+ while ((ret = dm_read_invis(dmapi.sid, hanp, hlen, dmapi.token, ofs, sizeof(buf), buf)) > 0) {
if (write(fd, buf, ret) != ret) {
printf("Failed to write to store for %s - %s\n", path, strerror(errno));
hsm_store_unlink(st.st_dev, st.st_ino);
/* this sleep is to work around a race in dmapi on GPFS. A read might have started
before we setup the managed region. We need the read to complete before
we can punch holes in the file. There must be a better way .... */
- msleep(1);
+ if (options.wait_time) {
+ msleep(options.wait_time);
+ }
/* now upgrade to a exclusive right on the file */
- ret = dm_upgrade_right(dmapi.sid, hanp, hlen, token);
+ ret = dm_upgrade_right(dmapi.sid, hanp, hlen, dmapi.token);
if (ret != 0) {
printf("dm_upgrade_right failed for %s - %s\n", path, strerror(errno));
goto respond;
h.inode = st.st_ino;
h.state = HSM_STATE_START;
- ret = dm_set_dmattr(dmapi.sid, hanp, hlen, token, &attrname, 0, sizeof(h), (void*)&h);
+ ret = dm_set_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname, 0, sizeof(h), (void*)&h);
if (ret == -1) {
printf("failed dm_set_dmattr on %s - %s\n", path, strerror(errno));
hsm_store_unlink(st.st_dev, st.st_ino);
region.rg_size = st.st_size;
region.rg_flags = DM_REGION_WRITE | DM_REGION_READ;
- ret = dm_set_region(dmapi.sid, hanp, hlen, token, 1, ®ion, &exactFlag);
+ ret = dm_set_region(dmapi.sid, hanp, hlen, dmapi.token, 1, ®ion, &exactFlag);
if (ret == -1) {
printf("failed dm_set_region on %s - %s\n", path, strerror(errno));
hsm_store_unlink(st.st_dev, st.st_ino);
}
/* give those pesky reads another chance */
- ret = dm_downgrade_right(dmapi.sid, hanp, hlen, token);
+ ret = dm_downgrade_right(dmapi.sid, hanp, hlen, dmapi.token);
if (ret != 0) {
printf("dm_downgrade_right failed for %s - %s\n", path, strerror(errno));
goto respond;
}
- msleep(1);
+ if (options.wait_time) {
+ msleep(options.wait_time);
+ }
- ret = dm_upgrade_right(dmapi.sid, hanp, hlen, token);
+ ret = dm_upgrade_right(dmapi.sid, hanp, hlen, dmapi.token);
if (ret != 0) {
printf("dm_downgrade_right failed for %s - %s\n", path, strerror(errno));
goto respond;
}
- ret = dm_get_dmattr(dmapi.sid, hanp, hlen, token, &attrname,
+ ret = dm_get_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname,
sizeof(h), &h, &rlen);
if (ret != 0) {
printf("Abandoning partial migrate - attribute gone\n");
goto respond;
}
- ret = dm_punch_hole(dmapi.sid, hanp, hlen, token, 0, st.st_size);
+ ret = dm_punch_hole(dmapi.sid, hanp, hlen, dmapi.token, 0, st.st_size);
if (ret == -1) {
printf("failed dm_punch_hole on %s - %s\n", path, strerror(errno));
hsm_store_unlink(st.st_dev, st.st_ino);
h.state = HSM_STATE_MIGRATED;
- ret = dm_set_dmattr(dmapi.sid, hanp, hlen, token, &attrname, 0, sizeof(h), (void*)&h);
+ ret = dm_set_dmattr(dmapi.sid, hanp, hlen, dmapi.token, &attrname, 0, sizeof(h), (void*)&h);
if (ret == -1) {
printf("failed dm_set_dmattr on %s - %s\n", path, strerror(errno));
hsm_store_unlink(st.st_dev, st.st_ino);
retval = 0;
respond:
- ret = dm_respond_event(dmapi.sid, token, DM_RESP_CONTINUE, 0, 0, NULL);
+ ret = dm_respond_event(dmapi.sid, dmapi.token, DM_RESP_CONTINUE, 0, 0, NULL);
if (ret == -1) {
printf("failed dm_respond_event on %s - %s\n", path, strerror(errno));
exit(1);
}
+
+ dmapi.token = DM_NO_TOKEN;
dm_handle_free(hanp, hlen);
return retval;
static void usage(void)
{
- printf("Usage: hacksm_migrate PATH..\n");
+ printf("Usage: hacksm_migrate <options> PATH..\n");
+ printf("\n\tOptions:\n");
+ printf("\t\t -w WAITTIME time to wait in migrate (milliseconds)\n");
+ printf("\t\t -c cleanup lost tokens\n");
exit(0);
}
int main(int argc, char * const argv[])
{
int opt, i, ret=0;
+ bool cleanup = false;
/* parse command-line options */
- while ((opt = getopt(argc, argv, "h")) != -1) {
+ while ((opt = getopt(argc, argv, "hw:c")) != -1) {
switch (opt) {
+ case 'w':
+ options.wait_time = strtoul(optarg, NULL, 0);
+ break;
+ case 'c':
+ cleanup = true;
+ break;
case 'h':
default:
usage();
argv += optind;
argc -= optind;
- if (argc == 0) {
- usage();
+ if (cleanup) {
+ hsm_cleanup_tokens(dmapi.sid);
+ if (argc == 0) {
+ return 0;
+ }
}
signal(SIGTERM, hsm_term_handler);
hsm_init();
+ if (argc == 0) {
+ usage();
+ }
+
for (i=0;i<argc;i++) {
ret |= hsm_migrate(argv[i]);
}
}
-static void hsm_init(const char *path)
+static void hsm_init(void)
{
char *dmapi_version = NULL;
dm_eventset_t eventSet;
}
done:
- if (have_right) {
- ret = dm_release_right(dmapi.sid, hanp, hlen, token);
- if (ret == -1) {
- printf("failed dm_release_right on %s\n", strerror(errno));
- }
- }
-
ret = dm_respond_event(dmapi.sid, msg->ev_token,
DM_RESP_CONTINUE, retcode, 0, NULL);
if (ret != 0) {
printf("Failed to respond to read event\n");
exit(1);
}
+
+ if (have_right) {
+ ret = dm_release_right(dmapi.sid, hanp, hlen, token);
+ if (ret == -1) {
+ printf("failed dm_release_right on %s\n", strerror(errno));
+ }
+ }
}
}
}
-static void hsm_cleanup_tokens(void)
-{
- dm_token_t tok[10];
- u_int n;
- int ret, i;
-
- while ((ret = dm_getall_tokens(dmapi.sid, 10, tok, &n)) == 0 && n > 0) {
- printf("Cleaning up %u tokens\n", n);
- for (i=0;i<n;i++) {
- dm_respond_event(dmapi.sid, tok[i],
- DM_RESP_CONTINUE, 0, 0, NULL);
- }
- }
-}
-
static void hsm_wait_events(void)
{
int ret;
static void usage(void)
{
- printf("Usage: hacksmd PATH\n");
+ printf("Usage: hacksmd <options>\n");
+ printf("\n\tOptions:\n");
+ printf("\t\t -c cleanup lost tokens\n");
exit(0);
}
int main(int argc, char * const argv[])
{
int opt;
- char *fspath;
+ bool cleanup = false;
+
/* parse command-line options */
- while ((opt = getopt(argc, argv, "h")) != -1) {
+ while ((opt = getopt(argc, argv, "ch")) != -1) {
switch (opt) {
+ case 'c':
+ cleanup = true;
+ break;
case 'h':
default:
usage();
argv += optind;
argc -= optind;
- if (argc == 0) {
- usage();
- }
-
- fspath = argv[0];
-
signal(SIGTERM, hsm_term_handler);
signal(SIGINT, hsm_term_handler);
- hsm_init(fspath);
+ hsm_init();
+
+ hsm_cleanup_tokens(dmapi.sid);
- hsm_cleanup_tokens();
+ if (cleanup) {
+ return 0;
+ }
hsm_wait_events();