예제 #1
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");
}
예제 #2
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);
}