2 a test implementation of a HSM daemon
4 Andrew Tridgell August 2008
16 #define SESSION_NAME "hacksmd"
18 static void hsm_term_handler(int signal)
20 printf("Got signal %d - exiting\n", signal);
25 static void hsm_init(const char *path)
27 char *dmapi_version = NULL;
28 dm_eventset_t eventSet;
31 ret = dm_init_service(&dmapi_version);
33 printf("Failed to init dmapi\n");
37 printf("Initialised DMAPI version '%s'\n", dmapi_version);
39 hsm_recover_session(SESSION_NAME, &dmapi.sid);
41 /* we want mount events only initially */
43 DMEV_SET(DM_EVENT_MOUNT, eventSet);
44 ret = dm_set_disp(dmapi.sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
45 &eventSet, DM_EVENT_MAX);
47 printf("Failed to setup events\n");
53 static void hsm_handle_mount(dm_eventmsg_t *msg)
55 dm_mount_event_t *mount;
58 dm_eventset_t eventSet;
61 mount = DM_GET_VALUE(msg, ev_data, dm_mount_event_t*);
62 hand1 = DM_GET_VALUE(mount , me_handle1, void *);
63 hand1len = DM_GET_LEN(mount, me_handle1);
66 DMEV_SET(DM_EVENT_READ, eventSet);
67 DMEV_SET(DM_EVENT_WRITE, eventSet);
68 DMEV_SET(DM_EVENT_TRUNCATE, eventSet);
69 DMEV_SET(DM_EVENT_DESTROY, eventSet);
70 ret = dm_set_eventlist(dmapi.sid, hand1, hand1len,
71 DM_NO_TOKEN, &eventSet, DM_EVENT_MAX);
73 printf("Failed to setup all event handler\n");
77 ret = dm_set_disp(dmapi.sid, hand1, hand1len, DM_NO_TOKEN,
78 &eventSet, DM_EVENT_MAX);
80 printf("Failed to setup disposition for all events\n");
84 ret = dm_respond_event(dmapi.sid, msg->ev_token,
85 DM_RESP_CONTINUE, 0, 0, NULL);
87 printf("Failed to respond to mount event\n");
93 static void hsm_handle_recall(dm_eventmsg_t *msg)
99 dm_attrname_t attrname;
100 dm_token_t token = msg->ev_token;
103 dm_boolean_t exactFlag;
109 ev = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
110 hanp = DM_GET_VALUE(ev, de_handle, void *);
111 hlen = DM_GET_LEN(ev, de_handle);
113 memset(attrname.an_chars, 0, DM_ATTR_NAME_SIZE);
114 strncpy((char*)attrname.an_chars, HSM_ATTRNAME, DM_ATTR_NAME_SIZE);
116 ret = dm_request_right(dmapi.sid, hanp, hlen, token, DM_RR_WAIT, DM_RIGHT_EXCL);
118 printf("dm_request_right failed - %s\n", strerror(errno));
124 ret = dm_get_dmattr(dmapi.sid, hanp, hlen, token, &attrname,
125 sizeof(h), &h, &rlen);
127 if (errno == ENOENT) {
128 printf("File already recalled (no attribute)\n");
131 printf("dm_get_dmattr failed - %s\n", strerror(errno));
135 if (rlen != sizeof(h)) {
136 printf("hsm_handle_read - bad attribute size %d\n", (int)rlen);
140 if (strncmp(h.magic, HSM_MAGIC, sizeof(h.magic)) != 0) {
141 printf("Bad magic '%*.*s'\n", (int)sizeof(h.magic), (int)sizeof(h.magic), h.magic);
145 h.state = HSM_STATE_RECALL;
146 ret = dm_set_dmattr(dmapi.sid, hanp, hlen, token, &attrname, 0, sizeof(h), (void*)&h);
148 printf("dm_set_dmattr failed - %s\n", strerror(errno));
152 fd = hsm_store_open(h.device, h.inode, O_RDONLY);
154 printf("Failed to open store file for file 0x%llx:0x%llx\n",
155 (unsigned long long)h.device, (unsigned long long)h.inode);
159 printf("Recalling file %llx:%llx of size %d\n",
160 (unsigned long long)h.device, (unsigned long long)h.inode,
164 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
165 int ret2 = dm_write_invis(dmapi.sid, hanp, hlen, token, DM_WRITE_SYNC, ofs, ret, buf);
167 printf("dm_write_invis failed - %s\n", strerror(errno));
174 ret = dm_remove_dmattr(dmapi.sid, hanp, hlen, token, 0, &attrname);
176 printf("dm_remove_dmattr failed - %s\n", strerror(errno));
180 ret = hsm_store_unlink(h.device, h.inode);
182 printf("Failed to unlink store file\n");
186 ret = dm_set_region(dmapi.sid, hanp, hlen, token, 0, NULL, &exactFlag);
188 printf("failed dm_set_region - %s\n", strerror(errno));
194 ret = dm_release_right(dmapi.sid, hanp, hlen, token);
196 printf("failed dm_release_right on %s\n", strerror(errno));
200 ret = dm_respond_event(dmapi.sid, msg->ev_token,
201 DM_RESP_CONTINUE, retcode, 0, NULL);
203 printf("Failed to respond to read event\n");
209 static void hsm_handle_destroy(dm_eventmsg_t *msg)
211 dm_destroy_event_t *ev;
215 dm_attrname_t attrname;
216 dm_token_t token = msg->ev_token;
219 dm_boolean_t exactFlag;
221 ev = DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
222 hanp = DM_GET_VALUE(ev, ds_handle, void *);
223 hlen = DM_GET_LEN(ev, ds_handle);
225 if (DM_TOKEN_EQ(token, DM_INVALID_TOKEN)) {
229 memset(attrname.an_chars, 0, DM_ATTR_NAME_SIZE);
230 strncpy((char*)attrname.an_chars, HSM_ATTRNAME, DM_ATTR_NAME_SIZE);
232 ret = dm_get_dmattr(dmapi.sid, hanp, hlen, token, &attrname,
233 sizeof(h), &h, &rlen);
235 printf("dm_get_dmattr failed - %s\n", strerror(errno));
239 if (rlen != sizeof(h)) {
240 printf("hsm_handle_read - bad attribute size %d\n", (int)rlen);
244 if (strncmp(h.magic, HSM_MAGIC, sizeof(h.magic)) != 0) {
245 printf("Bad magic '%*.*s'\n", (int)sizeof(h.magic), (int)sizeof(h.magic), h.magic);
249 ret = hsm_store_unlink(h.device, h.inode);
251 printf("Failed to unlink store file for file 0x%llx:0x%llx\n",
252 (unsigned long long)h.device, (unsigned long long)h.inode);
256 ret = hsm_store_unlink(h.device, h.inode);
258 printf("Failed to unlink store file\n");
262 ret = dm_remove_dmattr(dmapi.sid, hanp, hlen, token, 0, &attrname);
264 printf("dm_remove_dmattr failed - %s\n", strerror(errno));
268 ret = dm_set_region(dmapi.sid, hanp, hlen, token, 0, NULL, &exactFlag);
270 printf("failed dm_set_region - %s\n", strerror(errno));
275 if (!DM_TOKEN_EQ(msg->ev_token,DM_NO_TOKEN) &&
276 !DM_TOKEN_EQ(msg->ev_token, DM_INVALID_TOKEN)) {
277 ret = dm_respond_event(dmapi.sid, msg->ev_token,
278 DM_RESP_CONTINUE, retcode, 0, NULL);
280 printf("Failed to respond to destroy event\n");
287 static void hsm_handle_message(dm_eventmsg_t *msg)
289 printf("Got event %s from node 0x%x\n",
290 dmapi_event_string(msg->ev_type), msg->ev_nodeid);
292 switch (msg->ev_type) {
294 hsm_handle_mount(msg);
298 hsm_handle_recall(msg);
300 case DM_EVENT_DESTROY:
301 hsm_handle_destroy(msg);
304 if (!DM_TOKEN_EQ(msg->ev_token,DM_NO_TOKEN) &&
305 !DM_TOKEN_EQ(msg->ev_token, DM_INVALID_TOKEN)) {
306 printf("Giving default response\n");
307 int ret = dm_respond_event(dmapi.sid, msg->ev_token,
308 DM_RESP_CONTINUE, 0, 0, NULL);
310 printf("Failed to respond to mount event\n");
318 static void hsm_cleanup_tokens(void)
324 while ((ret = dm_getall_tokens(dmapi.sid, 10, tok, &n)) == 0 && n > 0) {
325 printf("Cleaning up %u tokens\n", n);
327 dm_respond_event(dmapi.sid, tok[i],
328 DM_RESP_CONTINUE, 0, 0, NULL);
333 static void hsm_wait_events(void)
339 printf("Waiting for events\n");
343 /* we don't use DM_RR_WAIT to ensure that the daemon can be killed */
345 ret = dm_get_events(dmapi.sid, 0, 0, sizeof(buf), buf, &rlen);
347 if (errno == EAGAIN) continue;
348 printf("Failed to get event (%s)\n", strerror(errno));
352 for (msg=(dm_eventmsg_t *)buf; msg; msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *)) {
353 hsm_handle_message(msg);
358 static void usage(void)
360 printf("Usage: hacksmd PATH\n");
364 int main(int argc, char * const argv[])
368 /* parse command-line options */
369 while ((opt = getopt(argc, argv, "h")) != -1) {
389 signal(SIGTERM, hsm_term_handler);
390 signal(SIGINT, hsm_term_handler);
394 hsm_cleanup_tokens();