Example #1
0
/*
 *			logfile_getaddr
 *
 * Description:
 *	Returns an address of a particular offset in the file.
 *	The size of the item to map is i_maxmap
 *	This routine assumes that if we have to remap that i_maxmap
 *	will fit inside the default mapping size.
 * Arguments:
 *	start	offset in the file to map
 *	map	0 means use map_entry, 1 means use map_offset
 * Returns:
 *	Returns NULL for a failure with the mapping file.
 * Preconditions:
 */
caddr_t
logfile_getaddr(cfsd_logfile_object_t *logfile_object_p, off_t start, int map)
{
	mmap_info_t *mmp;
	caddr_t pa;
	off_t end;

	dbug_enter("logfile_getaddr");

	mmp = (map == 0) ?
	    &logfile_object_p->i_map_entry :
	    &logfile_object_p->i_map_offset;

	/* determine the end of the item */
	end = start + logfile_object_p->i_maxmap - 1;

	/* map the entry in if necessary */
	if ((start < mmp->i_paoff) || (mmp->i_paend < end)) {
		if (logfile_domap(logfile_object_p,
		    start & logfile_object_p->i_pagemask, map)) {
			dbug_leave("logfile_getaddr");
			return (NULL);
		}
		dbug_assert((mmp->i_paoff <= start) && (end <= mmp->i_paend));
	}

	/* make an address and return it */
	pa = mmp->i_pa + (start - mmp->i_paoff);
	dbug_leave("logfile_getaddr");
	return (pa);
}
Example #2
0
/*
 *			logfile_dumpstats
 *
 * Description:
 *	Prints out various stats about the hashing.
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
logfile_dumpstats(cfsd_logfile_object_t *logfile_object_p)
{
	int xx;
	double dd;

	dbug_enter("logfile_dumpstats");

	dbug_print(("dump", "Request - next %d",
	    logfile_object_p->i_stat_nextcnt));
	dbug_print(("dump", "Request - offset %d",
	    logfile_object_p->i_stat_offcnt));
	dbug_print(("dump", "Map Moves %d", logfile_object_p->i_stat_mapmove));
	dbug_print(("dump", "Mapping Size %d", logfile_object_p->i_maplen));
	dbug_print(("dump", "Item Size %d", logfile_object_p->i_maxmap));
	dbug_print(("dump", "File Size %d", logfile_object_p->i_size));
	if (logfile_object_p->i_stat_mapmove == 0) {
		dbug_leave("logfile_dumpstats");
		return;
	}

	dd = (double)logfile_object_p->i_stat_mapmove /
	    (logfile_object_p->i_stat_nextcnt +
	    logfile_object_p->i_stat_offcnt);
	dbug_print(("dump", "Mmap moves per Request %.2f", dd));

	xx = logfile_object_p->i_stat_mapdist /
	    logfile_object_p->i_stat_mapmove;
	dbug_print(("dump", "Average distance per mmap moves %d", xx));
	dbug_leave("logfile_dumpstats");
}
Example #3
0
/*
 *			logfile_entry
 *
 * Description:
 *	Sets addrp to the address of the log entry at offset
 *	The mapping remains in effect until:
 *		a) this routine is called again
 *		b) logfile_teardown is called
 *		c) this object is destroyed
 * Arguments:
 *	offset	offset to start of entry
 *	entpp	place to store address
 * Returns:
 *	Returns 0 for success, 1 for EOF, -1 if a fatal error occurs.
 * Preconditions:
 *	precond(addrp)
 */
int
logfile_entry(cfsd_logfile_object_t *logfile_object_p,
	off_t offset,
	cfs_dlog_entry_t **entpp)
{
	cfs_dlog_entry_t *entp;

	dbug_enter("logfile_entry");
	dbug_precond(entpp);
	dbug_precond(offset >= sizeof (long));


	logfile_object_p->i_stat_nextcnt++;

	/* check for eof */
	if (offset >= logfile_object_p->i_size) {
		dbug_leave("logfile_entry");
		return (1);
	}
	dbug_assert((offset & 3) == 0);

	/* get the address of the entry */
	entp = (cfs_dlog_entry_t *)logfile_getaddr(logfile_object_p, offset, 0);
	if (entp == NULL) {
		dbug_leave("logfile_entry");
		return (-1);
	}
	/* sanity check, record should be alligned */
	if (entp->dl_len & 3) {
		dbug_print(("error",
		    "Record at offset %d length is not alligned %d",
		    offset, entp->dl_len));
		dbug_leave("logfile_entry");
		return (-1);
	}

	/* sanity check record should a reasonable size */
	if ((entp->dl_len < CFS_DLOG_ENTRY_MINSIZE) ||
	    (entp->dl_len > CFS_DLOG_ENTRY_MAXSIZE)) {
		dbug_print(("error",
		    "Record at offset %d has an invalid size %d", offset,
		    entp->dl_len));
		dbug_leave("logfile_entry");
		return (-1);
	}

	/* preserve offset and pointer */
	logfile_object_p->i_cur_offset = offset;
	logfile_object_p->i_cur_entry = entp;

	/* return success */
	*entpp = entp;
	dbug_leave("logfile_entry");
	return (0);
}
Example #4
0
/*
 *			logfile_domap
 *
 * Description:
 *	Maps in the specified section of the file.
 * Arguments:
 *	off	The offset to map in.  Must be i_pagesize aligned.
 *	map	0 means use map_entry, 1 means use map_offset
 * Returns:
 *	Returns 0 for success or an errno value on failure.
 * Preconditions:
 */
int
logfile_domap(cfsd_logfile_object_t *logfile_object_p, off_t off, int map)
{
	int xx;
	int len;
	mmap_info_t *mmp;

	dbug_enter("logfile_domap");
	dbug_precond(logfile_object_p->i_fid >= 0);

	len = logfile_object_p->i_maplen;
	mmp = (map == 0) ?
		&logfile_object_p->i_map_entry :
		&logfile_object_p->i_map_offset;

	logfile_object_p->i_stat_mapmove++;

	/* destroy old mapping if it exists */
	if (mmp->i_pa) {
		/* determine how far we have to move the map */
		logfile_object_p->i_stat_mapdist += abs(mmp->i_paoff - off);

		/* remove the map */
		xx = munmap(mmp->i_pa, mmp->i_palen);
		if (xx == -1) {
			xx = errno;
			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
			    logfile_object_p->i_name, xx, mmp->i_pa,
			    mmp->i_palen));
		}
		mmp->i_pa = NULL;
		mmp->i_palen = 0;
		mmp->i_paoff = 0;
		mmp->i_paend = 0;
	}

	/* do the mapping */
	mmp->i_pa = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
	    logfile_object_p->i_fid, off);
	if (mmp->i_pa == MAP_FAILED) {
		xx = errno;
		dbug_print(("error",
		    "Could not map %s, error %d, off %d, len %d",
		    logfile_object_p->i_name, xx, off, len));
		mmp->i_pa = NULL;
		dbug_leave("logfile_domap");
		return (xx);
	}

	mmp->i_palen = len;
	mmp->i_paoff = off;
	mmp->i_paend = off + len - 1;
	dbug_leave("logfile_domap");
	return (0);
}
Example #5
0
/*
 *			fscache_fsproblem
 *
 * Description:
 * Arguments:
 *	kmodp
 * Returns:
 * Preconditions:
 *	precond(kmodp)
 */
void
fscache_fsproblem(cfsd_fscache_object_t *fscache_object_p,
	cfsd_kmod_object_t *kmod_object_p)
{
#if 0
	int xx;
#endif

	dbug_enter("fscache_fsproblem");

	dbug_precond(fscache_object_p);
	dbug_precond(kmod_object_p);

#if 0
	/* first try to put all modified files in lost+found */
	xx = kmod_lostfoundall(kmod_object_p);
	if (xx) {
		/* if that failed, put file system in read-only mode */
		kmod_rofs(kmod_object_p);
#endif
		fscache_lock(fscache_object_p);
		fscache_object_p->i_disconnectable = 0;
		fscache_object_p->i_modify++;
		fscache_unlock(fscache_object_p);
#if 0
	}
#endif
	dbug_leave("fscache_fsproblem");
}
Example #6
0
/*
 * -----------------------------------------------------------------
 *			cfsd_fscache_destroy
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
cfsd_fscache_destroy(cfsd_fscache_object_t *fscache_object_p)
{
	int xx;

	dbug_enter("cfsd_fscache_destroy");

	dbug_precond(fscache_object_p);
	/* dbug_assert(fscache_object_p->i_refcnt == 0); */

	/* close down the message file descriptor */
	if (fscache_object_p->i_ofd >= 0) {
		if (close(fscache_object_p->i_ofd))
			dbug_print(("error", "cannot close fscache fd error %d",
			    errno));
		fscache_object_p->i_ofd = -1;
	}

	/* destroy the locking mutex */
	xx = mutex_destroy(&fscache_object_p->i_lock);
	dbug_assert(xx == 0);

	/* destroy the conditional variable */
	xx = cond_destroy(&fscache_object_p->i_cvwait);
	dbug_assert(xx == 0);

	cfsd_free(fscache_object_p);

	dbug_leave("cfsd_fscache_destroy");
}
Example #7
0
/*
 * ------------------------------------------------------------
 *			all_cachefstab_update
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
all_cachefstab_update(cfsd_all_object_t *all_object_p)
{
	cfsd_cache_object_t *cache_object_p;
	FILE *fout;

	dbug_enter("all_cachefstab_update");

	fout = fopen(CACHEFSTAB, "w");
	if (fout == NULL) {
		dbug_print(("error", "cannot write %s", CACHEFSTAB));
	} else {
		cache_object_p = all_object_p->i_cachelist;

		while (cache_object_p != NULL) {
			dbug_assert(cache_object_p);
			fprintf(fout, "%s\n", cache_object_p->i_cachedir);
			cache_object_p = cache_object_p->i_next;
		}
		if (fclose(fout))
			dbug_print(("error", "cannot close %s error %d",
			    CACHEFSTAB, errno));
	}
	dbug_leave("all_cachefstab_update");
}
Example #8
0
/*
 * ------------------------------------------------------------
 *			cfsd_all_destroy
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
cfsd_all_destroy(cfsd_all_object_t *all_object_p)
{
	cfsd_cache_object_t *cache_object_p;
	cfsd_cache_object_t *tmp_cache_object_p;
	int xx;

	dbug_enter("cfsd_all_destroy");

	/* dbug_assert(all_object_p->i_hoardp == NULL); */

	/* get rid of any cache objects */
	cache_object_p = all_object_p->i_cachelist;

	while (cache_object_p != NULL) {
		tmp_cache_object_p = cache_object_p->i_next;
		cfsd_cache_destroy(cache_object_p);
		cache_object_p = tmp_cache_object_p;
	}

	/* destroy the locking mutex */
	xx = mutex_destroy(&all_object_p->i_lock);
	dbug_assert(xx == 0);
	cfsd_free(all_object_p);
	dbug_leave("cfsd_all_destroy");
}
Example #9
0
/*
 * ------------------------------------------------------------
 *			all_unlock
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
all_unlock(cfsd_all_object_t *all_object_p)
{
	dbug_enter("all_unlock");

	mutex_unlock(&all_object_p->i_lock);
	dbug_leave("all_unlock");
}
Example #10
0
/*
 * -----------------------------------------------------------------
 *			fscache_unlock
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
fscache_unlock(cfsd_fscache_object_t *fscache_object_p)
{
	dbug_enter("fscache_unlock");

	dbug_precond(fscache_object_p);
	mutex_unlock(&fscache_object_p->i_lock);
	dbug_leave("fscache_unlock");
}
Example #11
0
/*
 *			cfsd_logfile_destroy
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
cfsd_logfile_destroy(cfsd_logfile_object_t *logfile_object_p)
{
	dbug_enter("cfsd_logfile_destroy");
	logfile_sync(logfile_object_p);
	logfile_teardown(logfile_object_p);
	cfsd_free(logfile_object_p);
	dbug_leave("cfsd_logfile_destroy");
}
Example #12
0
/*
 *			fscache_changes
 *
 * Description:
 *	Used to specify whether or not there are changes to roll to the
 *	server.
 * Arguments:
 *	tt
 * Returns:
 * Preconditions:
 */
void
fscache_changes(cfsd_fscache_object_t *fscache_object_p, int tt)
{
	dbug_enter("fscache_changes");
	dbug_precond(fscache_object_p);
	fscache_object_p->i_changes = tt;
	fscache_object_p->i_modify++;
	dbug_leave("fscache_changes");
}
Example #13
0
/*
 *			logfile_sync
 *
 * Description:
 *	Performs an fsync on the log file.
 * Arguments:
 * Returns:
 *	Returns 0 for success or an errno value on failure.
 * Preconditions:
 */
int
logfile_sync(cfsd_logfile_object_t *logfile_object_p)
{
	int xx;

	dbug_enter("logfile_sync");

	if (logfile_object_p->i_fid == -1) {
		dbug_leave("logfile_sync");
		return (0);
	}
	xx = fsync(logfile_object_p->i_fid);
	if (xx) {
		xx = errno;
		dbug_print(("error", "fsync failed %d", xx));
	}
	dbug_leave("logfile_sync");
	return (xx);
}
Example #14
0
/*
 * ------------------------------------------------------------
 *			all_cachelist_add
 *
 * Description:
 * Arguments:
 *	cachep
 * Returns:
 * Preconditions:
 *	precond(cachep)
 */
void
all_cachelist_add(cfsd_all_object_t *all_object_p,
	cfsd_cache_object_t *cache_object_p)
{
	dbug_enter("all_cachelist_add");

	dbug_precond(cache_object_p);

	cache_object_p->i_next = all_object_p->i_cachelist;
	all_object_p->i_cachelist = cache_object_p;
	all_object_p->i_modify++;
	all_object_p->i_cachecount++;
	dbug_leave("all_cachelist_add");
}
Example #15
0
/*
 *			logfile_teardown
 *
 * Description:
 *	Uninitializes the object.
 *	Call logfile_setup before using this object again.
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
logfile_teardown(cfsd_logfile_object_t *logfile_object_p)
{
	int xx;

	dbug_enter("logfile_teardown");

	if (logfile_object_p->i_map_entry.i_pa) {
		xx = munmap(logfile_object_p->i_map_entry.i_pa,
		    logfile_object_p->i_map_entry.i_palen);
		if (xx == -1) {
			xx = errno;
			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
			    logfile_object_p->i_name, xx,
			    logfile_object_p->i_map_entry.i_pa,
			    logfile_object_p->i_map_entry.i_palen));
		}
		logfile_object_p->i_map_entry.i_pa = NULL;
	}
	logfile_object_p->i_map_entry.i_paoff = 0;
	logfile_object_p->i_map_entry.i_paend = 0;
	logfile_object_p->i_map_entry.i_palen = 0;

	if (logfile_object_p->i_map_offset.i_pa) {
		xx = munmap(logfile_object_p->i_map_offset.i_pa,
		    logfile_object_p->i_map_offset.i_palen);
		if (xx == -1) {
			xx = errno;
			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
			    logfile_object_p->i_name, xx,
			    logfile_object_p->i_map_offset.i_pa,
			    logfile_object_p->i_map_offset.i_palen));
		}
		logfile_object_p->i_map_offset.i_pa = NULL;
	}
	logfile_object_p->i_map_offset.i_paoff = 0;
	logfile_object_p->i_map_offset.i_paend = 0;
	logfile_object_p->i_map_offset.i_palen = 0;

	if (logfile_object_p->i_fid != -1) {
		if (close(logfile_object_p->i_fid))
			dbug_print(("error", "Could not close %s, %d",
			    logfile_object_p->i_name, errno));
		logfile_object_p->i_fid = -1;
	}
	logfile_object_p->i_cur_offset = 0;
	logfile_object_p->i_cur_entry = NULL;
	dbug_leave("logfile_teardown");
}
Example #16
0
/*
 *			logfile_offset
 *
 * Description:
 *	Sets addrp to the address of the specified offset.
 *	The mapping remains in effect until:
 *		a) this routine is called again
 *		b) logfile_teardown is called
 *		c) this object is destroyed
 * Arguments:
 *	offset	offset into file, must be 0 <= offset < i_size
 *	addrp	returns mapped address
 * Returns:
 *	Returns 0 for success, -1 if a fatal error occurs.
 * Preconditions:
 *	precond(addrp)
 */
int
logfile_offset(cfsd_logfile_object_t *logfile_object_p,
	off_t offset,
	caddr_t *addrp)
{
	caddr_t pa;

	dbug_enter("logfile_offset");
	dbug_precond(addrp);
	dbug_precond((0 <= offset) && (offset < logfile_object_p->i_size));

	logfile_object_p->i_stat_offcnt++;

	/* get the address for the offset */
	pa = logfile_getaddr(logfile_object_p, offset, 1);
	if (pa == NULL) {
		dbug_leave("logfile_offset");
		return (-1);
	}
	/* return success */
	*addrp = pa;
	dbug_leave("logfile_offset");
	return (0);
}
Example #17
0
/*
 * -----------------------------------------------------------------
 *			cfsd_fscache_create
 *
 * Description:
 * Arguments:
 *	name
 *	cachepath
 * Returns:
 * Preconditions:
 *	precond(name)
 *	precond(cachepath)
 */
cfsd_fscache_object_t *
cfsd_fscache_create(const char *name, const char *cachepath,
	int fscacheid)
{
	cfsd_fscache_object_t *fscache_object_p;
	int xx;

	dbug_enter("cfsd_fscache_create");

	dbug_precond(name);
	dbug_precond(cachepath);

	fscache_object_p = cfsd_calloc(sizeof (cfsd_fscache_object_t));
	strlcpy(fscache_object_p->i_name, name,
	    sizeof (fscache_object_p->i_name));
	strlcpy(fscache_object_p->i_cachepath, cachepath,
	    sizeof (fscache_object_p->i_cachepath));
	fscache_object_p->i_fscacheid = fscacheid;
	fscache_object_p->i_refcnt = 0;
	fscache_object_p->i_disconnectable = 0;
	fscache_object_p->i_mounted = 0;
	fscache_object_p->i_threaded = 0;
	fscache_object_p->i_connected = 0;
	fscache_object_p->i_reconcile = 0;
	fscache_object_p->i_changes = 0;
	fscache_object_p->i_simdis = 0;
	fscache_object_p->i_tryunmount = 0;
	fscache_object_p->i_backunmount = 0;
	fscache_object_p->i_time_state = 0;
	fscache_object_p->i_time_mnt = 0;
	fscache_object_p->i_modify = 1;

	fscache_object_p->i_threadid = 0;
	fscache_object_p->i_ofd = -1;

	fscache_object_p->i_next = NULL;

	/* initialize the locking mutex */
	xx = mutex_init(&fscache_object_p->i_lock, USYNC_THREAD, NULL);
	dbug_assert(xx == 0);

	xx = cond_init(&fscache_object_p->i_cvwait, USYNC_THREAD, 0);
	dbug_assert(xx == 0);

	dbug_leave("cfsd_fscache_create");
	return (fscache_object_p);
}
Example #18
0
int
fscache_pingserver(cfsd_fscache_object_t *fscache_object_p)
{

	static struct timeval TIMEOUT = { 25, 0 };
	CLIENT *clnt;
	enum clnt_stat retval;
	int ret = 0;
	char hostname[sizeof (fscache_object_p->i_backfs)];
	char *cptr;

	dbug_enter("fscache_pingserver");
	dbug_precond(fscache_object_p);

	strlcpy(hostname, fscache_object_p->i_backfs, sizeof (hostname));
	if (cptr = strchr(hostname, ':'))
		*cptr = '\0';

	dbug_assert(cptr != NULL);
	dbug_print(("info", "remote host '%s' before clnt_create", hostname));

	dbug_print(("info", "before clnt_create"));
	/* XXX this takes 75 seconds to time out */
	/* XXX should use lower level routines to reduce overhead */
	clnt = clnt_create(hostname, NFS_PROGRAM, NFS_VERSION, "udp");
	if (clnt == NULL) {
		/* XXX what if this fails other than TIMEDOUT */
		/* clnt_pcreateerror(hostname); */
		dbug_print(("info", "clnt_create failed"));
		ret = -1;
	} else {
		dbug_print(("info", "before null rpc"));
		/* XXX this takes 45 seconds to time out */
		retval = clnt_call(clnt, 0, xdr_void, NULL, xdr_void, NULL,
		    TIMEOUT);
		if (retval != RPC_SUCCESS) {
			/* clnt_perror(clnt, "null rpc call failed"); */
			dbug_print(("info", "null rpc call failed %d", retval));
			ret = -1;
		}
		clnt_destroy(clnt);
	}
	dbug_leave("fscache_pingserver");
	return (ret);
}
Example #19
0
/*
 * ------------------------------------------------------------
 *			all_cachelist_at
 *
 * Description:
 * Arguments:
 *	index
 * Returns:
 *	Returns ...
 * Preconditions:
 */
cfsd_cache_object_t *
all_cachelist_at(cfsd_all_object_t *all_object_p, size_t index)
{
	cfsd_cache_object_t *cache_object_p;
	int i = 0;

	dbug_enter("all_cachelist_at");

	/* find the correct cache object */
	cache_object_p = all_object_p->i_cachelist;

	while ((cache_object_p != NULL) && (i++ < index)) {
		cache_object_p = cache_object_p->i_next;
	}

	dbug_leave("all_cachelist_at");
	return (cache_object_p);
}
Example #20
0
/*
 * ------------------------------------------------------------
 *			cfsd_all_create
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
cfsd_all_object_t *
cfsd_all_create(void)
{

	/* get the host name */
	struct utsname info;
	cfsd_all_object_t *all_object_p;
	int xx;
	char buffer[MAXPATHLEN];

	dbug_enter("cfsd_all_create");

	all_object_p =
	    (cfsd_all_object_t *)cfsd_calloc(sizeof (cfsd_all_object_t));

	xx = uname(&info);
	if (xx == -1) {
		dbug_print(("error", "cannot get host name"));
		strlcpy(all_object_p->i_machname, gettext("unknown"),
		    sizeof (all_object_p->i_machname));
	} else {
		strlcpy(all_object_p->i_machname, info.nodename,
		    sizeof (all_object_p->i_machname));
	}

	/* initialize the locking mutex */
	xx = mutex_init(&all_object_p->i_lock, USYNC_THREAD, NULL);
	dbug_assert(xx == 0);

	all_object_p->i_nextcacheid = 0;
	all_object_p->i_modify = 1;
	all_object_p->i_cachelist = NULL;
	all_object_p->i_cachecount = 0;

	/* all_object_p->i_hoardp = NULL; */

	snprintf(buffer, sizeof (buffer), gettext("host name is \"%s\""),
	    all_object_p->i_machname);
	dbug_print(("info", buffer));
	dbug_leave("cfsd_all_create");
	return (all_object_p);
}
Example #21
0
/*
 * ------------------------------------------------------------
 *			all_cachelist_find
 *
 * Description:
 * Arguments:
 *	namep
 * Returns:
 *	Returns ...
 * Preconditions:
 *	precond(namep)
 */
cfsd_cache_object_t *
all_cachelist_find(cfsd_all_object_t *all_object_p, const char *namep)
{
	cfsd_cache_object_t *cache_object_p;

	dbug_enter("all_cachelist_find");

	dbug_precond(namep);

	/* find the correct cache object */
	cache_object_p = all_object_p->i_cachelist;

	while ((cache_object_p != NULL) &&
		strcmp(namep, cache_object_p->i_cachedir)) {
		cache_object_p = cache_object_p->i_next;
	}

	dbug_leave("all_cachelist_find");
	return (cache_object_p);
}
Example #22
0
/*
 *			cfsd_logfile_create
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
cfsd_logfile_object_t *
cfsd_logfile_create(void)
{
	cfsd_logfile_object_t *logfile_object_p;

	dbug_enter("cfsd_logfile_create");

	logfile_object_p = cfsd_calloc(sizeof (cfsd_logfile_object_t));
	logfile_object_p->i_fid = -1;
	logfile_object_p->i_map_entry.i_pa = NULL;
	logfile_object_p->i_map_entry.i_paoff = 0;
	logfile_object_p->i_map_entry.i_paend = 0;
	logfile_object_p->i_map_entry.i_palen = 0;
	logfile_object_p->i_map_offset.i_pa = NULL;
	logfile_object_p->i_map_offset.i_paoff = 0;
	logfile_object_p->i_map_offset.i_paend = 0;
	logfile_object_p->i_map_offset.i_palen = 0;
	logfile_object_p->i_cur_offset = 0;
	logfile_object_p->i_cur_entry = NULL;
	dbug_leave("cfsd_logfile_create");
	return (logfile_object_p);
}
Example #23
0
/*
 * -----------------------------------------------------------------
 *			fscache_setup
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
fscache_setup(cfsd_fscache_object_t *fscache_object_p)
{
	char *tmp;
	char cfs_mnt_filename[MAXPATHLEN];
	FILE *fin;
	/*
	 * Line input buffer allows for type field (magic number size
	 * of 50 is historic), the field separator ": ", a large value
	 * (again historic) and a '\n' character.
	 */
	char type[50];
	char value[MAXPATHLEN * 4];
	char buf[sizeof (type) + 2 + sizeof (value) + 1];
	int err = 0;
	int xx;
	char *options[] = { "snr", "disconnectable", NULL };
	char *strp = buf;
	char *dummy;
	struct stat64 sinfo;
	time_t mtime;

	dbug_enter("fscache_setup");
	dbug_precond(fscache_object_p);

	fscache_object_p->i_modify++;
	fscache_object_p->i_disconnectable = 0;
	fscache_object_p->i_connected = 0;
	fscache_object_p->i_reconcile = 0;
	fscache_object_p->i_changes = 0;
	fscache_object_p->i_time_state = 0;
	fscache_object_p->i_time_mnt = 0;
	fscache_object_p->i_mntpt[0] = '\0';
	fscache_object_p->i_backfs[0] = '\0';
	fscache_object_p->i_backpath[0] = '\0';
	fscache_object_p->i_backfstype[0] = '\0';
	fscache_object_p->i_cfsopt[0] = '\0';
	fscache_object_p->i_bfsopt[0] = '\0';

	snprintf(cfs_mnt_filename, sizeof (cfs_mnt_filename), "%s/%s/%s",
	    fscache_object_p->i_cachepath, fscache_object_p->i_name,
	    CACHEFS_MNT_FILE);

	/* open for reading the file with the mount information */
	fin = fopen(cfs_mnt_filename, "r");
	if (fin == NULL) {
		dbug_print(("err", "could not open %s, %d", cfs_mnt_filename,
		    errno));
		dbug_leave("fscache_setup");
		return;
	}
	/* get the modify time of the mount file */
	if (fstat64(fileno(fin), &sinfo) == -1) {
		dbug_print(("err", "could not stat %s, %d", cfs_mnt_filename,
		    errno));
		if (fclose(fin))
			dbug_print(("err", "cannot close %s, %d",
			    cfs_mnt_filename, errno));
		dbug_leave("fscache_setup");
		return;
	}
	mtime = sinfo.st_mtime;

	/* read the mount information from the file */
	while (fgets(buf, sizeof (buf), fin) != NULL) {
		tmp = strtok(buf, ":");
		if (strlcpy(type, tmp, sizeof (type)) >= sizeof (type)) {
			/* Buffer Overflow */
			dbug_print(("err", "overflow in type field"
			    " of file %s", cfs_mnt_filename));
			if (fclose(fin))
				dbug_print(("err", "cannot close %s, %d",
				    cfs_mnt_filename, errno));
			dbug_leave("fscache_setup");
			return;
		}
		tmp = strtok(NULL, "\n");
		if (tmp != NULL && *tmp == ' ') {
			/*
			 * There is a valid value string so skip
			 * the space after the ":".
			 */
			tmp++;
			if (strlcpy(value, tmp, sizeof (value))
			    >= sizeof (value)) {
				/* Buffer Overflow */
				dbug_print(("err",
				    "overflow in value field"
				    " of file %s", cfs_mnt_filename));
				if (fclose(fin))
					dbug_print(("err",
					    "cannot close %s, %d",
					    cfs_mnt_filename, errno));
				dbug_leave("fscache_setup");
				return;
			}
		} else {
			value[0] = '\0';
		}
		dbug_print(("info", "\"%s\" \"%s\"", type, value));
		if (strcmp(type, "cachedir") == 0) {
			if (strcmp(fscache_object_p->i_cachepath, value) != 0) {
				err = 1;
				dbug_print(("err", "caches do not match %s, %s",
				    fscache_object_p->i_cachepath, buf));
			}
		} else if (strcmp(type, "mnt_point") == 0) {
			strlcpy(fscache_object_p->i_mntpt, value,
			    sizeof (fscache_object_p->i_mntpt));
		} else if (strcmp(type, "special") == 0) {
			strlcpy(fscache_object_p->i_backfs, value,
			    sizeof (fscache_object_p->i_backfs));
		} else if (strcmp(type, "backpath") == 0) {
			strlcpy(fscache_object_p->i_backpath, value,
			    sizeof (fscache_object_p->i_backpath));
		} else if (strcmp(type, "backfstype") == 0) {
			strlcpy(fscache_object_p->i_backfstype, value,
			    sizeof (fscache_object_p->i_backfstype));
		} else if (strcmp(type, "cacheid") == 0) {
			if (strcmp(fscache_object_p->i_name, value) != 0) {
				err = 1;
				dbug_print(("err", "ids do not match %s, %s",
				    fscache_object_p->i_name, value));
			}
		} else if (strcmp(type, "cachefs_options") == 0) {
			strlcpy(fscache_object_p->i_cfsopt, value,
			    sizeof (fscache_object_p->i_cfsopt));
		} else if (strcmp(type, "backfs_options") == 0) {
			strlcpy(fscache_object_p->i_bfsopt, value,
			    sizeof (fscache_object_p->i_bfsopt));
		} else if (strcmp(type, "mount_time") == 0) {
			continue;
		} else {
			dbug_print(("err", "unknown keyword \"%s\"", type));
			err = 1;
		}
	}
	if (fclose(fin))
		dbug_print(("err", "cannot close %s, %d",
		    cfs_mnt_filename, errno));

	/* see if this is a file system that is disconnectable */
	if ((err == 0) &&
		(fscache_object_p->i_backfs[0] &&
		fscache_object_p->i_cfsopt[0])) {
		strlcpy(buf, fscache_object_p->i_cfsopt, sizeof (buf));
		while (*strp != '\0') {
			xx = getsubopt(&strp, options, &dummy);
			if (xx != -1) {
				fscache_object_p->i_disconnectable = 1;
				break;
			}
		}
	}

	/*
	 * open up a fd on the sysmsg so we have a place to write
	 * log rolling errors
	 */
	if (fscache_object_p->i_disconnectable) {
		if (fscache_object_p->i_ofd < 0)
			fscache_object_p->i_ofd = open("/dev/sysmsg",
			    O_WRONLY);
		if (fscache_object_p->i_ofd < 0) {
			fprintf(stderr,
			    gettext("cachefsd: File system %s cannot be"
			    " disconnected.\n"),
			    fscache_object_p->i_mntpt);
			fprintf(stderr,
			    gettext("cachefsd: Cannot open /dev/sysmsg\n"));
			fscache_object_p->i_disconnectable = 0;
		}
	}

	/* see if the file system is mounted */
	snprintf(cfs_mnt_filename, sizeof (cfs_mnt_filename), "%s/%s/%s",
	    fscache_object_p->i_cachepath, fscache_object_p->i_name,
	    CACHEFS_UNMNT_FILE);
	if (stat64(cfs_mnt_filename, &sinfo) == 0) {
		fscache_object_p->i_mounted = 0;
		mtime = sinfo.st_mtime;
	} else
		fscache_object_p->i_mounted = 1;

	/* save the time of the last mount or unmount */
	fscache_object_p->i_time_mnt = mtime;

	dbug_print(("info", "disconnectable == %d, mounted == %d",
	    fscache_object_p->i_disconnectable,
	    fscache_object_p->i_mounted));
	dbug_leave("fscache_setup");
}
Example #24
0
/*
 *			fscache_addagain
 *
 * Description:
 * Arguments:
 *	lfp
 * Returns:
 *	Returns ...
 * Preconditions:
 *	precond(lfp)
 */
int
fscache_addagain(cfsd_fscache_object_t *fscache_object_p,
	cfsd_logfile_object_t *logfile_object_p,
	ulong_t nseq)
{
	int xx;
	cfs_dlog_entry_t *entp;
	off_t noffset;
	off_t prevoff = 0;
	off_t toff;

	dbug_enter("fscache_addagain");

	dbug_precond(fscache_object_p);
	dbug_precond(logfile_object_p);

	entp = logfile_object_p->i_cur_entry;

	noffset = logfile_object_p->i_cur_offset;

	dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED);
	dbug_assert(nseq);

	/* both set or both zero */
	dbug_assert((!fscache_object_p->i_again_seq ^
	    !fscache_object_p->i_again_offset) == 0);

	entp->dl_seq = nseq;
	/* simple case, first one on list */
	if ((fscache_object_p->i_again_seq == 0) ||
	    (nseq < fscache_object_p->i_again_seq)) {
		entp->dl_u.dl_modify.dl_next = fscache_object_p->i_again_offset;
		fscache_object_p->i_again_seq = nseq;
		fscache_object_p->i_again_offset = noffset;
		dbug_leave("fscache_addagain");
		return (0);
	}

	/* Search until we find the element on the list prior to the */
	/* insertion point. */
	for (toff = fscache_object_p->i_again_offset; toff != 0;
		toff = entp->dl_u.dl_modify.dl_next) {
		/* get pointer to next element on the list */
		xx = logfile_entry(logfile_object_p, toff, &entp);
		if (xx) {
			dbug_leave("fscache_addagain");
			return (xx);
		}
		dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED);

		/* done if we found the element after the insertion point */
		if (nseq < entp->dl_seq)
			break;
		prevoff = toff;
	}
	dbug_assert(prevoff);

	/* get pointer to element prior to the insertion point */
	xx = logfile_entry(logfile_object_p, prevoff, &entp);
	if (xx) {
		dbug_leave("fscache_addagain");
		return (xx);
	}
	dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED);
	dbug_assert(entp->dl_u.dl_modify.dl_next == toff);

	/* set element to point to our new element */
	entp->dl_u.dl_modify.dl_next = noffset;

	/* get pointer to our new element */
	xx = logfile_entry(logfile_object_p, noffset, &entp);
	if (xx) {
		dbug_leave("fscache_addagain");
		return (xx);
	}
	dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED);

	/* set it to point to next link or end of list */
	entp->dl_u.dl_modify.dl_next = toff;

	/* return success */
	dbug_leave("fscache_addagain");
	return (0);
}
Example #25
0
/*
 *			fscache_rollone
 *
 * Description:
 * Arguments:
 *	kmodp
 *	tblp
 *	lfp
 * Returns:
 *	Returns ...
 * Preconditions:
 *	precond(kmodp)
 *	precond(tblp)
 *	precond(lfp)
 */
int
fscache_rollone(cfsd_fscache_object_t *fscache_object_p,
	cfsd_kmod_object_t *kmod_object_p,
	cfsd_maptbl_object_t *maptbl_object_p,
	cfsd_logfile_object_t *logfile_object_p,
	ulong_t seq)
{
	cfsd_logelem_object_t *logelem_object_p = NULL;
	cfs_dlog_entry_t *entp;
	int xx;
	char *strp;

	dbug_enter("fscache_rollone");

	dbug_precond(fscache_object_p);
	dbug_precond(kmod_object_p);
	dbug_precond(maptbl_object_p);
	dbug_precond(logfile_object_p);

	entp = logfile_object_p->i_cur_entry;

	/* create an object for the appropriate log type */
	switch (entp->dl_op) {
	case CFS_DLOG_CREATE:
		dbug_print(("info", "create"));
		logelem_object_p = cfsd_logelem_create_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_REMOVE:
		dbug_print(("info", "remove"));
		logelem_object_p = cfsd_logelem_remove_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_LINK:
		dbug_print(("info", "link"));
		logelem_object_p = cfsd_logelem_link_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_RENAME:
		dbug_print(("info", "rename"));
		logelem_object_p = cfsd_logelem_rename_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_MKDIR:
		dbug_print(("info", "mkdir"));
		logelem_object_p = cfsd_logelem_mkdir_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_RMDIR:
		dbug_print(("info", "rmdir"));
		logelem_object_p = cfsd_logelem_rmdir_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_SYMLINK:
		dbug_print(("info", "symlink"));
		logelem_object_p = cfsd_logelem_symlink_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_SETATTR:
		dbug_print(("info", "setattr"));
		logelem_object_p = cfsd_logelem_setattr_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_SETSECATTR:
		dbug_print(("info", "setsecattr"));
		logelem_object_p = cfsd_logelem_setsecattr_create(
		    maptbl_object_p, logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_MODIFIED:
		dbug_print(("info", "modified"));
		logelem_object_p = cfsd_logelem_modified_create(maptbl_object_p,
		    logfile_object_p, kmod_object_p);
		break;

	case CFS_DLOG_MAPFID:
		dbug_print(("info", "mapfid"));
		break;

	case CFS_DLOG_TRAILER:
		dbug_print(("info", "trailer"));
		break;

	default:
		dbug_assert(0);
		dbug_leave("fscache_rollone");
		return (EIO);
	}

	/* do not bother if ignoring the record */
	if (logelem_object_p == NULL) {
		dbug_print(("info", "record ignored"));
		dbug_leave("fscache_rollone");
		return (0);
	}

	/* XXX debugging */
	logelem_dump(logelem_object_p);

	/* roll the entry */
	xx = logelem_roll(logelem_object_p, &seq);

	strp = logelem_object_p->i_messagep;
	if (strp) {
		write(fscache_object_p->i_ofd, strp, strlen(strp));
		dbug_print(("conflict", "%s", strp));
	}

	if (xx == EAGAIN) {
		dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED);
		xx = fscache_addagain(fscache_object_p, logfile_object_p, seq);
		if (xx == 0)
			xx = EAGAIN;
	}

	/* destroy the object */
	cfsd_logelem_destroy(logelem_object_p);

	dbug_leave("fscache_rollone");
	return (xx);
}
Example #26
0
/*
 * -----------------------------------------------------------------
 *			fscache_process
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
fscache_process(cfsd_fscache_object_t *fscache_object_p)
{
	int xx;
	int changes;
	cfsd_kmod_object_t *kmod_object_p;
	int setup = 1;
	int state;

	dbug_enter("fscache_process");
	dbug_precond(fscache_object_p);

	kmod_object_p = cfsd_kmod_create();
	for (;;) {
		fscache_lock(fscache_object_p);
		fscache_object_p->i_time_state = time(NULL);
		fscache_object_p->i_modify++;

		/* if we should try to unmount the file system */
		if (fscache_object_p->i_tryunmount) {
			/* shut down the interface to the kmod */
			if (setup == 0) {
				kmod_shutdown(kmod_object_p);
				setup = 1;
			}

			/* try to unmount the file system */
			if (umount(fscache_object_p->i_mntpt) == -1) {
				xx = errno;
				dbug_print(("info", "unmount failed %s",
				    strerror(xx)));
			} else {
				fscache_object_p->i_mounted = 0;
			}

			/* wake up thread blocked in fscache_unmount */
			fscache_object_p->i_tryunmount = 0;
			xx = cond_broadcast(&fscache_object_p->i_cvwait);
			dbug_assert(xx == 0);

			/* all done if unmount succeeded */
			if (fscache_object_p->i_mounted == 0) {
				fscache_unlock(fscache_object_p);
				break;
			}
		}

		if (setup) {
			setup = 0;
			/*
			 * make an interface into the cachefs kmod for
			 * this fs
			 */
			xx = kmod_setup(kmod_object_p,
			    fscache_object_p->i_mntpt);
			if (xx != 0) {
				dbug_print(("err",
				    "setup of kmod interface failed %d", xx));
				fscache_object_p->i_disconnectable = 0;
				fscache_object_p->i_modify++;
				fscache_unlock(fscache_object_p);
				break;
			}

			/* verify that we got the file system we expected XXX */
		}

		/* get the current state of the file system */
		state = kmod_stateget(kmod_object_p);

		if (fscache_object_p->i_simdis && (state == CFS_FS_CONNECTED)) {
			dbug_print(("simdis", "simulating disconnection on %s",
			    fscache_object_p->i_mntpt));
			xx = kmod_stateset(kmod_object_p, CFS_FS_DISCONNECTED);
			dbug_assert(xx == 0);
			state = kmod_stateget(kmod_object_p);
			dbug_assert(state == CFS_FS_DISCONNECTED);
		}
		fscache_unlock(fscache_object_p);

		switch (state) {
		case CFS_FS_CONNECTED:
			fscache_lock(fscache_object_p);
			fscache_object_p->i_connected = 1;
			fscache_object_p->i_reconcile = 0;
			fscache_object_p->i_modify++;
			fscache_unlock(fscache_object_p);

			/* wait for fs to switch to disconnecting */
			dbug_print(("info", "about to xwait"));
			xx = kmod_xwait(kmod_object_p);
			if (xx == EINTR) {
				dbug_print(("info", "a. EINTR from xwait"));
				continue;
			}
			dbug_assert(xx == 0);
			state = kmod_stateget(kmod_object_p);
			dbug_assert(state == CFS_FS_DISCONNECTED);
			break;

		case CFS_FS_DISCONNECTED:
			fscache_lock(fscache_object_p);
			fscache_object_p->i_connected = 0;
			fscache_object_p->i_reconcile = 0;
			fscache_object_p->i_modify++;
			fscache_unlock(fscache_object_p);

			/* wait until we are reconnected */
			fscache_server_alive(fscache_object_p, kmod_object_p);
			if (fscache_object_p->i_tryunmount)
				continue;

			/* switch to reconnecting mode */
			xx = kmod_stateset(kmod_object_p, CFS_FS_RECONNECTING);
			dbug_assert(xx == 0);
			break;

		case CFS_FS_RECONNECTING:
			fscache_lock(fscache_object_p);
			fscache_object_p->i_connected = 1;
			fscache_object_p->i_reconcile = 1;
			fscache_object_p->i_modify++;
			changes = fscache_object_p->i_changes;
			fscache_unlock(fscache_object_p);

			/* roll the log */
			xx = fscache_roll(fscache_object_p, kmod_object_p);
			if (xx) {
				dbug_assert(xx == ETIMEDOUT);
				/* switch to disconnected */
				xx = kmod_stateset(kmod_object_p,
				    CFS_FS_DISCONNECTED);
				dbug_assert(xx == 0);
			} else {
				/* switch to connected */
				xx = kmod_stateset(kmod_object_p,
				    CFS_FS_CONNECTED);
				dbug_assert(xx == 0);
				changes = 0;
			}

			fscache_lock(fscache_object_p);
			fscache_object_p->i_reconcile = 0;
			fscache_changes(fscache_object_p, changes);
			fscache_object_p->i_modify++;
			fscache_unlock(fscache_object_p);

			break;

		default:
			dbug_assert(0);
			break;
		}
	}
	cfsd_kmod_destroy(kmod_object_p);
	dbug_leave("fscache_process");
}
Example #27
0
/*
 *			fscache_simdisconnect
 *
 * Description:
 *	Simulates disconnection or reconnects from a simulated disconnection.
 * Arguments:
 *	disconnect	1 means disconnect, !1 means connect
 * Returns:
 *	Returns 0 for success, !0 on an error
 * Preconditions:
 */
int
fscache_simdisconnect(cfsd_fscache_object_t *fscache_object_p, int disconnect)
{

	int xx;
	int ret = 0;
	char *strp;
	int tcon;
	int trec;

	dbug_enter("fscache_simdisconnect");
	dbug_precond(fscache_object_p);

	strp = disconnect ? "disconnection" : "reconnection";

	dbug_print(("simdis", "About to simulate %s", strp));

	fscache_lock(fscache_object_p);

	if (disconnect) {
		/* if file system cannot be disconnected */
		if (fscache_object_p->i_disconnectable == 0) {
			ret = 1;
			goto out;
		}

		/* if file system is already disconnected */
		if (fscache_object_p->i_connected == 0) {
			ret = 2;
			goto out;
		}
		fscache_object_p->i_simdis = 1;
	} else {
		/* if file system is already connected */
		if (fscache_object_p->i_connected) {
			ret = 1;
			goto out;
		}

		/* if file system is not "simulated" disconnected */
		if (fscache_object_p->i_simdis == 0) {
			ret = 2;
			goto out;
		}
		fscache_object_p->i_simdis = 0;
	}

	/* if fs thread not running */
	if (fscache_object_p->i_threaded == 0) {
		if (fscache_object_p->i_mounted) {
			dbug_print(("simdis", "thread not running"));
			ret = -1;
		} else {
			if (fscache_object_p->i_simdis)
				fscache_object_p->i_connected = 0;
			else
				fscache_object_p->i_connected = 1;
		}
		goto out;
	}

	/* get the attention of the thread */
	dbug_print(("info", "thread %d, killing %d with sigusr1",
	    thr_self(), fscache_object_p->i_threadid));
	xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1);
	if (xx) {
		dbug_print(("simdis", "thr_kill failed %d, threadid %d",
		    xx, fscache_object_p->i_threadid));
		ret = -1;
	}

out:
	fscache_unlock(fscache_object_p);

	if (ret == 0) {
		for (;;) {
			dbug_print(("simdis", "     waiting for simulated %s",
			    strp));
			fscache_lock(fscache_object_p);
			tcon = fscache_object_p->i_connected;
			trec = fscache_object_p->i_reconcile;
			fscache_unlock(fscache_object_p);
			if (disconnect) {
				if (tcon == 0)
					break;
			} else {
				if ((tcon == 1) && (trec == 0))
					break;
			}
			cfsd_sleep(1);
		}
		dbug_print(("simdis", "DONE waiting for simulated %s", strp));
	} else {
		dbug_print(("simdis", "simulated %s failed %d", strp, ret));
	}

	dbug_leave("fscache_simdisconnect");
	return (ret);
}
Example #28
0
/*
 *			fscache_roll
 *
 * Description:
 *	Rolls the contents of the log to the server.
 * Arguments:
 *	kmodp	interface to kernel functions
 * Returns:
 *	Returns 0 for success or ETIMEDOUT if a timeout error occurred.
 * Preconditions:
 *	precond(kmodp)
 */
int
fscache_roll(cfsd_fscache_object_t *fscache_object_p,
	cfsd_kmod_object_t *kmod_object_p)
{
	int error = 0;
	cfsd_logelem_object_t *logelem_object_p;
	char namebuf[MAXPATHLEN];
	char backupfile[MAXPATHLEN];
	int xx;
	cfs_dlog_entry_t *entp;
	off_t next_offset;
	ulong_t curseq = 0;
	int eof = 0;
	char *xp;
	cfsd_logfile_object_t *logfile_object_p;
	cfsd_maptbl_object_t *maptbl_object_p;

	dbug_enter("fscache_roll");

	dbug_precond(fscache_object_p);
	dbug_precond(kmod_object_p);

	/* map in the log file */
	logfile_object_p = cfsd_logfile_create();

	snprintf(namebuf, sizeof (namebuf), "%s/%s/%s",
	    fscache_object_p->i_cachepath, fscache_object_p->i_name,
	    CACHEFS_DLOG_FILE);
	xx = logfile_setup(logfile_object_p, namebuf, CFS_DLOG_ENTRY_MAXSIZE);
	if (xx) {
		if (xx == ENOENT) {
			cfsd_logfile_destroy(logfile_object_p);
			dbug_leave("fscache_roll");
			return (0);
		}
		fscache_fsproblem(fscache_object_p, kmod_object_p);
		cfsd_logfile_destroy(logfile_object_p);
		dbug_leave("fscache_roll");
		return (0);
	}

	fscache_lock(fscache_object_p);
	fscache_changes(fscache_object_p, 1);
	fscache_unlock(fscache_object_p);

	/* create a hashed mapping table for changes to cids */
	maptbl_object_p = cfsd_maptbl_create();
	snprintf(namebuf, sizeof (namebuf), "%s/%s/%s",
	    fscache_object_p->i_cachepath, fscache_object_p->i_name,
	    CACHEFS_DMAP_FILE);
	xx = maptbl_setup(maptbl_object_p, namebuf);
	if (xx) {
		fscache_fsproblem(fscache_object_p, kmod_object_p);
		cfsd_logfile_destroy(logfile_object_p);
		cfsd_maptbl_destroy(maptbl_object_p);
		dbug_leave("fscache_roll");
		return (0);
	}

	/*
	 * lock is not needed because they are only used when
	 * rolling the log by fscache_roll and fscache_addagain
	 */
	fscache_object_p->i_again_offset = 0;
	fscache_object_p->i_again_seq = 0;

	/* Pass 1: collect all cid to fid mappings */
	next_offset = LOGFILE_ENTRY_START;
	for (;;) {
		/* get a pointer to the next record */
		xx = logfile_entry(logfile_object_p, next_offset, &entp);
		if (xx == 1)
			break;
		if (xx == -1) {
			fscache_fsproblem(fscache_object_p, kmod_object_p);
			cfsd_logfile_destroy(logfile_object_p);
			cfsd_maptbl_destroy(maptbl_object_p);
			dbug_leave("fscache_roll");
			return (0);
		}
		next_offset += entp->dl_len;

		/* skip record if not valid */
		if (entp->dl_valid != CFS_DLOG_VAL_COMMITTED)
			continue;

		/* create an object for the appropriate log type */
		logelem_object_p = NULL;
		switch (entp->dl_op) {
		case CFS_DLOG_CREATE:
		case CFS_DLOG_REMOVE:
		case CFS_DLOG_LINK:
		case CFS_DLOG_RENAME:
		case CFS_DLOG_MKDIR:
		case CFS_DLOG_RMDIR:
		case CFS_DLOG_SYMLINK:
		case CFS_DLOG_SETATTR:
		case CFS_DLOG_SETSECATTR:
		case CFS_DLOG_MODIFIED:
		case CFS_DLOG_TRAILER:
			break;

		case CFS_DLOG_MAPFID:
			dbug_print(("info", "mapfid"));
			logelem_object_p = cfsd_logelem_mapfid_create(
			    maptbl_object_p, logfile_object_p,
			    kmod_object_p);
			break;

		default:
			dbug_assert(0);
			fscache_fsproblem(fscache_object_p, kmod_object_p);
			break;
		}

		/* do not bother if ignoring the record */
		if (logelem_object_p == NULL)
			continue;

		/* debuggging */
		logelem_dump(logelem_object_p);

		/* roll the entry */
		xx = logelem_roll(logelem_object_p, (ulong_t *)NULL);
		if (xx) {
			fscache_fsproblem(fscache_object_p, kmod_object_p);
			cfsd_logelem_destroy(logelem_object_p);
			cfsd_maptbl_destroy(maptbl_object_p);
			cfsd_logfile_destroy(logfile_object_p);
			dbug_leave("fscache_roll");
			return (0);
		}

		/* mark record as completed */
		entp->dl_valid = CFS_DLOG_VAL_PROCESSED;
		xx = logfile_sync(logfile_object_p);
		if (xx) {
			fscache_fsproblem(fscache_object_p, kmod_object_p);
			cfsd_logelem_destroy(logelem_object_p);
			cfsd_maptbl_destroy(maptbl_object_p);
			cfsd_logfile_destroy(logfile_object_p);
			dbug_leave("fscache_roll");
			return (0);
		}

		/* destroy the object */
		cfsd_logelem_destroy(logelem_object_p);
	}

	/* Pass 2: modify the back file system */
	next_offset = LOGFILE_ENTRY_START;
	for (;;) {
		/* if we need the seq number of a deferred modify */
		if (fscache_object_p->i_again_offset &&
			(fscache_object_p->i_again_seq == 0)) {

			/* get a pointer to the next record */
			xx = logfile_entry(logfile_object_p,
			    fscache_object_p->i_again_offset, &entp);
			if (xx == 1)
				break;
			if (xx == -1) {
				fscache_fsproblem(fscache_object_p,
					kmod_object_p);
				cfsd_logfile_destroy(logfile_object_p);
				cfsd_maptbl_destroy(maptbl_object_p);
				dbug_leave("fscache_roll");
				return (0);
			}
			dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED);
			fscache_object_p->i_again_seq = entp->dl_seq;
			dbug_assert(fscache_object_p->i_again_seq != 0);
		}

		/* get a pointer to the next record to process */
		if (!eof) {
			xx = logfile_entry(logfile_object_p, next_offset,
			    &entp);
			if (xx == 1) {
				eof = 1;
				curseq = ULONG_MAX;
			} else if (xx) {
				break;
			} else {
				curseq = entp->dl_seq;
			}
		}

		/* if its time to process a deferred modify entry */
		if (fscache_object_p->i_again_seq &&
		    (eof || (fscache_object_p->i_again_seq < entp->dl_seq))) {
			xx = logfile_entry(logfile_object_p,
			    fscache_object_p->i_again_offset, &entp);
			if (xx)
				break;
			dbug_assert(entp->dl_op == CFS_DLOG_MODIFIED);
			curseq = entp->dl_seq;
			fscache_object_p->i_again_offset =
			    entp->dl_u.dl_modify.dl_next;
			fscache_object_p->i_again_seq = 0;
			entp->dl_u.dl_modify.dl_next = -1;
		} else if (eof) {
			xx = 0;
			break;
		}

		/* else move the offset to the next record */
		else {
			next_offset += entp->dl_len;
		}

		/* skip record if not valid */
		if (entp->dl_valid != CFS_DLOG_VAL_COMMITTED)
			continue;

		/* process the record */
		xx = fscache_rollone(fscache_object_p, kmod_object_p,
		    maptbl_object_p, logfile_object_p, curseq);
		if (xx == ETIMEDOUT) {
			/* timeout error, back to disconnected */
			cfsd_maptbl_destroy(maptbl_object_p);
			cfsd_logfile_destroy(logfile_object_p);
			dbug_print(("info", "timeout error occurred"));
			dbug_leave("fscache_roll");
			return (xx);
		} else if (xx == EIO) {
			break;
		} else if (xx == EAGAIN) {
			continue;
		} else if (xx) {
			/* should never happen */
			dbug_assert(0);
			break;
		} else {
			/* mark record as completed */
			entp->dl_valid = CFS_DLOG_VAL_PROCESSED;
			xx = logfile_sync(logfile_object_p);
			if (xx)
				break;
		}
	}

	/* if an unrecoverable error occurred */
	if (xx) {
		dbug_print(("error", "error processing log file"));
		fscache_fsproblem(fscache_object_p, kmod_object_p);
	}

	/* dump stats about the hash table */
	maptbl_dumpstats(maptbl_object_p);

	/* dump stats about the log file */
	logfile_dumpstats(logfile_object_p);

	/* debugging hack, rename the log files */

	if (snprintf(namebuf, sizeof (namebuf), "%s/%s/%s",
	    fscache_object_p->i_cachepath, fscache_object_p->i_name,
	    CACHEFS_DLOG_FILE) > ((sizeof (backupfile)) - (sizeof (".bak")))) {
		dbug_print(("error", "unable to create backup dlog_file "
		    "for %s, path name is too long", namebuf));
	} else {
		/*
		 * No need to check return value from snprintf() as
		 * the previous check should suffice.
		 */
		snprintf(backupfile, sizeof (backupfile), "%s.bak", namebuf);
		if (rename(namebuf, backupfile) == -1) {
			dbug_print(("error",
			    "unable to create backup dlog_file"));
		}
	}

	if (snprintf(namebuf, sizeof (namebuf), "%s/%s/%s",
	    fscache_object_p->i_cachepath, fscache_object_p->i_name,
	    CACHEFS_DMAP_FILE) > ((sizeof (backupfile)) - (sizeof (".bak")))) {
		dbug_print(("error", "unable to create backup dmap_file "
		    "for %s, path name is too long", namebuf));
	} else {
		/*
		 * No need to check return value from snprintf() as
		 * the previous check should suffice.
		 */
		snprintf(backupfile, sizeof (backupfile), "%s.bak", namebuf);
		if (rename(namebuf, backupfile) == -1) {
			dbug_print(("error",
			    "unable to create backup dmap_file"));
		}
	}

	/* delete the log file */
	/* XXX */

	cfsd_maptbl_destroy(maptbl_object_p);
	cfsd_logfile_destroy(logfile_object_p);
	dbug_leave("fscache_roll");
	return (error);
}
Example #29
0
int
fscache_unmount(cfsd_fscache_object_t *fscache_object_p, int flag)
{
	int xx;
	int ret = 0;

	dbug_enter("fscache_unmount");
	dbug_precond(fscache_object_p);

	fscache_lock(fscache_object_p);

	/* if there is a thread running */
	if (fscache_object_p->i_threaded) {
		/* do not bother unmounting if rolling the log */
		if (fscache_object_p->i_reconcile) {
			ret = EBUSY;
			goto out;
		}

		/* inform the thread to try the unmount */
		fscache_object_p->i_tryunmount = 1;
		fscache_object_p->i_modify++;

		/* get the attention of the thread */
		dbug_print(("info", "about to do umount kill"));
		xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1);
		if (xx) {
			dbug_print(("error", "thr_kill failed %d, threadid %d",
			    xx, fscache_object_p->i_threadid));
			ret = EIO;
			goto out;
		}

		/* wait for the thread to wake us up */
		while (fscache_object_p->i_tryunmount) {
			xx = cond_wait(&fscache_object_p->i_cvwait,
			    &fscache_object_p->i_lock);
			dbug_print(("info", "cond_wait woke up %d %d",
			    xx, fscache_object_p->i_tryunmount));
		}

		/* if the file system is still mounted */
		if (fscache_object_p->i_mounted)
			ret = EBUSY;
	}

	/* else if there is no thread running */
	else {
		/* try to unmount the file system */
		if (umount2(fscache_object_p->i_mntpt, flag) == -1) {
			xx = errno;
			dbug_print(("info", "unmount failed %s",
			    strerror(xx)));
			if (xx == EBUSY)
				ret = EBUSY;
			else if (xx == ENOTSUP)
				ret = ENOTSUP;
			else
				ret = EIO;
		} else {
			fscache_object_p->i_mounted = 0;
			fscache_object_p->i_modify++;
		}
	}
out:
	fscache_unlock(fscache_object_p);
	dbug_leave("fscache_unmount");
	return (ret);
}
Example #30
0
/*
 * -----------------------------------------------------------------
 *			fscache_server_alive
 *
 * Description:
 * Arguments:
 * Returns:
 * Preconditions:
 */
void
fscache_server_alive(cfsd_fscache_object_t *fscache_object_p,
	cfsd_kmod_object_t *kmod_object_p)
{

	int xx;
	cfs_fid_t rootfid;
	dl_cred_t cr;
	cfs_vattr_t va;
	char cfsopt[CFS_MAXMNTOPTLEN];
	int child_pid;
	int stat_loc;

	dbug_enter("fscache_server_alive");

	dbug_precond(fscache_object_p);
	dbug_precond(kmod_object_p);

	for (;;) {
		/* wait for a little while */
		if (fscache_object_p->i_simdis == 0)
			cfsd_sleep(30);
		/* if simulating disconnect */
		fscache_lock(fscache_object_p);
		while (fscache_object_p->i_simdis &&
			!fscache_object_p->i_tryunmount) {
			dbug_print(("simdis", "before calling cond_wait"));
			xx = cond_wait(&fscache_object_p->i_cvwait,
			    &fscache_object_p->i_lock);
			dbug_print(("simdis", "cond_wait woke up %d %d",
			    xx, fscache_object_p->i_simdis));
		}
		fscache_unlock(fscache_object_p);

		if (fscache_object_p->i_tryunmount)
			break;

		/* see if the server is alive */
		if (fscache_pingserver(fscache_object_p) == -1) {
			/* dead server */
			continue;
		}

		/* try to mount the back file system if needed */
		if (fscache_object_p->i_backpath[0] == '\0') {
			dbug_precond(fscache_object_p->i_cfsopt[0]);
			dbug_precond(fscache_object_p->i_backfs[0]);
			dbug_precond(fscache_object_p->i_mntpt[0]);

			snprintf(cfsopt, sizeof (cfsopt), "%s,slide,remount",
			    fscache_object_p->i_cfsopt);
			/*
			 * Mounting of a cachefs file system is done by calling
			 * out to /usr/lib/fs/cachefs/mount so that mounts
			 * done by the user, autofs and by us here in cachefsd
			 * are consistent.
			 */
			switch ((child_pid = fork1())) {
			case -1:
				/*
				 * The original code used system()
				 * but never checked for an error
				 * occurring. The rest of the code
				 * would suggest that "continue" is
				 * the correct thing to do.
				 */
				dbug_print(("info", "unable to fork mount "
				    "process for back fs %s %d",
				    fscache_object_p->i_backfs, errno));
				continue;
			case 0:
				(void) setsid();
				execl("/usr/sbin/mount", "mount", "-F",
				    "cachefs", "-o", cfsopt,
				    fscache_object_p->i_backfs,
				    fscache_object_p->i_mntpt, NULL);
				break;
			default:
				(void) waitpid(child_pid, &stat_loc, WUNTRACED);
			}

		}

		/* get the root fid of the file system */
		xx = kmod_rootfid(kmod_object_p, &rootfid);
		if (xx) {
			dbug_print(("info", "could not mount back fs %s %d",
			    fscache_object_p->i_backfs, xx));
			continue;
		}

		/* dummy up a fake kcred */
		(void) memset(&cr, 0, sizeof (cr));

		/* try to get attrs on the root */
		xx = kmod_getattrfid(kmod_object_p, &rootfid, &cr, &va);
		if ((xx == ETIMEDOUT) || (xx == EIO)) {
			dbug_print(("info", "Bogus error %d", xx));
			continue;
		}
		break;
	}
	dbug_leave("fscache_server_alive");
}