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 )