Alien-Libjio

 view release on metacpan or  search on metacpan

libjio/libjio/journal.c  view on Meta::CPAN

	if (rv == 0)
		goto exit;

	/* write to the file descriptor */
	*(fs->jmap) = rv;

exit:
	plockf(fs->jfd, F_UNLOCK, 0, 0);
	return rv;
}

/** Free a transaction id */
static void free_tid(struct jfs *fs, unsigned int tid)
{
	unsigned int curid, i;
	char name[PATH_MAX];

	/* lock the whole file */
	plockf(fs->jfd, F_LOCKW, 0, 0);

	/* read the current max. curid */
	curid = *(fs->jmap);

	/* if we're the max tid, scan the directory looking up for the new
	 * max; the detailed description can be found in the "doc/" dir */
	if (tid == curid) {
		/* look up the new max. */
		for (i = curid - 1; i > 0; i--) {
			get_jtfile(fs, i, name);
			if (access(name, R_OK | W_OK) == 0) {
				break;
			} else if (errno != EACCES) {
				/* Real error, stop looking for a new max. It
				 * doesn't hurt us because it's ok if the max
				 * is higher than it could be */
				break;
			}
		}

		/* and save it */
		*(fs->jmap) = i;
	}

	plockf(fs->jfd, F_UNLOCK, 0, 0);
	return;
}


static int already_warned_about_sync = 0;

/** fsync() a directory */
static int fsync_dir(int fd)
{
	int rv;

	rv = fsync(fd);

	if (rv != 0 && (errno == EINVAL || errno == EBADF)) {
		/* it seems to be legal that fsync() on directories is not
		 * implemented, so if this fails with EINVAL or EBADF, just
		 * call a global sync(); which is awful (and might still
		 * return before metadata is done) but it seems to be the
		 * saner choice; otherwise we just fail */
		sync();
		rv = 0;

		if (!already_warned_about_sync) {
			fprintf(stderr, "libjio warning: falling back on " \
					"sync() for directory syncing\n");
			already_warned_about_sync = 1;
		}
	}

	return rv;
}

/** Corrupt a journal file. Used as a last resource to prevent an applied
 * transaction file laying around */
static int corrupt_journal_file(struct journal_op *jop)
{
	off_t pos;
	struct on_disk_trailer trailer;

	/* We set the number of operations to 0, and the checksum to
	 * 0xffffffff, so there is no chance it's considered valid after a new
	 * transaction overwrites this one */
	trailer.numops = 0;
	trailer.checksum = 0xffffffff;

	pos = lseek(jop->fd, 0, SEEK_END);
	if (pos == (off_t) -1)
		return -1;

	if (pwrite(jop->fd, (void *) &trailer, sizeof(trailer), pos)
			!= sizeof(trailer))
		return -1;

	if (fdatasync(jop->fd) != 0)
		return -1;

	return 0;
}

/** Mark the journal as broken. To do so, we just create a file named "broken"
 * inside the journal directory. Used internally to mark severe journal errors
 * that should prevent further journal use to avoid potential corruption, like
 * failures to remove transaction files. The mark is removed by jfsck(). */
static int mark_broken(struct jfs *fs)
{
	char broken_path[PATH_MAX];
	int fd;

	snprintf(broken_path, PATH_MAX, "%s/broken", fs->jdir);
	fd = creat(broken_path, 0600);
	close(fd);

	return fd >= 0;
}

/** Check if the journal is broken */
static int is_broken(struct jfs *fs)



( run in 0.570 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )