Beispiel #1
0
int journal_close(journal_t *journal)
{
	/* Check journal. */
	if (journal == NULL) {
		return KNOT_EINVAL;
	}

	/* Check if lazy. */
	int ret = KNOT_EOK;
	if (journal->fd < 0) {
		free(journal->path);
	} else {
		/* Recalculate CRC. */
		ret = journal_update_crc(journal->fd);

		/* Unlock journal file. */
		journal->fl.l_type = F_UNLCK;
		fcntl(journal->fd, F_SETLK, &journal->fl);
		dbg_journal("journal: unlocked journal %p\n", journal);

		/* Close file. */
		close(journal->fd);
	}

	dbg_journal("journal: closed journal %p\n", journal);

	/* Free allocated resources. */
	free(journal);

	return ret;
}
Beispiel #2
0
/*! \brief Close journal file. */
static int journal_close_file(journal_t *journal)
{
	/* Check journal. */
	if (journal == NULL) {
		return KNOT_EINVAL;
	}

	/* Recalculate CRC. */
	int ret = journal_update_crc(journal->fd);

	/* Close file. */
	close(journal->fd);
	journal->fd = -1;

	/* Free nodes. */
	free(journal->nodes);
	journal->nodes = NULL;

	dbg_journal("journal: closed journal %p\n", journal);

	return ret;
}
Beispiel #3
0
int journal_create(const char *fn, uint16_t max_nodes)
{
	if (fn == NULL) {
		return KNOT_EINVAL;
	}

	/* File lock. */
	struct flock fl;
	memset(&fl, 0, sizeof(struct flock));
	fl.l_type = F_WRLCK;
	fl.l_whence = SEEK_SET;
	fl.l_start = 0;
	fl.l_len = 0;
	fl.l_pid = getpid();

	/* Create journal file. */
	int fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	if (fd < 0) {
		dbg_journal("journal: failed to create file '%s'\n", fn);
		return knot_map_errno(errno);
	}

	/* Lock. */
	fcntl(fd, F_SETLKW, &fl);
	fl.l_type  = F_UNLCK;

	/* Create journal header. */
	dbg_journal("journal: creating header\n");
	const char magic[MAGIC_LENGTH] = JOURNAL_MAGIC;
	if (!sfwrite(magic, MAGIC_LENGTH, fd)) {
		fcntl(fd, F_SETLK, &fl);
		close(fd);
		remove(fn);
		return KNOT_ERROR;
	}
	crc_t crc = crc_init();
	if (!sfwrite(&crc, sizeof(crc_t), fd)) {
		fcntl(fd, F_SETLK, &fl);
		close(fd);
		remove(fn);
		return KNOT_ERROR;
	}
	if (!sfwrite(&max_nodes, sizeof(uint16_t), fd)) {
		fcntl(fd, F_SETLK, &fl);
		close(fd);
		remove(fn);
		return KNOT_ERROR;
	}

	/* Create node queue head + tail.
	 * qhead points to least recent node
	 * qtail points to next free node
	 * qhead == qtail means empty queue
	 */
	uint16_t zval = 0;
	if (!sfwrite(&zval, sizeof(uint16_t), fd)) {
		fcntl(fd, F_SETLK, &fl);
		close(fd);
		remove(fn);
		return KNOT_ERROR;
	}

	if (!sfwrite(&zval, sizeof(uint16_t), fd)) {
		fcntl(fd, F_SETLK, &fl);
		close(fd);
		remove(fn);
		return KNOT_ERROR;
	}

	dbg_journal_verb("journal: creating free segment descriptor\n");

	/* Create free segment descriptor. */
	journal_node_t jn;
	memset(&jn, 0, sizeof(journal_node_t));
	jn.id = 0;
	jn.flags = JOURNAL_VALID;
	jn.pos = JOURNAL_HSIZE + (max_nodes + 1) * sizeof(journal_node_t);
	jn.len = 0;
	if (!sfwrite(&jn, sizeof(journal_node_t), fd)) {
		fcntl(fd, F_SETLK, &fl);
		close(fd);
		remove(fn);
		return KNOT_ERROR;
	}

	/* Create nodes. */
	dbg_journal("journal: creating node table, size=%u\n", max_nodes);
	memset(&jn, 0, sizeof(journal_node_t));
	for(uint16_t i = 0; i < max_nodes; ++i) {
		if (!sfwrite(&jn, sizeof(journal_node_t), fd)) {
			fcntl(fd, F_SETLK, &fl);
			close(fd);
			if (remove(fn) < 0) {
				dbg_journal("journal: failed to remove journal file after error\n");
			}
			return KNOT_ERROR;
		}
	}

	/* Recalculate CRC. */
	if (journal_update_crc(fd) != KNOT_EOK) {
		fcntl(fd, F_SETLK, &fl);
		close(fd);
		if(remove(fn) < 0) {
			dbg_journal("journal: failed to remove journal file after error\n");
		}
		return KNOT_ERROR;
	}

	/* Unlock and close. */
	fcntl(fd, F_SETLK, &fl);
	close(fd);

	/* Journal file created. */
	dbg_journal("journal: file '%s' initialized\n", fn);
	return KNOT_EOK;
}