static void gfarmGssPrintStatus(char **list, const char *diag) { char **lP = list; if (lP != NULL && *lP != NULL) { while (*lP != NULL) { gflog_info(GFARM_MSG_1000607, "\t : %s", *lP++); } } else gflog_info(GFARM_MSG_1000608, "GSS %s Status Error: UNKNOWN", diag); gfarmGssFreeCrackedStatus(list); }
/* FIXME: should support return values other than gfarm_error_t too */ void gfm_async_server_reply_to_gfsd_schedule(struct host *host, struct peer *peer, gfp_xdr_xid_t xid, gfarm_error_t errcode, int flags, const char *diag) { gfarm_error_t e; struct gfm_async_server_reply_to_gfsd_entry *qe; GFARM_MALLOC(qe); if (qe == NULL) { gflog_error(GFARM_MSG_1004031, "%s: %s: no memory for queue entry", host_name(host), diag); } else { netsendq_entry_init(&qe->qentry, &gfm_async_server_reply_to_gfsd_queue); qe->qentry.abhost = host_to_abstract_host(host); qe->peer = peer; qe->xid = xid; qe->errcode = errcode; qe->diag = diag; e = netsendq_add_entry(host_sendq(host), &qe->qentry, flags); if (e != GFARM_ERR_NO_ERROR) { gflog_info(GFARM_MSG_1004032, "%s: %s queueing: %s", host_name(host), diag, gfarm_error_string(e)); if ((flags & NETSENDQ_ADD_FLAG_DETACH_ERROR_HANDLING) == 0) free(qe); } } }
static void * gfs_client_status_request(void *arg) { gfarm_error_t e; struct gfs_client_status_entry *qe = arg; struct host *host = abstract_host_to_host(qe->qentry.abhost); struct peer *peer = host_get_peer(host); /* increment refcount */ static const char diag[] = "GFS_PROTO_STATUS"; e = gfs_client_send_request(host, peer, diag, gfs_client_status_result, gfs_client_status_free, qe, GFS_PROTO_STATUS, ""); netsendq_entry_was_sent(abstract_host_get_sendq(qe->qentry.abhost), &qe->qentry); if (e != GFARM_ERR_NO_ERROR) { gflog_info(GFARM_MSG_1001986, "gfs_client_status_request: %s", gfarm_error_string(e)); /* accessing `qe' is only allowed if e != GFARM_ERR_NO_ERROR */ qe->qentry.result = e; gfs_client_status_free(peer, qe); } host_put_peer(host, peer); /* decrement refcount */ /* this return value won't be used, because this thread is detached */ return (NULL); }
int FUNC__XSTAT(int ver, const char *path, STRUCT_STAT *buf) { _gfs_hook_debug_v( gflog_info(GFARM_MSG_UNFIXED, "Hooking " S(FUNC__XSTAT) ": %s", path)); return (FUNC___XSTAT(ver, path, buf)); }
static gfarm_error_t gfm_server_switch_back_channel_common( struct peer *peer, gfp_xdr_xid_t xid, size_t *sizep, int from_client, int version, const char *diag, struct relayed_request *relay) { gfarm_error_t e = GFARM_ERR_NO_ERROR, e2; struct host *host; gfp_xdr_async_peer_t async = NULL; struct local_peer *local_peer = NULL; int is_direct_connection; int i = 0; #ifdef __GNUC__ /* workaround gcc warning: might be used uninitialized */ host = NULL; #endif is_direct_connection = (peer_get_parent(peer) == NULL); giant_lock(); if (from_client) { gflog_debug(GFARM_MSG_1001995, "Operation not permitted: from_client"); e = GFARM_ERR_OPERATION_NOT_PERMITTED; } else if ((host = peer_get_host(peer)) == NULL) { gflog_debug(GFARM_MSG_1001996, "Operation not permitted: peer_get_host() failed"); e = GFARM_ERR_OPERATION_NOT_PERMITTED; } else if (is_direct_connection && (e = gfp_xdr_async_peer_new(&async)) != GFARM_ERR_NO_ERROR) { gflog_error(GFARM_MSG_1002288, "%s: gfp_xdr_async_peer_new(): %s", diag, gfarm_error_string(e)); } giant_unlock(); e2 = gfm_server_relay_put_reply(peer, xid, sizep, relay, diag, &e, "i", &i/*XXX FIXME*/); if (e2 != GFARM_ERR_NO_ERROR) return (e2); if (debug_mode) gflog_debug(GFARM_MSG_1000404, "gfp_xdr_flush"); e2 = gfp_xdr_flush(peer_get_conn(peer)); if (e2 != GFARM_ERR_NO_ERROR) { gflog_warning(GFARM_MSG_1000405, "%s: protocol flush: %s", diag, gfarm_error_string(e2)); return (e2); } else if (e != GFARM_ERR_NO_ERROR) return (e2); if (is_direct_connection) { local_peer = peer_to_local_peer(peer); local_peer_set_async(local_peer, async); /* XXXRELAY */ local_peer_set_readable_watcher(local_peer, back_channel_recv_watcher); } if (host_is_up(host)) /* throw away old connetion */ { gflog_warning(GFARM_MSG_1002440, "back_channel(%s): switching to new connection", host_name(host)); host_disconnect_request(host, NULL); } giant_lock(); peer_set_peer_type(peer, peer_type_back_channel); abstract_host_set_peer(host_to_abstract_host(host), peer, version); giant_unlock(); if (is_direct_connection) { local_peer_watch_readable(local_peer); gfarm_thr_statewait_signal( local_peer_get_statewait(local_peer), e2, diag); } callout_setfunc(host_status_callout(host), NULL /* or, use back_channel_send_manager thread pool? */, gfs_client_status_callout, host); gfs_client_status_schedule(host, 1); gflog_info(GFARM_MSG_1004035, "back_channel(%s): started", host_name(host)); return (e2); }
/* * Back channel protocol switch for slave gfmd. It forwards a GFS protocol * request from gfsd it a master gmfd and relays its reply in the opposite * direction. */ static gfarm_error_t async_back_channel_protocol_switch_slave(struct abstract_host *h, struct peer *peer, int request, gfp_xdr_xid_t xid, size_t size, int *unknown_request) { gfarm_error_t e = GFARM_ERR_NO_ERROR; struct host *host = abstract_host_to_host(h); struct gfp_xdr *conn = peer_get_conn(peer); struct protocol_switch_slave_closure *closure = NULL; size_t data_size; int eof; static const char diag[] = "async_back_channel_protocol_switch_slave"; if (debug_mode) gflog_info(GFARM_MSG_1004033, "%s: <%s> back_channel start receiving request(%d)", peer_get_hostname(peer), diag, (int)request); do { /* * We dispose 'closure' in * async_back_channel_protocol_switch_slave_result(). */ closure = protocol_switch_slave_closure_alloc(h, peer_get_private_peer_id(peer), xid, size, NULL); if (closure == NULL) { e = GFARM_ERR_NO_MEMORY; (void) gfp_xdr_purge(conn, 0, size); break; } data_size = size; e = gfp_xdr_recv(conn, 1, &eof, "r", data_size, &data_size, closure->data); if (e != GFARM_ERR_NO_ERROR) { (void) gfp_xdr_purge(conn, 0, size); break; } else if (eof) { e = GFARM_ERR_UNEXPECTED_EOF; break; } else if (data_size != 0) { e = GFARM_ERR_PROTOCOL; gflog_warning(GFARM_MSG_1004034, "%s: <%s> protocol redidual %u", peer_get_hostname(peer), diag, (int)data_size); } e = gfmdc_slave_client_remote_gfs_rpc(peer, closure, async_back_channel_protocol_switch_slave_result, async_back_channel_protocol_switch_slave_disconnect, request, size, closure->data); } while (0); if (e != GFARM_ERR_NO_ERROR) { if (!eof) { (void) gfm_async_server_put_reply(host, peer, xid, diag, e, ""); } if (closure != NULL) protocol_switch_slave_closure_free(closure); } return (e); }
static void gfs_client_status_schedule(struct host *host, int first_attempt) { gfarm_error_t e; struct gfs_client_status_entry *qe; enum { stop_callout, do_next, do_retry } callout_next = do_next; const char diag[] = "GFS_PROTO_STATUS"; GFARM_MALLOC(qe); if (qe == NULL) { callout_next = do_retry; gflog_error(GFARM_MSG_1004026, "%s: %s: no memory for queue entry", host_name(host), diag); } else { netsendq_entry_init(&qe->qentry, &gfs_proto_status_queue); qe->qentry.abhost = host_to_abstract_host(host); e = netsendq_add_entry(host_sendq(host), &qe->qentry, NETSENDQ_ADD_FLAG_DETACH_ERROR_HANDLING); if (e == GFARM_ERR_NO_ERROR) { /* OK */ } else if (first_attempt && e == GFARM_ERR_DEVICE_BUSY) { /* * if this is first attempt just after * the back channel connection is made, * it's possible previous callout remains * with the following scenario: * 1. gfs_client_status_callout() thread begins to run * 2. host_unset_peer() calls callout_stop() * 3. netsendq_host_becomes_down() clears readyq * 4. the gfs_client_status_callout() thread in 1 * adds an entry to workq and readyq */ gflog_info(GFARM_MSG_1004027, "%s: %s queueing conflict", host_name(host), diag); } else { /* increment refcount */ struct peer *peer = host_get_peer(host); callout_next = stop_callout; gflog_info(GFARM_MSG_1004028, "%s: %s queueing: %s", host_name(host), diag, gfarm_error_string(e)); /* `qe' is be freed by gfs_client_status_finalize() */ if (peer == NULL) { gflog_info(GFARM_MSG_1004029, "%s: %s: already disconnected", host_name(host), diag); } else { gfs_client_status_disconnect_or_message(host, peer, diag, "queueing", gfarm_error_string(e)); /* decrement refcount */ host_put_peer(host, peer); } } } switch (callout_next) { case stop_callout: /* do nothing */ break; case do_next: callout_schedule(host_status_callout(host), gfarm_metadb_heartbeat_interval * 1000000); break; case do_retry: callout_schedule(host_status_callout(host), gfarm_metadb_heartbeat_interval * 1000000 / 10); break; } }
int FUNC___XSTAT(int ver, const char *path, STRUCT_STAT *buf) { const char *e; char *url; struct gfs_stat gs; int nf = -1, np, errno_save = errno; _gfs_hook_debug_v(gflog_info(GFARM_MSG_UNFIXED, "Hooking " S(FUNC___XSTAT) "(%s)", path)); if (!gfs_hook_is_url(path, &url)) return (SYSCALL_XSTAT(ver, path, buf)); _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: Hooking " S(FUNC___XSTAT) "(%s)", path)); switch (gfs_hook_get_current_view()) { case section_view: _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: " S(GFS_STAT_SECTION) "(%s, %s)", url, gfs_hook_get_current_section())); e = GFS_STAT_SECTION(url, gfs_hook_get_current_section(), &gs); break; case index_view: _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: " S(GFS_STAT_INDEX) "(%s, %d)", url, gfs_hook_get_current_index())); e = GFS_STAT_INDEX(url, gfs_hook_get_current_index(), &gs); break; case local_view: /* * If the number of fragments is not the same as the * number of parallel processes, or the file is not * fragmented, do not change to the local file view. */ if (gfarm_url_fragment_number(url, &nf) == NULL) { if (gfs_pio_get_node_size(&np) == NULL && nf == np) { _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: " S(GFS_STAT_INDEX) "(%s, %d)", url, gfarm_node)); e = GFS_STAT_INDEX(url, gfarm_node, &gs); } else { _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: " S(GFS_STAT) "(%s)", url)); e = GFS_STAT(url, &gs); } } else { _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: " S(GFS_STAT) "(%s)", url)); e = GFS_STAT(url, &gs); } break; default: _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: " S(GFS_STAT) "(%s)", url)); e = GFS_STAT(url, &gs); } free(url); if (e == NULL) { struct passwd *p; memset(buf, 0, sizeof(*buf)); buf->st_dev = GFS_DEV; buf->st_ino = gs.st_ino; buf->st_mode = gs.st_mode; buf->st_nlink = S_ISDIR(buf->st_mode) ? GFS_NLINK_DIR : 1; /* XXX FIXME: need to convert gfarm global user to UNIX uid */ p = getpwnam(gfarm_get_local_username()); if (p != NULL) { buf->st_uid = p->pw_uid; buf->st_gid = p->pw_gid; } else { buf->st_uid = getuid(); /* XXX */ buf->st_gid = getgid(); /* XXX */ } buf->st_size = gs.st_size; buf->st_blksize = GFS_BLKSIZE; buf->st_blocks = (gs.st_size + STAT_BLKSIZ - 1) / STAT_BLKSIZ; buf->st_atime = gs.st_atimespec.tv_sec; buf->st_mtime = gs.st_mtimespec.tv_sec; buf->st_ctime = gs.st_ctimespec.tv_sec; gfs_stat_free(&gs); errno = errno_save; return (0); } _gfs_hook_debug(gflog_info(GFARM_MSG_UNFIXED, "GFS: " S(FUNC___XSTAT) ": %s", e)); errno = gfarm_error_to_errno(e); return (-1); }
int FUNC___OPEN(const char *path, int oflag, ...) { GFS_File gf; const char *e; char *url; va_list ap; mode_t mode; int filedes; struct gfs_stat gs; int is_directory, save_errno; int nf = -1, np; va_start(ap, oflag); /* * We need `int' instead of `mode_t' in va_arg() below, because * sizeof(mode_t) < sizeof(int) on some platforms (e.g. FreeBSD), * and gcc-3.4/gcc-4's builtin va_arg() warns the integer promotion. * XXX this doesn't work, if sizeof(mode_t) > sizeof(int), * but currently there isn't any such platform as far as we know. */ mode = va_arg(ap, int); va_end(ap); _gfs_hook_debug_v(gflog_info( "Hooking " S(FUNC___OPEN) "(%s, 0%o)", path, oflag)); if (!gfs_hook_is_url(path, &url)) return (SYSCALL_OPEN(path, oflag, mode)); if (gfs_hook_get_current_view() == section_view) e = gfs_stat_section(url, gfs_hook_get_current_section(), &gs); else e = gfs_stat(url, &gs); if (e == NULL) { is_directory = GFARM_S_ISDIR(gs.st_mode); gfs_stat_free(&gs); } else { /* XXX - metadata may be incomplete. anyway, continue. */ /* XXX - metadata of a directory should not be imcomplete */ is_directory = 0; if (e != GFARM_ERR_NO_SUCH_OBJECT) _gfs_hook_debug(gflog_info( "GFS: Hooking " S(FUNC___OPEN) ": gfs_stat: %s", e)); } if (is_directory) { GFS_Dir dir; _gfs_hook_debug(gflog_info( "GFS: Hooking " S(FUNC___OPEN) "(%s, 0%o): dir", url, oflag)); if ((oflag & (O_CREAT|O_TRUNC)) != 0 || (oflag & O_ACCMODE) != O_RDONLY) { free(url); errno = EISDIR; return (-1); } e = gfs_opendir(url, &dir); if (e == NULL) { filedes = gfs_hook_insert_gfs_dir(dir, url); save_errno = errno; _gfs_hook_debug( gflog_info("GFS: Hooking " S(FUNC___OPEN) " --> %d", filedes); ); free(url); if (filedes == -1) errno = save_errno; return (filedes); }