Beispiel #1
0
int
print_one_message(
    dm_eventmsg_t	*msg)
{
    int		pkt_error = 0;
    dm_namesp_event_t  *msg_ne;
    void		*hanp1, *hanp2, *namp1, *namp2;
    u_int		hlen1, hlen2, nlen1, nlen2;
    char		hans1[HANDLE_STR], hans2[HANDLE_STR];
    char		nams1[MAXNAMELEN], nams2[MAXNAMELEN];

    /***** USER EVENTS *****/

    if (msg->ev_type == DM_EVENT_USER) {
        char	*privp;
        u_int	plen, i;

        printf(HDR,
               "user", msg->ev_token, msg->ev_sequence);

        /* print private data as ascii or hex if it exists DM_CONFIG_MAX_MESSAGE_DATA */

        privp = DM_GET_VALUE(msg, ev_data, char *);
        plen  = DM_GET_LEN  (msg, ev_data);
        if (plen) {
            for (i = 0; i < plen; i++) {
                if (!isprint(privp[i]) && !isspace(privp[i]))
                    break;
            }
            if (i == plen - 1 && privp[i] == '\0') {
                printf(VALS,
                       "privdata", privp);
            } else {
                printf("\t%-15s ", "privdata");
                for (i = 0; i < plen; i++) {
                    printf("%.2x", privp[i]);
                }
                printf("\n");
            }
        } else {
            printf(VALS,
                   "privdata", "<NONE>");
        }

        /***** CANCEL EVENT *****/

        /* Not implemented on SGI or Veritas */

    } else if (msg->ev_type == DM_EVENT_CANCEL) {
Beispiel #2
0
static int
print_one_data_event(
    dm_data_event_t	*msg_de)
{
    char		handle[HANDLE_STR];
    void		*hanp;
    size_t		hlen;

    hanp  = DM_GET_VALUE(msg_de, de_handle, void *);
    hlen  = DM_GET_LEN  (msg_de, de_handle);

    if (hanp && hlen) {
        hantoa(hanp, hlen, handle);
    } else {
        sprintf(handle, "<BAD HANDLE, hlen %d>", hlen);
    }

    printf(VALS VALLLD VALLLD,
           "file handle",	handle,
           "offset", msg_de->de_offset,
           "length", msg_de->de_length);

    return(0);
}
Beispiel #3
0
void *Thread(void *parm)
{
	int rc;
	size_t dmMsgBufLen;
	dm_eventmsg_t *dmMsg;
	int bMounted = DM_FALSE;
	dm_eventtype_t type;
	dm_token_t token;
	dm_eventset_t events;
	dm_response_t response;

	do {
		/* Loop until message received (wait could be interrupted) */
		do {
			DMLOG_PRINT(DMLVL_DEBUG, "Waiting for event...\n");
			dmMsgBufLen = 0;

			rc = dm_get_events(sid, 1, DM_EV_WAIT, sizeof(dmMsgBuf), dmMsgBuf, &dmMsgBufLen);
			DMLOG_PRINT(DMLVL_DEBUG, "... dm_get_events returned %d (errno %d)\n", rc, errno);
		} while ((rc == -1) && (errno == EINTR) && (dmMsgBufLen == 0));

		if (rc) {
			DMLOG_PRINT(DMLVL_ERR, "dm_get_events failed with rc = %d, errno = %d\n", rc, errno);
			dm_destroy_session(sid);
			DM_EXIT();
		} else {
			dmMsg = (dm_eventmsg_t *)dmMsgBuf;
			token = dmMsg->ev_token;
			type = dmMsg->ev_type;

			DMLOG_PRINT(DMLVL_DEBUG, "Received message %d\n", type);
		}

		if (type == DM_EVENT_MOUNT) {
			/* SPECIAL CASE: need to set disposition, events and response */
			dm_mount_event_t *me = DM_GET_VALUE(dmMsg, ev_data, dm_mount_event_t *);
			void *lhanp = DM_GET_VALUE(me, me_handle1, void *);
			size_t lhlen = DM_GET_LEN(me, me_handle1);

			DMLOG_PRINT(DMLVL_DEBUG, "Message is DM_EVENT_MOUNT\n");
			DMLOG_PRINT(DMLVL_DEBUG, "  Mode: %x\n", me->me_mode);
			DMLOG_PRINT(DMLVL_DEBUG, "  File system handle: %p\n", lhanp);
			DMLOG_PRINT(DMLVL_DEBUG, "  File system handle length: %d\n", lhlen);
			DMLOG_PRINT(DMLVL_DEBUG, "  Mountpoint handle: %p\n", DM_GET_VALUE(me, me_handle2, void *));
			DMLOG_PRINT(DMLVL_DEBUG, "  Mountpoint handle length: %d\n", DM_GET_LEN(me, me_handle2));
			DMLOG_PRINT(DMLVL_DEBUG, "  Mountpoint path: %s\n", DM_GET_VALUE(me, me_name1, char *));
			DMLOG_PRINT(DMLVL_DEBUG, "  Media designator: %s\n", DM_GET_VALUE(me, me_name2, char *));
			DMLOG_PRINT(DMLVL_DEBUG, "  Root handle: %p\n", DM_GET_VALUE(me, me_roothandle, void *));
			DMLOG_PRINT(DMLVL_DEBUG, "  Root handle length: %d\n", DM_GET_LEN(me, me_roothandle));
	   
    			bMounted = dm_handle_is_valid(lhanp, lhlen);

    			rc = dm_request_right(sid, lhanp, lhlen, token, DM_RR_WAIT, DM_RIGHT_EXCL);
			if (rc == -1) {
				DMLOG_PRINT(DMLVL_ERR, "dm_request_right failed! (rc = %d, errno = %d)\n", rc, errno);
				dm_destroy_session(sid);
				DM_EXIT();
			}

			DMEV_ZERO(events);
			DMEV_SET(DM_EVENT_PREUNMOUNT, events);
			DMEV_SET(DM_EVENT_UNMOUNT, events);
			DMEV_SET(DM_EVENT_READ, events);
			DMEV_SET(DM_EVENT_WRITE, events);
			rc = dm_set_disp(sid, lhanp, lhlen, token, &events, DM_EVENT_MAX);
			if (rc == -1) {
				DMLOG_PRINT(DMLVL_ERR, "dm_set_disp failed! (rc = %d, errno = %d)\n", rc, errno);
				dm_destroy_session(sid);
				DM_EXIT();
			}

			DMEV_ZERO(events);
			DMEV_SET(DM_EVENT_PREUNMOUNT, events);
			DMEV_SET(DM_EVENT_UNMOUNT, events);
			rc = dm_set_eventlist(sid, lhanp, lhlen, token, &events, DM_EVENT_MAX);
			if (rc == -1) {
				DMLOG_PRINT(DMLVL_ERR, "dm_set_eventlist failed! (rc = %d, errno = %d)\n", rc, errno);
				dm_destroy_session(sid);
				DM_EXIT();
			}

    			rc = dm_release_right(sid, lhanp, lhlen, token);
			if (rc == -1) {
				DMLOG_PRINT(DMLVL_ERR, "dm_request_right failed! (rc = %d, errno = %d)\n", rc, errno);
				dm_destroy_session(sid);
				DM_EXIT();
			}

			response = DM_RESP_CONTINUE;
		} else if (type == DM_EVENT_UNMOUNT) {
			dm_namesp_event_t *nse = DM_GET_VALUE(dmMsg, ev_data, dm_namesp_event_t *);
			if (nse->ne_retcode == 0) {
				bMounted = DM_FALSE;
			}

			response = DM_RESP_CONTINUE;
		} else {
Beispiel #4
0
/*
 * First, weed out the events which return interesting structures.
 * If it's not one of those, unpack the dm_namesp_event structure
 * and display the contents.
 */
int
handle_message(
	       dm_sessid_t	sid,
	       dm_eventmsg_t	*msg)
{
  int			pkt_error = 0;
  int			error;
  dm_response_t		response = DM_RESP_INVALID;
  int			respond, respcode = 0;
  dm_namesp_event_t	*msg_ne;
#if	!VERITAS
    dm_mount_event_t	*msg_me;
#endif
  void			*hanp1, *hanp2, *namp1, *namp2;
  u_int			hlen1, hlen2, nlen1, nlen2;
  char			hans1[HANDLE_STR], hans2[HANDLE_STR];
  char			nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
  void		        *fs_hanp;
  size_t		fs_hlen;
  dm_timestruct_t       *pending_time;

  /*
   * Set the defaults for responding to events
   */

  /*****************************************************
   *     If the daemon is feeling unfriendly, it will
   *  respond (when necessary) with DM_RESP_ABORT, rather
   *  than the standard DM_RESP_CONTINUE.
   *
   *     While unfriendly, the daemon normally returns
   *  a respcode of "unfriendly_errno".  This defaults to 
   *  EBADMSG but can be set when unfriendly mode is
   *  activated.
   *****************************************************/

  respond = 1;
  if (unfriendly_count==0) {
    response = friendly ? DM_RESP_CONTINUE : DM_RESP_ABORT;
    respcode = friendly ? 0 : unfriendly_errno;
  }
  else if (unfriendly_count > 0) {
    if (unfriendly_count-- == 0) {
      response = DM_RESP_CONTINUE;
      respcode = 0;
    }
    else {
      response = DM_RESP_ABORT;
      respcode = unfriendly_errno;
    }    
  }
  
  if (pending_count >= 0) {
    if (msg->ev_type != DM_EVENT_USER) {
      if (pending_count-- == 0) {
	int i;
	for (i=arr_top; i>=0; --i) {
	  dm_respond_event(sid, token_arr[i], 
			   DM_RESP_CONTINUE, 0, 0, 0);
	}
	response = DM_RESP_CONTINUE;
	respcode = 0;
      }
      else {
        if (pending_count<10) {
	  token_arr[pending_count]=msg->ev_token;
	}
	pending_time = malloc(sizeof(dm_timestruct_t));
	pending_time->dm_tv_sec=0;
	pending_time->dm_tv_nsec=0;
	dm_pending(sid, msg->ev_token, pending_time);
	printf("pending\ntries left\t:%d\n",pending_count);
	return 0;
      }
    } 
  }

  /***** USER EVENTS *****/

  if (msg->ev_type == DM_EVENT_USER) {
    char	*privp;
    u_int	plen, i;

    printf(HDR,
		"user", msg->ev_token, msg->ev_sequence);

    /* print private data as ascii or hex if it exists 
       DM_CONFIG_MAX_MESSAGE_DATA */

    privp = DM_GET_VALUE(msg, ev_data, char *);
    plen  = DM_GET_LEN  (msg, ev_data);
    if (plen) {
	for (i = 0; i < plen; i++) {
		if (!isprint(privp[i]) && !isspace(privp[i]))
			break;
	}
	if (i == plen - 1 && privp[i] == '\0') {
	  /*****************************************************
	   *  Here, we check the messages from send_message.
	   *  Some of them have special meanings.
	   *****************************************************/
	  if (strncmp(privp, "over", 4)==0) {
	    response = DM_RESP_CONTINUE;
	    respcode = 0;
	  }
	  else if (strncmp(privp, "pending", 7)==0){
	    if (strlen(privp)>8) {
	      sscanf(privp, "pending%*c%d", &pending_count);
	    }	  
	    else {
	      pending_count=1;
	    }
	    arr_top=pending_count-1;
	  }
	  else if (strncmp(privp, "reset_fs", 8)==0){
	    if (get_fs_handle(fsname, &fs_hanp, &fs_hlen)){
	      strcpy(privp, "error");
	    }
	    else if (set_disposition(sid, fs_hanp, fs_hlen)){
	      strcpy(privp, "error");
	    }
	    else if (set_events(sid, fs_hanp, fs_hlen)){
	      strcpy(privp, "error");
	    }
	  }
	  else if (strncmp(privp, "friendly", 8)==0) {
	    friendly = 1;
	    response = DM_RESP_CONTINUE;
	    respcode = 0;
	  }
	  else if (strncmp(privp, "unfriendly", 10)==0) {
	    friendly = 0;
	    response = DM_RESP_CONTINUE;
	    respcode = 0;
	    if (strlen(privp)>11) {
	      sscanf(privp, "unfriendly%*c%d", &unfriendly_errno);
	    }
	    else {
	      unfriendly_errno=EBADMSG;
	    }
	  }
	  else if (strncmp(privp, "countdown", 9)==0) {
	    response = DM_RESP_CONTINUE;
	    respcode = 0;
	    
	    if (strlen(privp)>10) {
	      sscanf(privp, "countdown%*c%d%*c%d",
		     &unfriendly_count, &unfriendly_errno); 
	    }
	    else {
	      unfriendly_count=5;
	      unfriendly_errno=EAGAIN;
	    }
	  }


	  printf(VALS,
			"privdata", privp);

	} else {
          printf("privdata      :");
          for (i = 0; i < plen; i++) {
	    printf("%.2x", privp[i]);
          }
          printf("\n");
	}
    } else {
	printf(VALS,
		"privdata", "<NONE>");
    }

    if (msg->ev_token == DM_INVALID_TOKEN)	/* async dm_send_msg event */
      respond = 0;
  }
Beispiel #5
0
void
print_one_mount_event(
	void		*msg)
{
	void		*hanp1, *hanp2, *hanp3;
	size_t		hlen1, hlen2, hlen3;
	char		hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
	void		*namp1, *namp2;
	size_t		nlen1, nlen2;
	char		nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
	mode_t		mode;

#if	VERITAS
	dm_namesp_event_t  *msg_ne = (dm_namesp_event_t *)msg;

	msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
	hanp1  = DM_GET_VALUE(msg_ne, ne_handle1, void *);
	hlen1  = DM_GET_LEN  (msg_ne, ne_handle1);
	hanp2  = DM_GET_VALUE(msg_ne, ne_handle2, void *);
	hlen2  = DM_GET_LEN  (msg_ne, ne_handle2);
	namp1  = DM_GET_VALUE(msg_ne, ne_name1, void *);
	nlen1  = DM_GET_LEN  (msg_ne, ne_name1);
	namp2  = DM_GET_VALUE(msg_ne, ne_name2, void *);
	nlen2  = DM_GET_LEN  (msg_ne, ne_name2);
	rootp  = NULL;
	rlen   = 0;
	mode   = msg_ne->ne_mode;
#else
	dm_mount_event_t  *msg_me = (dm_mount_event_t *)msg;

	hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
	hlen1 = DM_GET_LEN(msg_me, me_handle1);
	hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
	hlen2 = DM_GET_LEN(msg_me, me_handle2);
	namp1  = DM_GET_VALUE(msg_me, me_name1, void *);
	nlen1 = DM_GET_LEN(msg_me, me_name1);
	namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
	nlen2 = DM_GET_LEN(msg_me, me_name2);
	hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
	hlen3 = DM_GET_LEN(msg_me, me_roothandle);
	mode  = msg_me->me_mode;
#endif	/* VERITAS */

	if (hanp1 && hlen1) {
		hantoa(hanp1, hlen1, hans1);
	} else {
		sprintf(hans1, "<BAD_HANDLE_hlen_%zd>", hlen1);
	}
	if (hanp2 && hlen2) {
		hantoa(hanp2, hlen2, hans2);
	} else {
		sprintf(hans2, "<BAD_HANDLE_hlen_%zd>", hlen2);
	}
	if (hanp3 && hlen3) {
		hantoa(hanp3, hlen3, hans3);
	} else {
		sprintf(hans3, "<BAD_HANDLE_hlen_%zd>", hlen3);
	}
	if (namp1 && nlen1) {
		strncpy(nams1, namp1, nlen1);
		if (nlen1 != sizeof(nams1))
			nams1[nlen1] = '\0';
	} else {
		sprintf(nams1, "<BAD STRING_nlen_%zd>", nlen1);
	}
	if (namp2 && nlen2) {
		strncpy(nams2, namp2, nlen2);
		if (nlen2 != sizeof(nams2))
			nams2[nlen2] = '\0';
	} else {
		sprintf(nams2, "<BAD_STRING_nlen_%zd>", nlen2);
	}

	printf(VALS VALS VALS VALS VALS VALD,
	     "fs handle",	hans1,
	     "mtpt handle",	hans2,
	     "mtpt path",	nams1,
	     "media desig",	nams2,
	     "root handle",	hans3,
    	     "mode",		mode);
}
Beispiel #6
0
/*
 * Get the attributes for all the files in a filesystem in bulk,
 * and print out the handles and sizes of any that meet our target
 * criteria.
 *
 * We are not interested in file names; if we were, then we would 
 * have to do a dm_get_dirattrs() on each directroy, then use 
 * dm_handle_to_path() to get the pathname. 
 */
int
scan_fs(
	dm_sessid_t 	 sid, 
	void		*fs_hanp, 
	size_t 	 	 fs_hlen, 
	dm_off_t	 target_size)
{
	u_int		 mask;			/* attributes to scan for */
	dm_stat_t	*dm_statbuf, *sbuf;	/* attributes buffer */
	dm_attrloc_t	 locp;			/* opaque location in fs */
	size_t		 rlenp;			/* ret length of stat info */
	size_t		 buflen;		/* length of stat buffer */
	void		*hanp;			/* file handle */
	size_t	 	 hlen;			/* file handle */
	int		 more;			/* loop terminator */
	int		 error; 


	/*
	 * Size the stat buffer to return info on 1K files at a time
	 */
	buflen     = sizeof(dm_stat_t) * 1024;
#ifdef	VERITAS_21
	if (buflen > 65536)
		buflen = 65536;
#endif
	dm_statbuf = (dm_stat_t *)calloc(1, buflen);
	if (dm_statbuf == NULL)  {
		err_msg("Can't get memory for stat buffer");
		return(1);
	}


	/*
	 * Initialize the offset opaque offset cookie that
	 * we use in successive calls to dm_get_bulkattr()
	 */
	error = dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &locp);
	if (error == -1) {
		errno_msg("%s/%d: Can't initialize offset cookie (%d)", __FILE__, __LINE__, errno);
		free(dm_statbuf);
		return(1);
	}

	/*
	 * Set our stat mask so that we'll only get the normal stat(2)
	 * info and the file's handle
	 */
	mask = DM_AT_HANDLE | DM_AT_STAT;
	do {
		more = dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
				       mask, &locp, buflen, dm_statbuf, &rlenp);
		if (more == -1) {
			errno_msg("%s/%d: Can't get bulkattr for filesystem", __FILE__, __LINE__, errno);
			break;
		}

		/*
		 * Walk through the stat buffer and pull out files 
		 * that are of interest
		 *
		 * The stat buffer is variable length, so we must
		 * use the DM_STEP_TO_NEXT macro to access each individual
		 * dm_stat_t structure in the returned buffer.
		 */
		sbuf = dm_statbuf;
		while (sbuf != NULL) {
			if (S_ISREG(sbuf->dt_mode) &&
			    sbuf->dt_size >= target_size) {	
				hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
				hlen = DM_GET_LEN(sbuf, dt_handle);

				print_victim(hanp, hlen, sbuf->dt_size);
			}
			sbuf = DM_STEP_TO_NEXT(sbuf, dm_stat_t *);
		}
	} while (more == 1);

	free(dm_statbuf);
	if (more == -1) 
		return(1);

	return(0);
}
// token recovery
void token_recovery(int event_rec) {
  int           error = 0;
  u_int         nbytes, ntokens = 0, ret_ntokens, i;
  dm_token_t    *tokenbuf = NULL, *tokenptr;
  size_t        buflen=0, ret_buflen;
  char          *msgbuf = NULL;
  dm_eventmsg_t *msg;
  void            *hanp;
  size_t           hlen;
  dm_data_event_t *msgev; 

  // Initial sizes for the token and message buffers
  ret_buflen=16*(sizeof(dm_eventmsg_t)+sizeof(dm_data_event_t)+HANDLE_LEN);
  ret_ntokens = 16;

  // get the list of tokens
  do {
    dm_token_t *tmpbuf;
    ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
    nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
    tmpbuf = realloc(tokenbuf, nbytes);
    if (tmpbuf == NULL) {
      fprintf(stderr,"Can't malloc %d bytes for tokenbuf\n", nbytes);
      exit_program(0);
    }

    tokenbuf = tmpbuf;
    error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
  } while (error && errno == E2BIG);

  if (error) {
    fprintf(stderr,"Can't get all outstanding tokens\n");
    exit_program(0);
  }

  tokenptr = tokenbuf;
  for (i = 0; i < ret_ntokens; i++) {

    do {
      char *tmpbuf;
      buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
      tmpbuf = realloc(msgbuf, buflen);
      if (tmpbuf == NULL) {
        fprintf(stderr,"Can't malloc %lu bytes for msgbuf\n", (long unsigned int)buflen);
        exit_program(0);
      }
      msgbuf = tmpbuf;
      error = dm_find_eventmsg(sid, *tokenptr, buflen, msgbuf, &ret_buflen);
    } while (error && errno == E2BIG);
    if (error) {
      fprintf(stderr,"Can't find the event message for token %llu %llu\n", tokenptr->high,tokenptr->low);
      exit_program(0);
    }

    msg = (dm_eventmsg_t *) msgbuf;
    while (msg != NULL) {
      // get file handle 
      msgev  = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
      hanp = DM_GET_VALUE(msgev, de_handle, void *);
      hlen = DM_GET_LEN(msgev, de_handle);

      if(event_rec==msg->ev_type) {
        if (Verbose)
          fprintf(stderr,"Recovering outstanding event for token %llu %llu\n",tokenptr->high,tokenptr->low);

        switch (msg->ev_type) {
           case DM_EVENT_MOUNT:
           spawn_child(msg->ev_token, hanp, hlen, "MOUNT");
           break;
         case DM_EVENT_READ:
           spawn_child(msg->ev_token, hanp, hlen, "READ");
           break;
         case DM_EVENT_WRITE:
           spawn_child(msg->ev_token, hanp, hlen, "WRITE");
           break;
         case DM_EVENT_TRUNCATE:
           spawn_child(msg->ev_token, hanp, hlen, "TRUNC");
           break;
         default:
           fprintf(stderr,"Invalid msg type %d\n", msg->ev_type);
           break;
        }
      }
      // go to next event
      msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
    }

    tokenptr++;
  }

  if (tokenbuf) free(tokenbuf);
  if (msgbuf) free(msgbuf);

}
// main event loop
void event_loop() {
  void *msgbuf;
  size_t bufsize, rlen;
  int error;
  dm_eventmsg_t *msg;
  pid_t process_id;

  void *hanp;
  size_t hlen;
  dm_data_event_t *msgev;

  int first_time=1;

  // define inizial message buffer size
  bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
  bufsize *= 16;
  msgbuf  = (void *)malloc(bufsize);
  if (msgbuf == NULL) {
    fprintf(stderr,"Can't allocate memory for buffer\n");
    goto out;
  }

  // start infinite loop
  for (;;) {
    // cleanup all finished children
    while (child_proc_count) {
      process_id = waitpid((pid_t) -1, NULL, WNOHANG);
      if (process_id < 0) { // waitpid error
        fprintf(stderr, "cannot waitpid\n");
        exit(1);
      } else if (process_id == 0)  break; // no child to wait
      else {
        child_proc_count--;  // cleaned up one child
        if(Verbose) {
           fprintf(stderr,"Cleanup child with pid %d\n",process_id);
        }
      }
    }

    // if initialization is not finished, try to finalize
    if(global_state==1) finalize_init();

    // check if filesystem is mounted, otherwise exit
    if(global_state==2&&!filesystem_is_mounted()) exit_program(0);

    // sleep for MAIN_LOOP_SLEEP_TIME mus
    usleep(MAIN_LOOP_SLEEP_TIME);

    // check if maximum number of children has been reached
    if(child_proc_count>=MAXIMUM_ALLOWED_CHILDREN) {
      if(first_time) printf("Maximum number of children reached %d/%d\n",child_proc_count,MAXIMUM_ALLOWED_CHILDREN);
      first_time=0;
      continue;
    }

    if(!first_time) {
      printf("Number of children back to normality %d/%d\n",child_proc_count,MAXIMUM_ALLOWED_CHILDREN);
      first_time=1;
    }

    // get MAXIMUM_MESSAGES available event messages with unblocking call
    error = dm_get_events(sid, MAXIMUM_MESSAGES, 0, bufsize, msgbuf, &rlen);
    if (error == -1) {
      if (errno == E2BIG) {
        // message buffer was too small, enlarge it
        free(msgbuf);
        msgbuf = (void *)malloc(rlen);
        if (msgbuf == NULL) {
          fprintf(stderr,"Can't resize msg buffer\n");
          goto out;
        }
        continue;
      }
      // we got an error while getting events, or simply there were no events
      // for the moment continue, but should improve error handling here
      continue;
    }

    // examine each message and dispatch children to manage events and respond to client
    msg = (dm_eventmsg_t *)msgbuf;
    while (msg != NULL ) {
      if (Verbose) {
        fprintf(stderr, "Received %s, sid %llx token %llx %llx\n", (msg->ev_type == DM_EVENT_READ ? "READ" : 
                                                         (msg->ev_type == DM_EVENT_WRITE ? "WRITE" : (msg->ev_type == DM_EVENT_TRUNCATE ? "TRUNCATE" : "MOUNT"))), 
                                                         sid, msg->ev_token.high, msg->ev_token.low);
      }

      // get file handle 
      msgev  = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
      hanp = DM_GET_VALUE(msgev, de_handle, void *);
      hlen = DM_GET_LEN(msgev, de_handle);
     
      switch (msg->ev_type) {
         case DM_EVENT_MOUNT:
           spawn_child(msg->ev_token, hanp, hlen, "MOUNT");
           break;
         case DM_EVENT_READ:
           spawn_child(msg->ev_token, hanp, hlen, "READ");
           break;
         case DM_EVENT_WRITE:
           spawn_child(msg->ev_token, hanp, hlen, "WRITE");
           break;
         case DM_EVENT_TRUNCATE:
           spawn_child(msg->ev_token, hanp, hlen, "TRUNC");
           break;
         default:
           fprintf(stderr,"Invalid msg type %d\n", msg->ev_type);
           break;
      }
      // go to next event
      msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
    }
  }

out:
  if (msgbuf != NULL) free(msgbuf);
  exit_program(0);
}