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) {
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); }
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 {
/* * 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; }
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); }
/* * 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); }