9 * Monitor all events for a file system.
10 * When one arrives, print a message with all the details.
11 * If the message is synchronous, always reply with DM_RESP_CONTINUE
12 * (This program doesn't perform any real file system or HSM work.)
14 * This is a simplification of the "migin.c" example program.
15 * The original code was by Peter Lawthers:
16 * This code was written by Peter Lawthers, and placed in the public
17 * domain for use by DMAPI implementors and app writers.
25 #include <sys/types.h>
27 #include <sys/resource.h>
29 #include <sys/param.h>
35 * Define some standard formats for the printf statements below.
38 #define HDR "%s: token %d sequence %d\n"
39 #define VALS "\t%-15s %s\n"
40 #define VALD "\t%-15s %d\n"
41 #define VALLLD "\t%-15s %lld\n"
47 int main (int, char **);
48 static void event_loop (dm_sessid_t, int);
49 int handle_message (dm_sessid_t, dm_eventmsg_t *);
50 static int format_mode(mode_t mode, char **ptr);
51 static int get_fs_handle (char *, void **, size_t *);
52 static int set_disposition(dm_sessid_t, void *, size_t);
53 static int set_disp_global(dm_sessid_t);
54 static int set_events (dm_sessid_t, void *, size_t);
55 static int clear_events (dm_sessid_t, void *, size_t);
56 int finish_responding(dm_sessid_t);
57 int establish_handler(void);
58 void exit_handler (int);
69 * Keep these global so the exit_handler and err_msg routines can get to them
75 dm_sessid_t oldsid = 0;
77 int register_new_mnts = 0;
78 int rwt_bit_clear = 1; /* Clear read/write/trunc bit before
79 * responding to event; reset all other
82 int dmf_events = 0; /* Use only those events that DMF uses */
88 fprintf(stderr, "Usage: %s ", prog);
89 fprintf(stderr, " <-S oldsid> <-v> <-s sleep> <-R> <-N> <-D> ");
90 fprintf(stderr, "filesystem \n");
106 /* Progname = argv[0];*/ Progname = "print_event";
109 while ((c = getopt(argc, argv, "vs:S:RND")) != EOF) {
112 Sleep = atoi(optarg);
115 register_new_mnts = 1;
124 oldsid = atoi(optarg);
135 if (optind >= argc) {
139 fsname = argv[optind];
140 if (fsname == NULL) {
146 * Establish an exit handler
148 error = establish_handler();
153 * Init the dmapi, and get a filesystem handle so
154 * we can set up our events
160 error = setup_dmapi(&sid);
165 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
170 * Set the event disposition so that our session will receive
171 * all the events for the given file system
173 error = set_disp_global(sid);
176 error = set_disposition(sid, fs_hanp, fs_hlen);
181 * Enable monitoring for all events in the given file system
183 error = set_events(sid, fs_hanp, fs_hlen);
188 * Now sit in an infinite loop, reporting on any events that occur.
189 * The program is exited after a signal through exit_handler().
192 event_loop(sid, 1 /*waitflag*/);
195 * If we get here, cleanup after the event_loop failure
204 * Main event loop processing
206 * The waitflag argument is set to 1 when we call this from main().
207 * In this case, continuously process incoming events,
208 * blocking if there are none available.
209 * In the exit_handler(), call this routine with waitflag=0.
210 * Just try to read the events once in this case with no blocking.
225 * We take a swag at a buffer size. If it's wrong, we can
229 bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
231 msgbuf = (void *)malloc(bufsize);
232 if (msgbuf == NULL) {
233 err_msg("Can't allocate memory for buffer");
238 error = dm_get_events(sid, ALL_AVAIL_MSGS,
239 waitflag ? DM_EV_WAIT:0, bufsize, msgbuf, &bufsize);
241 if (errno == EAGAIN) {
246 if (errno == E2BIG) {
248 msgbuf = (void *)malloc(bufsize);
249 if (msgbuf == NULL) {
250 err_msg("Can't resize msg buffer");
255 errno_msg("Error getting events from DMAPI (%d)", errno);
260 * Walk through the message buffer, pull out each individual
261 * message, and dispatch the messages to handle_message(),
262 * which will respond to the events.
266 msg = (dm_eventmsg_t *)msgbuf;
267 while (msg != NULL ) {
269 error = handle_message(sid, msg);
274 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
276 if (count != 1 && Verbose) {
277 err_msg("Found %d events in one call to "
278 "dm_get_events\n", count);
287 print_one_mount_event(
290 void *hanp1, *hanp2, *hanp3;
291 size_t hlen1, hlen2, hlen3;
292 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
295 char nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
299 dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
302 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
304 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
305 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
306 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
307 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
308 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
309 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
310 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
311 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
314 mode = msg_ne->ne_mode;
316 dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
318 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
319 hlen1 = DM_GET_LEN(msg_me, me_handle1);
320 hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
321 hlen2 = DM_GET_LEN(msg_me, me_handle2);
322 namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
323 nlen1 = DM_GET_LEN(msg_me, me_name1);
324 namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
325 nlen2 = DM_GET_LEN(msg_me, me_name2);
326 hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
327 hlen3 = DM_GET_LEN(msg_me, me_roothandle);
328 mode = msg_me->me_mode;
329 #endif /* VERITAS_21 */
331 if (hanp1 && hlen1) {
332 hantoa(hanp1, hlen1, hans1);
334 sprintf(hans1, "<BAD HANDLE, hlen %zd>", hlen1);
336 if (hanp2 && hlen2) {
337 hantoa(hanp2, hlen2, hans2);
339 sprintf(hans2, "<BAD HANDLE, hlen %zd>", hlen2);
341 if (hanp3 && hlen3) {
342 hantoa(hanp3, hlen3, hans3);
344 sprintf(hans3, "<BAD HANDLE, hlen %zd>", hlen3);
346 if (namp1 && nlen1) {
347 strncpy(nams1, namp1, nlen1);
348 if (nlen1 != sizeof(nams1))
351 sprintf(nams1, "<BAD STRING, nlen %zd>", nlen1);
353 if (namp2 && nlen2) {
354 strncpy(nams2, namp2, nlen2);
355 if (nlen2 != sizeof(nams2))
358 sprintf(nams2, "<BAD STRING, nlen %zd>", nlen2);
361 printf(VALS VALS VALS VALS VALS VALD,
363 "mtpt handle", hans2,
365 "media desig", nams2,
366 "root handle", hans3,
372 * First, weed out the events which return interesting structures.
373 * If it's not one of those, unpack the dm_namesp_event structure
374 * and display the contents.
383 dm_response_t response;
384 int respond, respcode;
385 dm_namesp_event_t *msg_ne;
387 dm_mount_event_t *msg_me;
389 void *hanp1, *hanp2, *namp1, *namp2;
390 u_int hlen1, hlen2, nlen1, nlen2;
391 char hans1[HANDLE_STR], hans2[HANDLE_STR];
392 char nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
395 * Set the defaults for responding to events
398 response = DM_RESP_CONTINUE;
401 /***** USER EVENTS *****/
403 if (msg->ev_type == DM_EVENT_USER) {
408 "user", msg->ev_token, msg->ev_sequence);
410 /* print private data as ascii or hex if it exists DM_CONFIG_MAX_MESSAGE_DATA */
412 privp = DM_GET_VALUE(msg, ev_data, char *);
413 plen = DM_GET_LEN (msg, ev_data);
415 for (i = 0; i < plen; i++) {
416 if (!isprint(privp[i]) && !isspace(privp[i]))
419 if (i == plen - 1 && privp[i] == '\0') {
423 printf("\t%-15s ", "privdata");
424 for (i = 0; i < plen; i++) {
425 printf("%.2x", privp[i]);
431 "privdata", "<NONE>");
434 if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
438 /***** CANCEL EVENT *****/
440 /* Not implemented on SGI or Veritas */
442 else if (msg->ev_type == DM_EVENT_CANCEL) {
443 dm_cancel_event_t *msg_ce;
445 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
446 printf(HDR VALD VALD,
447 "cancel", msg->ev_token, msg->ev_sequence,
448 "sequence", msg_ce->ce_sequence,
449 "token", msg_ce->ce_token);
453 /***** DATA EVENTS *****/
455 else if (msg->ev_type == DM_EVENT_READ ||
456 msg->ev_type == DM_EVENT_WRITE ||
457 msg->ev_type == DM_EVENT_TRUNCATE) {
458 dm_data_event_t *msg_de;
460 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
461 hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
462 hlen1 = DM_GET_LEN (msg_de, de_handle);
463 if (hanp1 && hlen1) {
464 hantoa(hanp1, hlen1, hans1);
467 switch(msg->ev_type) {
468 /* DM_EVENT_* and DM_REGION_* are different values, ug */
470 rgflag = DM_REGION_READ;
473 rgflag = DM_REGION_WRITE;
475 case DM_EVENT_TRUNCATE:
476 rgflag = DM_REGION_TRUNCATE;
479 err_msg("unexpected event type (%d)\n", msg->ev_type);
480 rgflag = DM_REGION_NOEVENT;
483 clear_region_event(sid, rgflag, hanp1, hlen1, hans1);
486 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
489 switch(msg->ev_type) {
492 printf(HDR VALS VALLLD VALLLD,
493 "read", msg->ev_token, msg->ev_sequence,
494 "file handle", hans1,
495 "offset", (long long) msg_de->de_offset,
496 "length", (long long) msg_de->de_length);
500 printf(HDR VALS VALLLD VALLLD,
501 "write", msg->ev_token, msg->ev_sequence,
502 "file handle", hans1,
503 "offset", (long long) msg_de->de_offset,
504 "length", (long long) msg_de->de_length);
507 case DM_EVENT_TRUNCATE:
508 printf(HDR VALS VALLLD VALLLD,
509 "truncate", msg->ev_token, msg->ev_sequence,
510 "file handle", hans1,
511 "offset", (long long) msg_de->de_offset,
512 "length", (long long) msg_de->de_length);
518 /***** DESTROY EVENT *****/
520 else if (msg->ev_type == DM_EVENT_DESTROY) {
521 dm_destroy_event_t *msg_ds;
522 char attrname[DM_ATTR_NAME_SIZE + 1];
527 msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
528 hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
529 hlen1 = DM_GET_LEN (msg_ds, ds_handle);
530 if (hanp1 && hlen1) {
531 hantoa(hanp1, hlen1, hans1);
533 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
535 if (msg_ds->ds_attrname.an_chars[0] != '\0') {
536 strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
537 attrname[DM_ATTR_NAME_SIZE] = '\0'; /* terminate the string */
539 strcpy(attrname, "<NONE>");
541 printf(HDR VALS VALS,
542 "destroy", msg->ev_token, msg->ev_sequence,
544 "attrname", attrname);
545 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
546 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
548 printf("\t%-15s ", "attrcopy");
549 for (i = 0; i < clen; i++) {
550 printf("%.2x", copy[i]);
554 printf(VALS, "attrcopy", "<NONE>");
559 /***** MOUNT EVENT *****/
561 else if (msg->ev_type == DM_EVENT_MOUNT) {
562 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
564 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
565 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
566 hlen1 = DM_GET_LEN(msg_me, me_handle1);
568 print_one_mount_event(msg_me);
570 if (register_new_mnts) {
571 if (set_disposition(sid, hanp1, hlen1) == 0)
572 set_events(sid, hanp1, hlen1);
575 #else /* VERITAS_21 */
576 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
577 print_one_mount_event(msg_ne);
578 #endif /* VERITAS_21 */
582 /***** NAMESPACE EVENTS *****/
587 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
588 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
589 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
590 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
591 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
592 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
593 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
594 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
595 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
597 if (hanp1 && hlen1) {
598 hantoa(hanp1, hlen1, hans1);
600 if (hanp2 && hlen2) {
601 hantoa(hanp2, hlen2, hans2);
603 if (namp1 && nlen1) {
604 strncpy(nams1, namp1, nlen1);
605 if (nlen1 != sizeof(nams1))
608 if (namp2 && nlen2) {
609 strncpy(nams2, namp2, nlen2);
610 if (nlen2 != sizeof(nams2))
614 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
615 msg->ev_type == DM_EVENT_UNMOUNT) {
616 if (msg_ne->ne_mode == 0) {
619 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
621 } else if (msg_ne->ne_mode > 0) {
628 } else if (msg->ev_type == DM_EVENT_CREATE ||
629 msg->ev_type == DM_EVENT_POSTCREATE ||
630 msg->ev_type == DM_EVENT_REMOVE ||
631 msg->ev_type == DM_EVENT_POSTREMOVE) {
632 if (format_mode(msg_ne->ne_mode, &type)) {
637 switch(msg->ev_type) {
639 case DM_EVENT_PREUNMOUNT:
640 printf(HDR VALS VALS VALS,
641 "preunmount", msg->ev_token, msg->ev_sequence,
644 "unmount mode", type);
647 case DM_EVENT_UNMOUNT:
648 printf(HDR VALS VALS VALD,
649 "unmount", msg->ev_token, msg->ev_sequence,
651 "unmount mode", type,
652 "retcode", msg_ne->ne_retcode);
655 case DM_EVENT_NOSPACE:
657 "nospace", msg->ev_token, msg->ev_sequence,
659 response = DM_RESP_ABORT;
663 case DM_EVENT_DEBUT: /* not supported on SGI */
665 "debut", msg->ev_token, msg->ev_sequence,
669 case DM_EVENT_CREATE:
670 printf(HDR VALS VALS VALS,
671 "create", msg->ev_token, msg->ev_sequence,
677 case DM_EVENT_POSTCREATE:
678 printf(HDR VALS VALS VALS VALS VALD,
679 "postcreate", msg->ev_token, msg->ev_sequence,
684 "retcode", msg_ne->ne_retcode);
686 clear_region_event(sid, 0, hanp2, hlen2, hans2);
689 case DM_EVENT_REMOVE:
690 printf(HDR VALS VALS VALS,
691 "remove", msg->ev_token, msg->ev_sequence,
697 case DM_EVENT_POSTREMOVE:
698 printf(HDR VALS VALS VALS VALD,
699 "postremove", msg->ev_token, msg->ev_sequence,
703 "retcode", msg_ne->ne_retcode);
707 case DM_EVENT_RENAME:
708 printf(HDR VALS VALS VALS VALS,
709 "rename", msg->ev_token, msg->ev_sequence,
716 case DM_EVENT_POSTRENAME:
717 printf(HDR VALS VALS VALS VALS VALD,
718 "postrename", msg->ev_token, msg->ev_sequence,
723 "retcode", msg_ne->ne_retcode);
727 case DM_EVENT_SYMLINK:
728 printf(HDR VALS VALS VALS,
729 "symlink", msg->ev_token, msg->ev_sequence,
735 case DM_EVENT_POSTSYMLINK:
736 printf(HDR VALS VALS VALS VALS VALD,
737 "postsymlink", msg->ev_token, msg->ev_sequence,
742 "retcode", msg_ne->ne_retcode);
747 printf(HDR VALS VALS VALS,
748 "link", msg->ev_token, msg->ev_sequence,
754 case DM_EVENT_POSTLINK:
755 printf(HDR VALS VALS VALS VALD,
756 "postlink", msg->ev_token, msg->ev_sequence,
760 "retcode", msg_ne->ne_retcode);
764 case DM_EVENT_ATTRIBUTE:
766 "attribute", msg->ev_token, msg->ev_sequence,
771 case DM_EVENT_CLOSE: /* not supported on SGI */
773 "close", msg->ev_token, msg->ev_sequence,
781 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
782 "ev_type", msg->ev_type);
783 if (msg->ev_token == DM_INVALID_TOKEN)
790 * Now respond to those messages which require a response
793 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
795 errno_msg("Can't respond to event");
799 err_msg("Sleeping for %d seconds!\n", Sleep);
809 Convert a mode_t field into a printable string.
811 Returns non-zero if the mode_t is invalid. The string is
812 returned in *ptr, whether there is an error or not.
820 static char modestr[100];
824 if (S_ISFIFO(mode)) typestr = "FIFO";
825 else if(S_ISCHR (mode)) typestr = "Character Device";
826 else if(S_ISBLK (mode)) typestr = "Block Device";
827 else if(S_ISDIR (mode)) typestr = "Directory";
828 else if(S_ISREG (mode)) typestr = "Regular File";
829 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
830 else if(S_ISSOCK(mode)) typestr = "Socket";
832 typestr = "<unknown type>";
836 sprintf(modestr, "mode %06o: perm %c%c%c %c%c%c %c%c%c %c%c%c, type %s",
838 mode & S_ISUID ? 's':' ',
839 mode & S_ISGID ? 'g':' ',
840 mode & S_ISVTX ? 't':' ',
841 mode & S_IRUSR ? 'r':'-',
842 mode & S_IWUSR ? 'w':'-',
843 mode & S_IXUSR ? 'x':'-',
844 mode & S_IRGRP ? 'r':'-',
845 mode & S_IWGRP ? 'w':'-',
846 mode & S_IXGRP ? 'x':'-',
847 mode & S_IROTH ? 'r':'-',
848 mode & S_IWOTH ? 'w':'-',
849 mode & S_IXOTH ? 'x':'-',
862 char hans[HANDLE_STR];
864 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
865 errno_msg("Can't get filesystem handle");
869 hantoa(*fs_hanpp, *fs_hlenp, hans);
870 err_msg("File system handle for %s: %s\n", fsname, hans);
877 Set the event disposition for this filesystem to include all valid
878 DMAPI events so that we receive all events for this filesystem.
879 Also set DM_EVENT_MOUNT disposition for the global handle.
880 It does not make sense to specify DM_EVENT_USER in the disposition
881 mask since a session is always unconditionally registered for these
884 Returns non-zero on error.
891 dm_eventset_t eventlist;
894 err_msg("Setting event disposition to send all "
895 "mount events to this session\n");
898 /* DM_EVENT_MOUNT must be sent in a separate request using the global
899 handle. If we ever support more than one filesystem at a time, this
900 request should be moved out of this routine to a place where it is
904 DMEV_ZERO(eventlist);
905 DMEV_SET(DM_EVENT_MOUNT, eventlist);
907 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
908 &eventlist, DM_EVENT_MAX) == -1) {
909 errno_msg("Can't set event disposition for mount");
923 dm_eventset_t eventlist;
926 err_msg("Setting event disposition to send all "
927 "events to this session\n");
930 DMEV_ZERO(eventlist);
932 /* File system administration events. */
934 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
935 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
936 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
938 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
939 lets it be specified in a dm_set_disp call; its just that the
940 event will never be seen on some platforms.
943 DMEV_SET(DM_EVENT_DEBUT, eventlist);
946 /* Namespace events. */
948 DMEV_SET(DM_EVENT_CREATE, eventlist);
949 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
950 DMEV_SET(DM_EVENT_REMOVE, eventlist);
951 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
952 DMEV_SET(DM_EVENT_RENAME, eventlist);
953 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
954 DMEV_SET(DM_EVENT_LINK, eventlist);
955 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
956 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
957 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
959 /* Managed region data events. */
961 DMEV_SET(DM_EVENT_READ, eventlist);
962 DMEV_SET(DM_EVENT_WRITE, eventlist);
963 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
965 /* Metadata events. */
967 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
968 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && !defined(linux)
969 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
971 #if !defined( __sgi) && !defined(linux)
972 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
974 DMEV_SET(DM_EVENT_DESTROY, eventlist);
978 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
980 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
981 &eventlist, DM_EVENT_MAX) == -1) {
982 errno_msg("Can't set event disposition for filesystem");
990 Enable event generation on each valid filesystem-based DMAPI event
991 within the given file system.
993 Returns non-zero on errors.
1002 dm_eventset_t eventlist;
1006 err_msg("Setting event list to enable all "
1007 "DMF-supported events "
1008 "for this file system\n");
1011 err_msg("Setting event list to enable all events "
1012 "for this file system\n");
1015 DMEV_ZERO(eventlist);
1017 /* File system administration events. */
1019 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
1020 EINVAL if specified.
1022 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1023 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1024 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1025 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
1027 /* Namespace events. */
1029 DMEV_SET(DM_EVENT_CREATE, eventlist);
1030 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1031 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1032 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1033 DMEV_SET(DM_EVENT_RENAME, eventlist);
1034 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1035 DMEV_SET(DM_EVENT_LINK, eventlist);
1036 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1037 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1038 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1040 /* Managed region data events. These are not settable by
1041 dm_set_eventlist on a filesystem basis. They are meant
1042 to be set using dm_set_region on regular files only.
1043 However, in the SGI implementation, they are filesystem-settable.
1044 Since this is useful for testing purposes, do it.
1048 /* DM_EVENT_WRITE */
1049 /* DM_EVENT_TRUNCATE */
1051 /* Metadata events. */
1053 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1054 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && ! defined(linux)
1055 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1057 #if !defined( __sgi) && !defined(linux)
1058 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1060 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1062 /* Did we want just the DMF events? */
1064 DMEV_ZERO(eventlist);
1065 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1066 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1069 /* Pseudo-events. */
1071 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1073 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1074 &eventlist, DM_EVENT_MAX) == -1) {
1075 errno_msg("Can't set event list");
1083 Disable monitoring for all events in the DMAPI for the given
1084 file system. This is done before exiting so that future
1085 operations won't hang waiting for their events to be handled.
1087 Returns non-zero on errors.
1096 dm_eventset_t eventlist;
1099 err_msg("Clearing event list to disable all events "
1100 "for this filesystem\n");
1102 DMEV_ZERO(eventlist);
1104 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1105 &eventlist, DM_EVENT_MAX) == -1) {
1106 errno_msg("Can't clear event list");
1122 dm_region_t region = { 0, 0, 0 };
1126 region.rg_flags = DM_REGION_READ|DM_REGION_WRITE|DM_REGION_TRUNCATE;
1127 region.rg_flags &= ~event;
1130 err_msg("Clearing region mask 0x%x for file %s\n",
1132 err_msg("Setting region mask 0x%x\n", region.rg_flags);
1135 if (dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, nelem, ®ion,
1137 errno_msg("Can't set region event");
1145 * Respond to any events which haven't been handled yet.
1146 * dm_getall_tokens provides a list of tokens for the outstanding events.
1147 * dm_find_eventmsg uses the token to lookup the corresponding message.
1148 * The message is passed to handle_message() for normal response processing.
1155 u_int nbytes, ntokens = 0, ret_ntokens, i;
1156 dm_token_t *tokenbuf = NULL, *tokenptr;
1157 size_t buflen = 0, ret_buflen;
1158 char *msgbuf = NULL;
1162 err_msg("Responding to any outstanding delivered event messages\n");
1165 * Initial sizes for the token and message buffers
1167 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1172 * The E2BIG dance...
1173 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1174 * If the routine returns E2BIG, use the returned size and try again.
1175 * If we're already using the returned size, double it and try again.
1179 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1180 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1181 tmpbuf = realloc(tokenbuf, nbytes);
1182 if (tmpbuf == NULL) {
1183 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1188 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1189 } while (error && errno == E2BIG);
1192 errno_msg("Can't get all outstanding tokens");
1196 tokenptr = tokenbuf;
1197 for (i = 0; i < ret_ntokens; i++) {
1199 err_msg("Responding to outstanding event for token %d\n",(int)*tokenptr);
1202 * The E2BIG dance reprise...
1206 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1207 tmpbuf = realloc(msgbuf, buflen);
1208 if (tmpbuf == NULL) {
1209 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1214 error = dm_find_eventmsg(sid, *tokenptr, buflen, msgbuf, &ret_buflen);
1215 } while (error && errno == E2BIG);
1217 errno_msg("Can't find the event message for token %d", (int)*tokenptr);
1221 msg = (dm_eventmsg_t *) msgbuf;
1222 while (msg != NULL) {
1223 error = handle_message(sid, msg);
1226 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1242 * Establish an exit handler since we run in an infinite loop
1245 establish_handler(void)
1247 struct sigaction act;
1250 * Set up signals so that we can wait for spawned children
1252 act.sa_handler = exit_handler;
1254 sigemptyset(&act.sa_mask);
1256 (void)sigaction(SIGHUP, &act, NULL);
1257 (void)sigaction(SIGINT, &act, NULL);
1258 (void)sigaction(SIGQUIT, &act, NULL);
1259 (void)sigaction(SIGTERM, &act, NULL);
1260 (void)sigaction(SIGUSR1, &act, NULL);
1261 (void)sigaction(SIGUSR1, &act, NULL);
1262 (void)sigaction(SIGUSR2, &act, NULL);
1271 * Stop events from being generated for the given file system
1272 * Respond to any events that were delivered but unanswered
1273 * (the event loop may have been in the middle of taking care of the event)
1274 * Try getting any undelivered events but don't block if none are there
1275 * (the file system may have generated an event after we killed dm_get_events)
1276 * Shutdown the session using the global "sid" variable.
1287 err_msg("Exiting...\n");
1289 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1292 error = clear_events(sid, fs_hanp, fs_hlen);
1294 /* just keep going */ ;
1297 error = finish_responding(sid);
1299 /* just keep going */ ;
1301 err_msg("Processing any undelivered event messages\n");
1302 event_loop(sid, 0 /*waitflag*/);
1304 err_msg("Shutting down the session\n");
1306 error = dm_destroy_session(sid);
1308 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");