Ejemplo n.º 1
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");
}
Ejemplo n.º 2
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");
}
Ejemplo n.º 3
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");
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
struct hostent *my_gethostbyname_r(const char *name,
				   struct hostent *result, char *buffer,
				   int buflen, int *h_errnop)
{
  struct hostent *hp;
  dbug_assert(buflen >= sizeof(struct hostent_data));
  hp= gethostbyname_r(name,result,(struct hostent_data *) buffer);
  *h_errnop= errno;
  return hp;
}
Ejemplo n.º 7
0
struct hostent *my_gethostbyname_r(const char *name,
				   struct hostent *result, char *buffer,
				   int buflen, int *h_errnop)
{
  struct hostent *hp;
  dbug_assert((size_t) buflen >= sizeof(*result));
  if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop))
    return 0;
  return hp;
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
struct hostent *my_gethostbyname_r(const char *name,
				   struct hostent *result, char *buffer,
				   int buflen, int *h_errnop)
{
  dbug_assert(buflen >= sizeof(struct hostent_data));
  if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1)
  {
    *h_errnop= errno;
    return 0;
  }
  return result;
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
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);
}
Ejemplo n.º 12
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);
}
Ejemplo n.º 13
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");
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
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);
}