/* *clears bit in bitmap */ void libuss_clear_multi_table_index(int x) { int ret; ret = pthread_mutex_lock(&multiplexer_mtx); if(ret != 0) dexit("thread_mutex_lock"); local_thread_bitmap[x] = 0; ret = pthread_mutex_unlock(&multiplexer_mtx); if(ret != 0) dexit("thread_mutex_unlock"); }
/* * return the actual value of run_on */ int update_run_on(int *run_on, int *device_id, int sfd) { #if(USS_FIFO == 1) struct uss_message m; ssize_t nof_br = fifo_blocking_read(&m, sfd); if(nof_br == sizeof(struct uss_message) /*&& errno != EAGAIN*/) { *run_on = m.accelerator_type; *device_id = m.accelerator_index; } else if(nof_br == (ssize_t)-1 && errno == EAGAIN) { //everything ok made empty nonblocking read //printf("EAGAIN nof_br=%i \n", (int)nof_br); } else if(nof_br == (ssize_t)0) { //EOF read dexit("update_run_on: daemon has crashed!"); } else { //printf("so(mess)=%i nof_br=%i \n",(int)sizeof(struct uss_message), (int)nof_br); dexit("update_run_on: read too small"); } #elif(USS_RTSIG == 1) struct signalfd_siginfo fdsi; ssize_t nof_br = rtsig_blocking_read(sfd, &fdsi); if(nof_br == sizeof(struct signalfd_siginfo)) { struct uss_address a; memset(&a, 0, sizeof(struct uss_address)); struct uss_message m; convert_int_to_uss(fdsi.ssi_int, &a, &m); *run_on = m.accelerator_type; *device_id = m.accelerator_index; } else if(nof_br != sizeof(struct signalfd_siginfo) && errno == EAGAIN) { //everything ok made empty nonblocking read } else { dexit("update_run_on: read too small"); } #endif return *run_on; }
/***************************************\ * message wrapper function * \***************************************/ void convert_uss_to_int(struct uss_address *a, struct uss_message *m, int *i) { int wrapped_int = 0; if(m->message_type >= (int)(1<<USS_WRAPPED_INT_RTSIG_MESSAGE_TYPE_LEN)) dexit("send_rtsig: message_type oob"); if(m->accelerator_type >= (int)(1<<USS_WRAPPED_INT_RTSIG_ACCEL_TYPE_LEN)) dexit("send_rtsig: message_type oob"); if(m->accelerator_index >= (int)(1<<USS_WRAPPED_INT_RTSIG_ACCEL_INDEX_LEN)) dexit("send_rtsig: message_type oob"); if(a->lid >= (int)(1<<USS_WRAPPED_INT_RTSIG_LOCAL_ADDRESS_LEN)) dexit("send_rtsig: message_type oob"); wrapped_int |= (m->message_type<<USS_WRAPPED_INT_RTSIG_MESSAGE_TYPE_POS); wrapped_int |= (m->accelerator_type<<USS_WRAPPED_INT_RTSIG_ACCEL_TYPE_POS); wrapped_int |= (m->accelerator_index<<USS_WRAPPED_INT_RTSIG_ACCEL_INDEX_POS); wrapped_int |= (a->lid<<USS_WRAPPED_INT_RTSIG_LOCAL_ADDRESS_POS); *i = wrapped_int; }
/* * returns 0 on succes, -1 on error */ int libuss_send_to_daemon(struct uss_address *source_address, struct uss_address *receiver_address, struct uss_message *message, int daemon_fd) { int ret; #if(USS_FILE_LOGGING == 1) struct timeval tv; gettimeofday(&tv, NULL); int fd = open("./benchmark/usslog", O_WRONLY | O_APPEND); if(fd == -1) {dexit("dlog");} char buf[100] = {0x0}; sprintf(buf, "%ld %ld : sending message cleanup (%i) to of accelerator_type %i\n", (long)tv.tv_sec, (long)tv.tv_usec, message->message_type, message->accelerator_type); write(fd, buf, strlen(buf)); close(fd); #endif #if(USS_FIFO == 1) ret = fifo_send(message, daemon_fd); #elif(USS_RTSIG == 1) //wraps source address (because daemon needs a threads LID) and message into a single int value int wrapped_int = 0; convert_uss_to_int(source_address, message, &wrapped_int); //send to receiver addres (because we send to daemon no receiver LID is needed) ret = rtsig_send(0, receiver_address->pid, wrapped_int); #endif return ret; }
rt_public void wide_listen(void) { /* Listen on all the file descriptors opened for reading until the * connected socket is broken. */ /* Make sure we listen on the connected socket and call the handling * routine whenever data is available there. */ #ifdef EIF_WINDOWS if (-1 == add_input(app_sp, (STREAM_FN) arqsthandle)) { #else if (-1 == add_input(app_sp, arqsthandle)) { #endif #ifdef USE_ADD_LOG add_log(4, "add_input: %s (%s)", s_strerror(), s_strname()); #endif dexit(1); } #ifdef USE_ADD_LOG add_log(12, "in listen"); #endif /* After having selected, we scan all our files to make sure none of them * has been removed from the selection process. If at least one is missing, * we are exiting immediately. */ #ifdef EIF_WINDOWS while (0 <= do_select(0)) { #ifdef USE_ADD_LOG add_log(12, "in while do_select"); #endif if (!has_input(app_sp)) { /* Socket connection broken? */ #ifdef USE_ADD_LOG add_log(12, "in !has_input which is what we want"); #endif return; /* Anyway, abort processing */ } } #ifdef USE_ADD_LOG add_log(12, "out of listen"); #endif #else while (0 < do_select((struct timeval *) 0)) { if (!has_input(app_sp)) /* Socket connection broken? */ return; /* Anyway, abort processing */ } #endif #ifdef USE_ADD_LOG add_log(12, "do_select: %s (%s)", s_strerror(), s_strname()); #endif }
char * volmgt_getfullrawname(char *n) { extern char *getfullrawname(char *); char *rval; char namebuf[MAXPATHLEN+1]; char *s; char c; char *res; #ifdef DEBUG denter("volmgt_getfullrawname(%s): entering\n", n); #endif /* try to get full char-spcl device name */ rval = getfullrawname(n); if ((rval != NULL) && (*rval != NULLC)) { /* found it */ res = rval; goto dun; } /* we have a null-string result */ if (rval != NULL) { /* free null string */ free(rval); } /* ok, so we either have a bad device or a floppy */ /* try the "fd", "diskette", and the "dsk" form */ if (((s = strstr(n, "/fd")) != NULL) || ((s = strstr(n, "/diskette")) != NULL) || ((s = strstr(n, "/dsk/")) != NULL)) { /* * ensure we have room to add one more char */ if (strlen(n) < (MAXPATHLEN - 1)) { c = *++s; /* save the first char */ *s = NULLC; /* replace it with a null */ (void) strcpy(namebuf, n); /* save first part of str */ *s = c; /* put first charback */ (void) strcat(namebuf, "r"); /* insert an 'r' */ (void) strcat(namebuf, s); /* copy rest of str */ res = strdup(namebuf); goto dun; } } /* no match found */ res = strdup(""); dun: #ifdef DEBUG dexit("volmgt_getfullrawname: returning %s\n", res ? res : "<null ptr>"); #endif return (res); }
/* *returns a free lid or negative if no more avail *depends on USS_MAX_LOCAL_THREADS */ int libuss_get_new_multi_table_index() { int ret, i; int final_ret = -1; ret = pthread_mutex_lock(&multiplexer_mtx); if(ret != 0) dexit("thread_mutex_lock"); for(i = 0; i < USS_MAX_LOCAL_THREADS; i++) { if(local_thread_bitmap[i] == 0) { local_thread_bitmap[i] = 1; final_ret = i; break; } } ret = pthread_mutex_unlock(&multiplexer_mtx); if(ret != 0) dexit("thread_mutex_unlock"); return final_ret; }
/* * this requires the communication method to use file descriptors * that can be made blocking or nonblocking via fcntl */ int waitfor_run_on(int *run_on, int *device_id, int sfd) { int flags, ret, final_ret; //delete flag: O_NONBLOCK flags = fcntl(sfd, F_GETFL); if(flags == -1) {dexit("waitfor_run_on had problem with fcntl");} flags &= (~O_NONBLOCK); ret = fcntl(sfd, F_SETFL, flags); if(ret == -1) {dexit("waitfor_run_on had problem with fcntl");} //now do blocking read on modified sfd final_ret = update_run_on(run_on, device_id, sfd); //reset flag: O_NONBLOCK flags = fcntl(sfd, F_GETFL); if(flags == -1) {dexit("waitfor_run_on had problem with fcntl");} flags |= O_NONBLOCK; ret = fcntl(sfd, F_SETFL, flags); if(ret == -1) {dexit("waitfor_run_on had problem with fcntl");} return final_ret; }
/* * translate suplied vol name into a pathname * * if volmgt is running, this pathname will be in /vol (or its equiv) * * if volmgt is not running then this path may be anywhere * * in either case the pathname will *not* be verified as a blk/chr dev * * if the return value is non-null then it's been alloced * * NOTE: assume "vol" is not a NULL ptr */ static char * fsi_xlate_name(char *vol) { char *res = NULL; /* result to return */ char *vr; /* volmgt root dir */ bool_t vm_running = volmgt_running(); /* volmgt running? */ #ifdef DEBUG denter("fsi_xlate_name(\"%s\"): entering\n", vol); #endif /* is it an absolute pathname ?? */ if (*vol == '/') { if (vm_running) { /* pathname must be in the /vol namespace */ vr = (char *)volmgt_root(); if (strncmp(vol, vr, strlen(vr)) != 0) { /* not a cool pathname */ errno = EINVAL; /* XXX: is this correct */ goto dun; } } res = strdup(vol); } else { /* * if volmgt is running we can try to dereference it * if volmgt isn't running then just give up */ if (!vm_running) { /* some unknown "name" */ errno = ENOENT; goto dun; } res = volmgt_symdev(vol); } dun: #ifdef DEBUG dexit("fsi_xlate_name: returning %s\n", res ? res : "<null ptr>"); #endif return (res); }
/***************************************\ * multiplexer start * \***************************************/ int libuss_start_multiplexer() { // //try to create a multiplexer socket // int ret; ret = pthread_mutex_lock(&multiplexer_mtx); if(ret != 0) dexit("thread_mutex_lock"); if(multiplexer_started == 0) { int ret, fd_multiplexer; struct sockaddr_un server_addr; //create a socket ret = remove(USS_REGISTRATION_MULTIPLEXER_SOCKET); if(ret == -1 && errno != ENOENT) {dexit("problem when trying to remove old socket");} fd_multiplexer = socket(AF_UNIX, SOCK_STREAM, 0); if(fd_multiplexer==-1) {dexit("dderror: creating socket\n");} memset(&server_addr, 0, sizeof(struct sockaddr_un)); server_addr.sun_family = AF_UNIX; strncpy(server_addr.sun_path, USS_REGISTRATION_MULTIPLEXER_SOCKET, sizeof(server_addr.sun_path)-1); ret = bind(fd_multiplexer, (struct sockaddr*) &server_addr, sizeof(struct sockaddr_un)); if(fd_multiplexer==-1) {dexit("dderror: binding socket failed\n");} ret = listen(fd_multiplexer, 128); if(fd_multiplexer==-1) {dexit("dderror: listen on socket failed\n");} pthread_create(®istration_multiplexer_thread, NULL, libuss_registration_multiplexer_thread, &fd_multiplexer); struct sigaction sa; sa.sa_flags = SA_SIGINFO | SA_RESTART; sa.sa_sigaction = incoming_sig_handler; sigemptyset(&sa.sa_mask); ret = sigaction((SIGRTMIN+0), &sa, NULL); if(ret == -1) {printf("dderror: signal int not established\n"); exit(1);} multiplexer_started = 1; } ret = pthread_mutex_unlock(&multiplexer_mtx); if(ret != 0) dexit("thread_mutex_unlock"); return 0; }
/* * arc approved interface (pending) * - can not be modified without approval from an arc * * committment level: * public * * description: * media_findname: try to come up with the character device when * provided with a starting point. This interface provides the * application programmer to provide "user friendly" names and * easily determine the "/vol" name. * * arguments: * start - a string describing a device. This string can be: * - a full path name to a device (insures it's a * character device by using getfullrawname()). * - a full path name to a volume management media name * with partitions (will return the lowest numbered * raw partition. * - the name of a piece of media (e.g. "fred"). * - a symbolic device name (e.g. floppy0, cdrom0, etc) * - a name like "floppy" or "cdrom". Will pick the lowest * numbered device with media in it. * * return value(s): * A pointer to a string that contains the character device * most appropriate to the "start" argument. * * NULL indicates that we were unable to find media based on "start". * * The string must be free(3)'d. * * preconditions: * none. */ char * media_findname(char *start) { static char *media_findname_work(char *); char *s = NULL; /* * This is just a wrapper to implement the volmgt_check nastyness. */ #ifdef DEBUG denter("media_findname(%s): entering\n", start ? start : "<null ptr>"); #endif if (start == NULL) { errno = EFAULT; goto dun; } /* * If we don't get positive results, we kick volume management * to ask it to look in the floppy drive. * * XXX: maybe this should be configurable ??? */ if ((s = media_findname_work(start)) == NULL) { #ifdef DEBUG dprintf("media_findname: calling volcheck and trying again\n"); #endif (void) volmgt_check(NULL); s = media_findname_work(start); } dun: #ifdef DEBUG dexit("media_findname: returning \"%s\"\n", s ? s : "<null ptr>"); #endif return (s); }
/* * Return a raw name, given a starting point. * * Assume: input string ptr is not null */ static char * media_findname_work(char *start) { extern char *vol_basename(char *); static void volmgt_deref_link(char *, char *, char *); char pathbuf[MAXPATHLEN+1]; char *rv; char *s; char linkbuf[MAXNAMELEN+1]; char *nameptr; struct stat64 sb; int n; int i; static const char *vold_root = NULL; static char vold_alias_dir[MAXPATHLEN+1]; char *res = NULL; DIR *dirp = NULL; struct dirent64 *dp; #ifdef DEBUG denter("media_findname_work(%s): entering\n", start); #endif if (vold_root == NULL) { vold_root = volmgt_root(); (void) concat_paths(vold_alias_dir, (char *)vold_root, (char *)ALIAS_DIR, NULL); } /* * if this is an absolute path name then * if it's a symlink deref it * if it's a raw device then we're done * else if it's a directory then look for a dev under it */ if (IS_ABS_PATH(start)) { /* try to get data on name passed in */ if (lstat64(start, &sb) < 0) { #ifdef DEBUG dprintf( "media_findname_work: lstat of \"%s\" (errno %d)\n", start, errno); #endif goto dun; /* error exit */ } /* * if is this a link to something else (e.g. ".../floppy0") * and it's in the volmgt namespace, then deref it */ if (S_ISLNK(sb.st_mode) && (strncmp(start, vold_alias_dir, strlen(vold_alias_dir)) == 0)) { /* it's a symlink */ if ((n = readlink(start, linkbuf, MAXNAMELEN)) <= 0) { /* we can't read the link */ #ifdef DEBUG dprintf( "media_findname_work: readlink(\"%s\") failed (errno %d)\n", start, errno); #endif goto dun; /* error exit */ } linkbuf[n] = NULLC; /* dereference the link */ volmgt_deref_link(pathbuf, start, linkbuf); /* stat where "start" pointed at */ if (stat64(pathbuf, &sb) < 0) { #ifdef DEBUG dprintf( "media_findname_work: stat failed on \"%s\" (errno %d)\n", pathbuf, errno); #endif goto dun; /* error exit */ } nameptr = pathbuf; } else { nameptr = start; } /* do we already have a char-spcl device ?? */ if (S_ISCHR(sb.st_mode)) { /* * absoluate pathname of a char-spcl device passed in */ res = strdup(nameptr); goto dun; /* success */ } /* not a char-spcl device -- is it a dir ?? */ if (S_ISDIR(sb.st_mode)) { /* open the dir and find first char-spcl device */ if ((s = getrawpart0(nameptr)) != NULL) { /* * absoluate pathname to a directory passed * in, under which there is at least one * char-spcl device */ free(s); res = strdup(nameptr); goto dun; /* success */ } } /* * try to get the char-spcl name if this is a blk-spcl * * XXX: shouldn't we ensure this is a blk spcl device? */ rv = volmgt_getfullrawname(nameptr); if ((rv == NULL) || (*rv == NULLC)) { goto dun; /* error exit */ } /* stat the fullrawname device (to see if it's char-spcl) */ if (stat64(rv, &sb) < 0) { #ifdef DEBUG dprintf( "media_findname_work: stat of \"%s\" (errno %d)\n", rv, errno); #endif goto dun; /* error exit */ } /* have we found the char-spcl device ?? */ if (S_ISCHR(sb.st_mode)) { /* * absolute pathname to block device supplied and * converted to an absoluate pathname to a char device */ res = rv; /* already malloc'ed */ goto dun; /* success */ } /* * fullrawname not a char-spcl device -- is it a dir ?? * * XXX: didn't we already check for a directory name * being supplied above? */ if (S_ISDIR(sb.st_mode)) { /* open dir and find first char-spcl device */ if ((s = getrawpart0(rv)) != NULL) { /* * the absolute pathname of directory * containing at least one char-spcl device * was passed in */ free(s); res = strdup(rv); goto dun; /* success */ } } /* having a full pathname didn't help us */ goto dun; /* failure -- pathname not found */ } /* * Ok, now we check to see if it's an alias. * Note here that in the case of an alias, we prefer * to return what the alias (symbolic link) points * at, rather than the symbolic link. Makes for * nicer printouts and such. */ (void) concat_paths(pathbuf, vold_alias_dir, start, NULL); #ifdef DEBUG dprintf("media_findname_work: looking for \"%s\"\n", pathbuf); #endif if (stat64(pathbuf, &sb) == 0) { #ifdef DEBUG dprintf("media_findname_work: is \"%s\" a chr-spcl dev?\n", pathbuf); #endif /* is this a char-spcl device ?? */ if (S_ISCHR(sb.st_mode)) { /* it's probably a link, so ... */ if ((n = readlink(pathbuf, linkbuf, MAXNAMELEN)) <= 0) { /* * error (since we are in the symlink * directory) not a link, but just punt * anyway */ res = strdup(pathbuf); } else { /* it was a link */ linkbuf[n] = NULLC; res = strdup(linkbuf); } goto dun; /* success */ } #ifdef DEBUG dprintf("media_findname_work: not chr-spcl -- is it a dir?\n"); #endif /* not a char-spcl device -- is it a dir ?? */ if (S_ISDIR(sb.st_mode)) { /* it's probably a link, so ... */ if ((n = readlink(pathbuf, linkbuf, MAXNAMELEN)) <= 0) { /* * error, but just punt anyway */ nameptr = pathbuf; s = getrawpart0(pathbuf); } else { /* it was a link */ linkbuf[n] = NULLC; /* open dir, finding first char-spcl dev */ nameptr = linkbuf; s = getrawpart0(linkbuf); } if (s != NULL) { free(s); res = strdup(nameptr); goto dun; } } } /* * check all aliases in the alias dir, to see if any match */ if ((dirp = opendir(vold_alias_dir)) == NULL) { goto try_hack; } while (dp = readdir64(dirp)) { /* skip uninteresting entries */ if (strcmp(dp->d_name, ".") == 0) { continue; } if (strcmp(dp->d_name, "..") == 0) { continue; } #ifdef DEBUG dprintf("media_findname_work: scanning alias \"%s\" ...\n", dp->d_name); #endif /* * open the link and see if it points at our entry */ (void) concat_paths(pathbuf, vold_alias_dir, dp->d_name, NULL); if ((n = readlink(pathbuf, linkbuf, MAXNAMELEN)) <= 0) { #ifdef DEBUG dprintf( "media_findname_work: readlink(\"%s\") failed (errno %d)\n", pathbuf, errno); #endif continue; } linkbuf[n] = NULLC; #ifdef DEBUG dprintf("media_findname_work: scanning link \"%s\" ...\n", linkbuf); #endif if (strcmp(vol_basename(linkbuf), start) == 0) { /* we *think* we've found a match */ if (stat64(linkbuf, &sb) == 0) { if (S_ISCHR(sb.st_mode)) { res = strdup(linkbuf); goto dun; } if (S_ISDIR(sb.st_mode)) { res = getrawpart0(linkbuf); if (res != NULL) { free(res); res = strdup(linkbuf); } goto dun; } } } } try_hack: /* * Ok, well maybe that's not it. Let's try the * hackname alias. */ /* * This creates the "hack" name. The model * is that xx# has the alias xx. So, cdrom# * and floppy# (the most frequent case) can * be referred to as cdrom and floppy. * We poke at what we consider to be a reasonable number of * devices (currently 5) before giving up. */ for (i = 0; i < HACKNAME_MAX; i++) { char num_buf[NUMBUF_SZ]; (void) sprintf(num_buf, "%d", i); (void) concat_paths(pathbuf, vold_alias_dir, start, num_buf); if (stat64(pathbuf, &sb) == 0) { /* is it a char-spcl device ?? */ if (S_ISCHR(sb.st_mode)) { /* it's probably a link, so... */ if ((n = readlink(pathbuf, linkbuf, MAXNAMELEN)) <= 0) { /* it wasn't a link */ res = strdup(pathbuf); } else { /* it was a link */ linkbuf[n] = NULLC; res = strdup(linkbuf); } goto dun; } /* not a char-spcl device -- is it a dir ?? */ if (S_ISDIR(sb.st_mode)) { /* it's probably a link, so ... */ if ((n = readlink(pathbuf, linkbuf, MAXNAMELEN)) <= 0) { /* get fist char-spcl dev in dir */ nameptr = pathbuf; s = getrawpart0(pathbuf); } else { /* it was a link */ linkbuf[n] = NULLC; /* get fist char-spcl dev in dir */ nameptr = linkbuf; s = getrawpart0(linkbuf); } if (s != NULL) { free(s); res = strdup(nameptr); goto dun; } } } } #ifdef DEBUG dprintf("media_findname_work: %s didn't match any test!\n", start); #endif dun: if (dirp != NULL) { (void) closedir(dirp); } #ifdef DEBUG dexit("media_findname_work: returning \"%s\"\n", res ? res : "<null ptr>"); #endif return (res); }
/* *this thread hijacks outgoing registration attempts *and slices in a local ID *it is also a thread that can receive SIGRTMIN+0 */ void* libuss_registration_multiplexer_thread(void *args) { pthread_detach(pthread_self()); int ret; int *fd_multiplexer_ptr = (int*)args; int fd_multiplexer = *fd_multiplexer_ptr; int fd_localthread, fd_daemon; //SIGRTMIN+0 has to be unlocked sigset_t unimmune_set; sigemptyset(&unimmune_set); sigaddset(&unimmune_set, (SIGRTMIN+0)); pthread_sigmask(SIG_UNBLOCK, &unimmune_set, NULL); // //loop for each new accepted connection (create no new thread for each => many regs may be delayed) // while(1) { // //wait for reg attempt from a local thread that uses multiplexer // fd_localthread = accept(fd_multiplexer, NULL, NULL); if(fd_localthread==-1) {printf("dderror: accept failed\n"); exit(1);} // //now new connection to daemon // struct sockaddr_un client_addr; fd_daemon = socket(AF_UNIX, SOCK_STREAM, 0); if(fd_daemon == -1) {dexit("error creating socket -> quit");} memset(&client_addr, 0, sizeof(struct sockaddr_un)); client_addr.sun_family = AF_UNIX; strncpy(client_addr.sun_path, USS_REGISTRATION_DAEMON_SOCKET, sizeof(client_addr.sun_path)-1); ret = connect(fd_daemon, (struct sockaddr*) &client_addr, sizeof(struct sockaddr_un)); if(ret == -1) { printf("error connecting socket\n"); close(fd_localthread); dexit("multiplexer could not connect to daemon -> quit"); } else { // //read meta_sched_addr_info from local thread // struct meta_sched_addr_info transport; memset(&transport, 0, sizeof(struct meta_sched_addr_info)); int nof_br = read(fd_localthread, &transport, sizeof(struct meta_sched_addr_info)); //if we received too small msai return error value if(nof_br != sizeof(struct meta_sched_addr_info)) { dexit("received too small msai"); } // //create multi_table entry // int index = libuss_get_new_multi_table_index(); if(index < 0) { close(fd_localthread); close(fd_daemon); dexit("too many threads per process"); } else { multi_table[index].local_thread = transport.tid; // //write modified meta_sched_addr_info to daemon // transport.addr.lid = index; write(fd_daemon, &transport, sizeof(struct meta_sched_addr_info)); // //read uss_response from daemon // struct uss_registration_response resp; read(fd_daemon, &resp, sizeof(uss_registration_response)); // //write modfied uss_response back to local thread // resp.client_addr.pid = getpid(); resp.client_addr.lid = index; write(fd_localthread, &resp, sizeof(struct uss_registration_response)); #if(USS_DEBUG == 1) printf("SCHED RESP CHECK: %i\n", resp.check); #endif // //depending on sched response, keep or clear saved state for this local thread // if(resp.check == USS_CONTROL_SCHED_ACCEPTED) { } else if(resp.check == USS_CONTROL_SCHED_DECLINED) { libuss_clear_multi_table_index(index); } else { //sth odd happend dexit("wrong scheduler response"); } } //close own connection with daemon close(fd_daemon); } }//end while return NULL; }
void _start() { main(); dexit(); }
/* * libuss_start * * provides main algorithm * * (dont use function pointer binding here, because it would * require a rebind each time an accelerator is chosen * -> maybe solve by inline calculation?) */ int libuss_start(struct meta_sched_info *msi, void *md, void *mcp, int *is_finished, int *run_on, int *device_id) { // //local variables // int ret; /* *run_on variable is provided from outside what allows other threads to check this ones status */ *run_on = USS_ACCEL_TYPE_IDLE; *device_id = 0; // //benchmark variables // #if(BENCHMARK_REGISTRATION_TIME == 1) struct timespec ts; #endif #if(BENCHMARK_CONTEXTSWITCH_TIME == 1) struct timespec cst; uint64_t cst_init_ns = 0; uint64_t cst_clean_ns = 0; char buf[100] = {0x0}; int bench_fd; #endif // //register at uss (fails if no daemon is started) // struct uss_address my_addr, daemon_addr; memset(&my_addr, 0, sizeof(struct uss_address)); memset(&daemon_addr, 0, sizeof(struct uss_address)); int my_fd; int daemon_fd; #if(BENCHMARK_REGISTRATION_TIME == 1) if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {dexit("clock_gettime() failed");} uint64_t regtime_start_ns = ts.tv_sec*(1000000000) + ts.tv_nsec; #endif ret = libuss_register_at_daemon(msi, &my_addr, &daemon_addr, &my_fd, &daemon_fd); #if(BENCHMARK_REGISTRATION_TIME == 1) if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {dexit("clock_gettime() failed");} uint64_t regtime_stop_ns = ts.tv_sec*(1000000000) + ts.tv_nsec; printf("%llu\n", (unsigned long long int)(regtime_stop_ns - regtime_start_ns)); #endif if(ret == -1) {printf("registering at daemon unsuccessful -> quit\n"); return USS_ERROR_GENERAL;} if(ret == USS_ERROR_SCHED_DECLINED_REG) {printf("scheduler declined registration\n"); return USS_ERROR_SCHED_DECLINED_REG;} if(ret == USS_ERROR_TRANSPORT) {printf("transport error occured\n"); return USS_ERROR_TRANSPORT;} struct meta_sched_info_element *selected; struct uss_message curr_message; int current_device_id; int do_main_atleast_once = 0; // //main functionality // //update once update_run_on(run_on, device_id, my_fd); //loop while (!(*is_finished)) { switch(*run_on) { case USS_ACCEL_TYPE_CUDA: #if(USS_LIBRARY_DEBUG == 1) printf("case: run CUDA\n"); #endif current_device_id = *device_id; do_main_atleast_once = 0; selected = msi->ptr[USS_ACCEL_TYPE_CUDA]; #if(BENCHMARK_CONTEXTSWITCH_TIME == 1) if(clock_gettime(CLOCK_MONOTONIC, &cst) != 0) {dexit("clock_gettime() failed");} cst_init_ns = cst.tv_sec*(1000000000) + cst.tv_nsec; bench_fd = open("./benchmark/cstlog", O_WRONLY | O_APPEND); if(bench_fd == -1) {dexit("bench_cst");} memset(buf, 0, (size_t)100); sprintf(buf, "i %lld\n", (long long int)(cst_init_ns)); //=time (ns) when this writer is before init write(bench_fd, buf, strlen(buf)); memset(buf, 0, (size_t)100); sprintf(buf, "c %lld\n", (long long int)(cst_clean_ns)); //=time (ns) when this writer did a cleanup write(bench_fd, buf, strlen(buf)); close(bench_fd); #endif selected->init(md, mcp, current_device_id); while(((USS_ACCEL_TYPE_CUDA == *run_on && current_device_id == *device_id) || do_main_atleast_once == 0) && !(*is_finished)) { selected->main(md, mcp, current_device_id); update_run_on(run_on, device_id, my_fd); do_main_atleast_once = 1; } selected->free(md, mcp, current_device_id); #if(BENCHMARK_CONTEXTSWITCH_TIME == 1) if(clock_gettime(CLOCK_MONOTONIC, &cst) != 0) {dexit("clock_gettime() failed");} cst_clean_ns = cst.tv_sec*(1000000000) + cst.tv_nsec; #endif if((*is_finished)) { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_ISFINISHED; curr_message.accelerator_type = USS_ACCEL_TYPE_CUDA; curr_message.accelerator_index = current_device_id; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } else { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_CLEANUP_DONE; curr_message.accelerator_type = USS_ACCEL_TYPE_CUDA; curr_message.accelerator_index = current_device_id; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } break; case USS_ACCEL_TYPE_FPGA: #if(USS_LIBRARY_DEBUG == 1) printf("case: run FPGA\n"); #endif current_device_id = *device_id; do_main_atleast_once = 0; selected = msi->ptr[USS_ACCEL_TYPE_FPGA]; selected->init(md, mcp, current_device_id); while(((USS_ACCEL_TYPE_FPGA == *run_on && current_device_id == *device_id) || do_main_atleast_once == 0) && !(*is_finished)) { selected->main(md, mcp, current_device_id); update_run_on(run_on, device_id, my_fd); do_main_atleast_once = 1; } selected->free(md, mcp, current_device_id); if((*is_finished)) { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_ISFINISHED; curr_message.accelerator_type = USS_ACCEL_TYPE_FPGA; curr_message.accelerator_index = current_device_id; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } else { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_CLEANUP_DONE; curr_message.accelerator_type = USS_ACCEL_TYPE_FPGA; curr_message.accelerator_index = current_device_id; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } break; case USS_ACCEL_TYPE_STREAM: #if(USS_LIBRARY_DEBUG == 1) printf("case: run FPGA\n"); #endif current_device_id = *device_id; do_main_atleast_once = 0; selected = msi->ptr[USS_ACCEL_TYPE_STREAM]; selected->init(md, mcp, current_device_id); while(((USS_ACCEL_TYPE_STREAM == *run_on && current_device_id == *device_id) || do_main_atleast_once == 0) && !(*is_finished)) { selected->main(md, mcp, current_device_id); update_run_on(run_on, device_id, my_fd); do_main_atleast_once = 1; } selected->free(md, mcp, current_device_id); if((*is_finished)) { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_ISFINISHED; curr_message.accelerator_type = USS_ACCEL_TYPE_STREAM; curr_message.accelerator_index = current_device_id; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } else { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_CLEANUP_DONE; curr_message.accelerator_type = USS_ACCEL_TYPE_STREAM; curr_message.accelerator_index = current_device_id; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } break; case USS_ACCEL_TYPE_CPU: #if(USS_LIBRARY_DEBUG == 1) printf("case: run CPU\n"); #endif selected = msi->ptr[USS_ACCEL_TYPE_CPU]; selected->init(md, mcp, 0); while(USS_ACCEL_TYPE_CPU == *run_on && !(*is_finished)) { selected->main(md, mcp, 0); update_run_on(run_on, device_id, my_fd); /*CPU has no do_main_atleaat_once because its init/cleanup cost are low*/ } selected->free(md, mcp, 0); if((*is_finished)) { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_ISFINISHED; curr_message.accelerator_type = USS_ACCEL_TYPE_CPU; curr_message.accelerator_index = 0; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } else { #if(USS_FIFO == 1) curr_message.address = my_addr; #endif curr_message.message_type = USS_MESSAGE_CLEANUP_DONE; curr_message.accelerator_type = USS_ACCEL_TYPE_CPU; curr_message.accelerator_index = 0; ret = libuss_send_to_daemon(&my_addr, &daemon_addr, &curr_message, daemon_fd); if(ret != 0) {dexit("library could not send message!!");} } break; case USS_ACCEL_TYPE_IDLE: /*fallthrough to default */ default: #if(USS_LIBRARY_DEBUG == 1) printf("case: IDLE\n"); #endif //this app thread has been 'idled' by daemon -> cant do anything until a message from daemon waitfor_run_on(run_on, device_id, my_fd); break; }//end switch }//end main while // //cleanup by closing the file descriptors // close(my_fd); close(daemon_fd); return ret; }
/* * libuss_register_at_daemon * */ int libuss_register_at_daemon(struct meta_sched_info *msi, struct uss_address *my_addr, struct uss_address *daemon_addr, int *my_fd, int *daemon_fd) { // //validity check // if(!msi) {printf("error: msi is NULL pointer -> quit"); return -1;} // //local variables // int ret; int fd; ssize_t size_ret; struct sockaddr_un target_addr; // //create a socket // fd = socket(AF_UNIX, SOCK_STREAM, 0); if(fd == -1) {printf("error creating socket -> quit"); return -1;} // //make this thread listen on virtual line // *my_fd = libuss_install_receiver(my_addr); if(*my_fd == -1) { printf("(problem with receiver installation)\n"); return USS_ERROR_GENERAL; } #if(USS_RTSIG == 1) libuss_start_multiplexer(); //will start only if not active yet #endif // //connect to daemon // memset(&target_addr, 0, sizeof(struct sockaddr_un)); target_addr.sun_family = AF_UNIX; #if(USS_FIFO == 1) strncpy(target_addr.sun_path, USS_REGISTRATION_DAEMON_SOCKET, sizeof(target_addr.sun_path)-1); #elif(USS_RTSIG == 1) strncpy(target_addr.sun_path, USS_REGISTRATION_MULTIPLEXER_SOCKET, sizeof(target_addr.sun_path)-1); #endif ret = connect(fd, (struct sockaddr*) &target_addr, sizeof(struct sockaddr_un)); if(ret == -1) {printf("libuss_register error connecting socket -> return \n"); return -1;} // //parse msi into meta_sched_addr_info // int i; struct meta_sched_addr_info transport; struct meta_sched_info_element *temp = NULL; memset(&transport, 0, sizeof(struct meta_sched_addr_info)); transport.addr = *my_addr; transport.tid = pthread_self(); transport.length = 0; for(i = 0; i < USS_NOF_SUPPORTED_ACCEL; i++) { temp = msi->ptr[i]; if(!temp) { //user doesn't want to use this accel continue; } else { if(transport.length >= USS_MAX_MSI_TRANSPORT) { printf("warning: user specified more accelerators than allowed by USS_MAX_MSI_TRANSPORT\n"); } else { transport.accelerator_type[transport.length] = i; transport.affinity[transport.length] = temp->affinity; transport.flags[transport.length] = temp->flags; transport.length += 1; } } } //abort if user hasn't set any elements in his msi if(transport.length == 0) {printf("error: user has specified empty msi -> quit\n"); return -1;} // //sort msai using bubble sort // int exchanged; int n = transport.length; do { exchanged = 0; for(i = 0; i < (n-1); i++) { if(transport.affinity[i] < transport.affinity[i+1]) { int temp_acc = transport.accelerator_type[i+1]; int temp_aff = transport.affinity[i+1]; int temp_fla = transport.flags[i+1]; transport.accelerator_type[i+1] = transport.accelerator_type[i]; transport.affinity[i+1] = transport.affinity[i]; transport.flags[i+1] = transport.flags[i]; transport.accelerator_type[i] = temp_acc; transport.affinity[i] = temp_aff; transport.flags[i] = temp_fla; exchanged = 1; } } n--; } while(exchanged == 1 && n > 0); #if(USS_LIBRARY_DEBUG == 1) //printf("\nREGISTRATION\n"); //print_msi_short(&transport); #endif // //send meta_sched_addr_info to server // size_ret = write(fd, &transport, sizeof(struct meta_sched_addr_info)); if(size_ret != sizeof(struct meta_sched_addr_info)) {dexit("libuss_register: write too small");} // //read response and analyze for success // struct uss_registration_response resp; ssize_t size_got = 0; while(size_got < (ssize_t)sizeof(struct uss_registration_response)) { size_ret = read(fd, ((&resp)+size_got), ((ssize_t)sizeof(struct uss_registration_response) - size_got)); if(size_ret == -1) {dexit("libuss_register: general error with read call");} size_got += size_ret; } if(size_ret != sizeof(struct uss_registration_response)) {dexit("libuss_register: read too small or unequal");} int check = resp.check; *daemon_addr = resp.daemon_addr; *my_addr = resp.client_addr; if(check == USS_CONTROL_SCHED_ACCEPTED) { #if(USS_FIFO == 1) #if(USS_LIBRARY_DEBUG == 1) printf("my_addr->fifo=%ld\n", my_addr->fifo); #endif *daemon_fd = libuss_install_sender(daemon_addr); if(*daemon_fd == -1) { printf("(problem with sender installation)\n"); close(fd); return USS_ERROR_GENERAL; } #elif(USS_RTSIG == 1) //sending signals needs no senderobject #endif #if(USS_LIBRARY_DEBUG == 1) printf("(succesfully transported msi and acceped by sched)\n"); #endif close(fd); return 0; } else if(check == USS_CONTROL_SCHED_DECLINED) { dexit("(scheduler did not accept registration)\n"); ret = close(fd); return USS_ERROR_SCHED_DECLINED_REG; } return -1; }
/* * This is an ON Consolidation Private interface. */ char * _media_oldaliases(char *start) { struct alias *s, *ns; char *p; char *res; #ifdef DEBUG denter("_media_oldaliases(%s): entering\n", start); #endif for (s = device_aliases; *s->alias != NULLC; s++) { if (strcmp(start, s->alias) == 0) { break; } } /* we don't recognize that alias at all */ if (*s->alias == NULLC) { #ifdef DEBUG dprintf("_media_oldaliases: failed\n"); #endif res = NULL; goto dun; } /* if volume management isn't running at all, give him back the name */ if (!volmgt_running()) { #ifdef DEBUG dprintf("_media_oldaliases: no vold!\n"); #endif res = strdup(s->name); goto dun; } /* * If volume management is managing that device, look up the * volume management name. */ if (volmgt_inuse(s->name)) { for (s = volmgt_aliases; *s->alias != NULLC; s++) { if (strcmp(start, s->alias) == 0) { res = strdup(s->name); goto dun; } } #ifdef DEBUG dprintf("_media_oldaliases: failed\n"); #endif res = NULL; goto dun; } /* * If volume management isn't managing the device, it's possible * that he's given us an alias that we should recognize, but the * default name is wrong. For example a user might have his * cdrom on controller 1, being managed by volume management, * but we would think it isn't because volmgt_inuse just told * us that c0t6d0s2 isn't being managed. So, before we return * the /dev name, we'll test the alias out using media_findname. * If media_findname can't make sense out of the alias, it probably * means that we really, really aren't managing the device and * should just return the /dev name. Whew. Isn't this grody? */ for (ns = volmgt_aliases; *ns->alias != NULLC; ns++) { if (strcmp(start, ns->alias) == 0) { if ((p = media_findname_work(ns->name))) { res = p; goto dun; } else { break; } } } res = strdup(s->name); dun: #ifdef DEBUG dexit("_media_oldaliases: returning %s\n", res ? res : "<null ptr>"); #endif return (res); }
static int get_media_info(char *path, char **mtypep, int *mnump, char **spclp) { FILE *fp = NULL; int fd = -1; char *cn = NULL; /* char spcl pathname */ struct stat64 sb; struct dk_cinfo info; struct mnttab mnt; int ret_val = FALSE; if ((fp = fopen(MNTTAB, "rF")) == NULL) { /* mtab is gone... let him go */ goto dun; } /* get char spcl pathname */ if ((cn = volmgt_getfullrawname(path)) == NULL) { goto dun; } if (cn[0] == NULLC) { goto dun; } if ((fd = open(cn, O_RDONLY|O_NDELAY)) < 0) { goto dun; } if (fstat64(fd, &sb) < 0) { goto dun; } if (ioctl(fd, DKIOCINFO, &info) != 0) { goto dun; } /* if we found the entry then disect it */ if (vol_getmntdev(fp, &mnt, sb.st_rdev, &info) != 0) { char *cp; char *mtype; char *mnt_dir; int mtype_len; DIR *dirp = NULL; struct dirent64 *dp; char *volname; /* return the spcl device name found */ *spclp = strdup(mnt.mnt_special); /* * try to get the media type (e.g. "floppy") from the mount * point (e.g. "/floppy/NAME") if vold is running */ if (!volmgt_running() || (!volmgt_ownspath(*spclp) && volmgt_symname(*spclp) == NULL)) { ret_val = TRUE; /* success (if limited) */ goto dun; } /* get the first part of the mount point (e.g. "floppy") */ cp = mnt.mnt_mountp; if (*cp++ != '/') { goto dun; } mtype = cp; if ((cp = strchr(mtype, '/')) == NULL) { goto dun; } *cp++ = NULLC; mnt_dir = mnt.mnt_mountp; /* save dir path */ /* get the volume name (e.g. "unnamed_floppy") */ volname = cp; /* scan for the symlink that points to our volname */ if ((dirp = opendir(mnt_dir)) == NULL) { goto dun; } mtype_len = strlen(mtype); while ((dp = readdir64(dirp)) != NULL) { char lpath[2 * (MAXNAMELEN+1)]; char linkbuf[MAXPATHLEN+4]; int lb_len; struct stat64 sb; if (strncmp(dp->d_name, mtype, mtype_len) != 0) { continue; /* not even close */ } (void) sprintf(lpath, "%s/%s", mnt_dir, dp->d_name); if (lstat64(lpath, &sb) < 0) { continue; /* what? */ } if (!S_ISLNK(sb.st_mode)) { continue; /* not our baby */ } if ((lb_len = readlink(lpath, linkbuf, sizeof (linkbuf))) < 0) { continue; } linkbuf[lb_len] = NULLC; /* null terminate */ if ((cp = vol_basename(linkbuf)) == NULL) { continue; } /* now we have the name! */ if (strcmp(cp, volname) == 0) { /* found it !! */ if (sscanf(dp->d_name + mtype_len, "%d", mnump) == 1) { *mtypep = strdup(mtype); ret_val = TRUE; } break; } } (void) closedir(dirp); } dun: if (fp != NULL) { (void) fclose(fp); } if (fd >= 0) { (void) close(fd); } if (cn != NULL) { free(cn); } #ifdef DEBUG if (ret_val) { dexit("get_media_info: returning mtype=%s, mnum=%d, spcl=%s\n", *mtypep == NULL ? "<null ptr>" : *mtypep, *mnump, *spclp == NULL ? "<null ptr>" : *spclp); } else { dexit("get_media_info: FAILED\n"); } #endif return (ret_val); }
/* * arc approved interface * - can not be modified without approval from an arc * * committment level: * uncommitted * * description: * volmgt_acquire: try to acquire the volmgt advisory device reservation * for a specific device. * * arguments: * dev - a device name to attempt reserving. This string can be: * - a full path name to a device * - a symbolic device name (e.g. floppy0) * * id - a reservation string that hopefully describes the application * making this reservation. * * pid - a pointer to a pid_t type. If this argument is not NULL * and the requested device is already reserved, the process * id of the reservation owner will be returned in this * location. * * ovr - an override indicator. If set to non-zero, the caller requests * that this reservation be made unconditionally. * * err - the address of a pointer to a string which is to receive the * id argument used when the current device was reserved. This * is only used when the current reservation attempt fails due * to an already existing reservation for this device. * * return value(s): * A non-zero indicator if successful. * * A zero indicator if unsuccessful. If errno is EBUSY, then the err * argument will be set to point to the string that the process currently * holding the reservation supplied when reserving the device. It is up * to the caller to release the storage occupied by the string via * free(3C) when no longer needed. * * preconditions: * none */ int volmgt_acquire(char *dev, char *id, int ovr, char **err, pid_t *pidp) { char *targ_name = NULL; struct stat sb; dev_t idev; vol_dbid_t dbid = (vol_dbid_t)-1; vol_db_entry_t dbe; vol_db_entry_t *dbp; int retval = 0; /* default return => ERROR */ int reterr = 0; #ifdef DEBUG denter("volmgt_acquire(\"%s\", \"%s\", %s, %#p, %#p): entering\n", dev ? dev : "<null ptr>", id ? id : "<null ptr>", ovr ? "TRUE" : "FALSE", err, pidp); #endif /* * the supplied arguments must not be NULL */ if ((dev == NULL) || (id == NULL) || (err == NULL)) { errno = EINVAL; goto dun; } /* * the id string must not be longer than the maximum allowable * number of characters */ if (strlen(id) > VOL_RSV_MAXIDLEN) { errno = E2BIG; goto dun; } if ((targ_name = fsi_xlate_name(dev)) == NULL) { goto dun; } /* * convert 'char *dev' to major/minor pair */ if (stat(targ_name, &sb) < 0) { goto dun; } idev = sb.st_rdev; /* * open the database file */ if ((dbid = vol_db_open()) < 0) { goto dun; } if ((dbp = vol_db_find(dbid, idev)) == NULL) { /* * the entry wasn't found, so reserve it */ dbe.dev_major = major(idev); dbe.dev_minor = minor(idev); dbe.pid = getpid(); dbe.id_tag = id; if (vol_db_insert(dbid, &dbe) != 0) { retval = 1; /* success! */ } } else { if (ovr || (vol_db_proc_find(dbp->pid) == 0)) { /* * the entry exists but either override was specified * or the process holding the reservation is no longer * active * * in either case we'll usurp the reservation */ if (vol_db_remove(dbid, idev) != 0) { /* reserve the device */ dbe.dev_major = major(idev); dbe.dev_minor = minor(idev); dbe.pid = getpid(); dbe.id_tag = id; if (vol_db_insert(dbid, &dbe) != 0) { retval = 1; } } } else { /* * the entry exists and override was NOT specified */ /* * optionally return the pid of the reservation * owner */ if (pidp != NULL) { *pidp = dbp->pid; } *err = strdup(dbp->id_tag); reterr = EBUSY; } vol_db_free(dbp); /* Release the entry */ } /* * if an error was encountered (currently only EBUSY supported) * set errno to reflect it */ if (reterr != 0) { errno = reterr; } dun: if ((int)dbid >= 0) { (void) vol_db_close(dbid); } if (targ_name != NULL) { free(targ_name); } #ifdef DEBUG dexit("volmgt_acquire: returning %s\n", retval ? "TRUE" : "FALSE"); #endif return (retval); }
/* * arc approved interface * - can not be modified without approval from an arc * * committment level: * uncommitted * * description: * volmgt_release: try to release the volmgt advisory device reservation * for a specific device. * * arguments: * dev - a device name to attempt reserving. This string can be: * - a full path name to a device * - a symbolic device name (e.g. floppy0) * * return value(s): * A non-zero indicator if successful * A zero indicator if unsuccessful * * preconditions: * none */ int volmgt_release(char *dev) { char *targ_name = NULL; struct stat sb; long idev; vol_dbid_t dbid; vol_db_entry_t *dbp; int retval = 0; /* default return => FAILURE */ int reterr = 0; #ifdef DEBUG denter("volmgt_release(\"%s\"): entering\n", dev ? dev : "<null ptr>"); #endif /* * first let's do some minimal validation of the supplied arguments */ /* * the supplied argument must not be NULL */ if (dev == NULL) { errno = EINVAL; goto dun; } if ((targ_name = fsi_xlate_name(dev)) == NULL) { goto dun; } /* * convert 'char *dev' to major/minor pair */ if (stat(targ_name, &sb) < 0) { goto dun; } idev = sb.st_rdev; /* * open the database file */ if ((dbid = vol_db_open()) < 0) { goto dun; } if ((dbp = vol_db_find(dbid, idev)) == NULL) { /* the entry wasn't found so I can't clear reservation */ errno = ENOENT; goto dun; } /* the entry was found so make sure I can clear it */ if (dbp->pid == getpid()) { /* * the reservation was made by me, clear it */ if (vol_db_remove(dbid, idev) != 0) { retval = 1; } } else { /* * the entry wasn't made by me */ reterr = EBUSY; } vol_db_free(dbp); /* * if an error was encountered (currently only EBUSY supported) * set errno to reflect it */ if (reterr != 0) { errno = reterr; } dun: if ((int)dbid >= 0) { (void) vol_db_close(dbid); } if (targ_name != NULL) { free(targ_name); } #ifdef DEBUG dexit("volmgt_release: returning %s\n", retval ? "TRUE" : "FALSE"); #endif return (retval); }