view common.c @ 0:cd351af3a8d2 migout

import source
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Thu, 27 Mar 2008 20:03:52 -0400
parents
children b742383276b7
line wrap: on
line source

#include <xfs/dmapi.h>

#include "types.h"
#include "die.h"
#include "common.h"

#include "settings.h"

#define	SMTP_MSG	"SMTP DMAPI session"

/* borrowed from xfstest repo */
static int session_compare(const void *a, const void *b)
{
	return(*((dm_sessid_t *)a) - *((dm_sessid_t *)b));
}

/* borrowed from xfstest repo */
static void find_session(dm_sessid_t *session)
{
	char		buffer[DM_SESSION_INFO_LEN];
	dm_sessid_t	*sidbuf = NULL;
	dm_sessid_t	new_session;
	u_int		allocelem = 0;
	u_int		nelem;
	size_t		rlen;
	int		error;
	u_int		i;

	/* Retrieve the list of all active sessions on the host. */

	nelem = 100;		/* a reasonable first guess */
	do {
		if (allocelem < nelem) {
			allocelem = nelem;
			sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
			if (sidbuf == NULL) {
				fprintf(stderr, "realloc of %d bytes failed\n",
					nelem * sizeof(*sidbuf));
				exit(1);
			}
		}
		error = dm_getall_sessions(allocelem, sidbuf, &nelem);
	} while (error < 0 && errno == E2BIG);

	/* If an error occurred, translate it into something meaningful. */

	if (error < 0) {
		fprintf(stderr, "unexpected dm_getall_sessions failure, %s\n",
			strerror(errno));
		free(sidbuf);
		exit(1);
	}

	/* We have the list of all active sessions.  Scan the list looking
	   for an existing "test" session that we can use.  The list must
	   first be sorted in case other processes happen to be creating test
	   sessions at the same time; we need to make sure that we pick the one
	   with the lowest session ID.
	*/

	qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);

	for (i = 0; i < nelem; i++) {
		error = dm_query_session(sidbuf[i], sizeof(buffer),
				buffer, &rlen);
		if (error < 0) {
			fprintf(stderr, "unexpected dm_query_session "
				"failure, %s\n", strerror(errno));
			free(sidbuf);
			exit(1);
		}

		if (!strncmp(buffer, SMTP_MSG, sizeof(SMTP_MSG)))
			break;
	}
	if (i < nelem) {
		*session = (dm_sessid_t)sidbuf[i];
		free(sidbuf);
		return;
	}

	/* No test session exists, so we have to create one ourselves. */

	if (dm_create_session(DM_NO_SESSION, SMTP_MSG, &new_session) != 0) {
		fprintf(stderr, "dm_create_session failed, %s\n",
			strerror(errno));
		free(sidbuf);
		exit(1);
	}

	/* Now re-retrieve the list of active sessions. */

	do {
		if (allocelem < nelem) {
			allocelem = nelem;
			sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
			if (sidbuf == NULL) {
				fprintf(stderr, "realloc of %d bytes failed\n",
					nelem * sizeof(*sidbuf));
				exit(1);
			}
		}
		error = dm_getall_sessions(allocelem, sidbuf, &nelem);
	} while (error < 0 && errno == E2BIG);

	if (error < 0) {
		fprintf(stderr, "dm_getall_sessions failed, %s\n",
			strerror(errno));
		free(sidbuf);
		exit(1);
	}

	/* Sort the session ID list into ascending ID order, then find the
	   test session with the lowest session ID.  We better find at
	   least one since we created one!
	*/

	qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);

	for (i = 0; i < nelem; i++) {
		error = dm_query_session(sidbuf[i], sizeof(buffer),
				buffer, &rlen);
		if (error < 0) {
			fprintf(stderr, "dm_query_session failed, %s\n",
				strerror(errno));
			free(sidbuf);
			exit(1);
		}
		if (!strncmp(buffer, SMTP_MSG, sizeof(SMTP_MSG)))
			break;
	}
	if (i == nelem) {
		fprintf(stderr, "can't find the session we created\n");
		free(sidbuf);
		exit(1);
	}
	*session = (dm_sessid_t)sidbuf[i];
	free(sidbuf);

	/* If the session we are going to use is not the one we created,
	   then we need to get rid of the created one.
	*/

	if (*session != new_session) {
		if ((new_session) != 0) {
			fprintf(stderr, "dm_destroy_session failed, %s\n",
				strerror(errno));
			exit(1);
		}
	}
}

int setup_dmapi(dm_sessid_t *sid)
{
	char *c;

	if (dm_init_service(&c) == -1) {
		warn("cannot init dmapi");
		return 1;
	}

	if (strcmp(c, DM_VER_STR_CONTENTS)) {
		warn("wrong version of dmapi");
		return 1;
	}

	find_session(sid);
	return 0;
}

int get_dmchange(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, unsigned int *change)
{
	int err;
	dm_stat_t stat;

	err = dm_get_fileattr(sid, handle, hlen, token, DM_AT_CFLAG, &stat);
	if (err == -1) {
		warn("could not get fileattr");
		return 1;
	}

	*change = stat.dt_change;
	return 0;
}

int lock_file(dm_sessid_t sid, u8 *handle, size_t hlen, int right, dm_token_t *token)
{
	int err;

	err = dm_create_userevent(sid, 0, NULL, token);
	if (err == -1) {
		warn("cannot create user event for session");
		return 1;
	}

	err = dm_request_right(sid, handle, hlen, *token, DM_RR_WAIT, right);
	if (err == -1) {
		warn("cannot obtain requested right");
		return 1;
	}

	return 0;
}

void unlock_file(dm_sessid_t sid, dm_token_t token)
{
	int err;

	err = dm_respond_event(sid, token, DM_RESP_CONTINUE, 0, 0, 0);
	if (err == -1)
		warn("cannot respond to event/release token");
}

int save_dataloc(dm_sessid_t sid, u8 *handle, ssize_t hlen, dm_token_t token)
{
	dm_attrname_t attrname;
	int err;

	memcpy(&attrname.an_chars[0], "dhanloc", 8);
	err = dm_set_dmattr(sid, handle, hlen, token, &attrname, 0, hlen, handle);
	if (err) {
		warn("can't set data location");
		return 1;
	}

	memcpy(&attrname.an_chars[0], "dhanlen", 8);
	err = dm_set_dmattr(sid, handle, hlen, token, &attrname, 0, sizeof(hlen), (void*)&hlen);
	if (err) {
		warn("can't set data location length");
		return 1;
	}

	return 0;
}

int set_man_regions(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, dm_size_t fsize, dm_off_t *off)
{
	dm_off_t rroff = 0;
	dm_size_t rlen;
	dm_region_t reg;
	unsigned int exact;
	int err;

	if (fsize > FENCEPOST_SIZE) {
		err = dm_probe_hole(sid, handle, hlen, token, FENCEPOST_SIZE, 0, &rroff, &rlen);
		if (err) {
			warn("could not probe hole in file");
			return 1;
		}
	}

	*off = rroff;

	reg.rg_offset = rroff;
	reg.rg_size = 0;
	reg.rg_flags = DM_REGION_READ | DM_REGION_WRITE | DM_REGION_TRUNCATE;

	err = dm_set_region(sid, handle, hlen, token, 1, &reg, &exact);
	if (err) {
		warn("could not set managed region");
		return 1;
	}

	return 0;
}

int make_nonres(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, dm_off_t off)
{
	int err;

	err = dm_punch_hole(sid, handle, hlen, token, off, 0);
	if (err) {
		warn("could not punch hole in file");
		return 1;
	}

	return 0;
}

void clear_man_regions(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token)
{
	dm_region_t reg;
	unsigned int exact;
	int err;

	reg.rg_offset = 0;
	reg.rg_size = 0;
	reg.rg_flags = DM_REGION_NOEVENT;

	err = dm_set_region(sid, handle, hlen, token, 1, &reg, &exact);
	if (err)
		warn("could not clear managed regions from file");
}