Beispiel #1
0
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);
}
Beispiel #2
0
/* 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);
		}
	}
}
Beispiel #3
0
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);
}
Beispiel #4
0
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));
}
Beispiel #5
0
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);
}
Beispiel #6
0
/*
 * 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);
}
Beispiel #7
0
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;
	}
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
		}