<commit_before>/* $Id$ */
/*
 * %PSC_START_COPYRIGHT%
 * -----------------------------------------------------------------------------
 * Copyright (c) 2007-2011, Pittsburgh Supercomputing Center (PSC).
 *
 * Permission to use, copy, and modify this software and its documentation
 * without fee for personal use or non-commercial use within your organization
 * is hereby granted, provided that the above copyright notice is preserved in
 * all copies and that the copyright and this permission notice appear in
 * supporting documentation.  Permission to redistribute this software to other
 * organizations or individuals is not permitted without the written permission
 * of the Pittsburgh Supercomputing Center.  PSC makes no representations about
 * the suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 * -----------------------------------------------------------------------------
 * %PSC_END_COPYRIGHT%
 */

#include <sys/types.h>
#include <sys/stat.h>

#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>

#include "pfl/fcntl.h"
#include "pfl/time.h"
#include "pfl/types.h"
#include "psc_ds/dynarray.h"
#include "psc_util/alloc.h"
#include "psc_util/atomic.h"
#include "psc_util/crc.h"
#include "psc_util/iostats.h"
#include "psc_util/journal.h"
#include "psc_util/lock.h"
#include "psc_util/thread.h"
#include "psc_util/waitq.h"

#include "zfs-fuse/zfs_slashlib.h"

struct psc_journalthr {
	struct psc_journal *pjt_pj;
};

__static void		pjournal_logwrite(struct psc_journal_xidhndl *, int,
				struct psc_journal_enthdr *, int);

__static int		pjournal_logwrite_internal(struct psc_journal *,
				struct psc_journal_enthdr *, uint32_t);

struct psc_waitq	pjournal_waitq = PSC_WAITQ_INIT;
psc_spinlock_t		pjournal_waitqlock = SPINLOCK_INIT;

#define JIO_READ	0
#define JIO_WRITE	1

#define psc_journal_read(pj, p, len, off)	psc_journal_io((pj), (p), (len), (off), JIO_READ)
#define psc_journal_write(pj, p, len, off)	psc_journal_io((pj), (p), (len), (off), JIO_WRITE)

/**
 * psc_journal_io - Perform a low-level I/O operation on the journal store.
 * @pj: the owning journal.
 */
__static int
psc_journal_io(struct psc_journal *pj, void *p, size_t len, off_t off,
    int rw)
{
	ssize_t nb;
	int rc;

	if (rw == JIO_READ)
		nb = pread(pj->pj_fd, p, len, off);
	else
		nb = pwrite(pj->pj_fd, p, len, off);

	if (nb == -1) {
		rc = errno;
		psc_error("journal %s (pj=%p, len=%zd, off=%"PSCPRIdOFFT")",
		    rw == JIO_READ ? "read" : "write", pj, len, off);
	} else if ((size_t)nb != len) {
		/*
		 * At least on one instance, short write actually
		 * returns "success" on a RAM-backed file system.
		 */
		rc = ENOSPC;
		psc_errorx("journal %s (pj=%p, len=%zd, off=%"PSCPRIdOFFT", "
		    "nb=%zd): short I/O", rw == JIO_READ ? "read" : "write",
		    pj, len, off, nb);
	} else {
		rc = 0;
		psc_iostats_intv_add(rw == JIO_READ ?
		    &pj->pj_rdist : &pj->pj_wrist, nb);

		if (rw == JIO_WRITE) {
			if (pj->pj_flags & PJF_ISBLKDEV) {
#ifdef HAVE_SYNC_FILE_RANGE
				rc = sync_file_range(pj->pj_fd, off, len,
					     SYNC_FILE_RANGE_WRITE |
					     SYNC_FILE_RANGE_WAIT_AFTER);
#else
				rc = fdatasync(pj->pj_fd);
#endif
			} else
				rc = fsync(pj->pj_fd);

			if (rc)
				psc_error("sync_file_range failed (len=%zd, off=%"
				    PSCPRIdOFFT")", len, off);
		}
	}
	return (rc);
}

int
pjournal_has_peers(struct psc_journal *pj)
{
	return(pj->pj_npeers);
}

uint64_t
pjournal_next_replay(struct psc_journal *pj)
{
	uint64_t xid;

	PJ_LOCK(pj);
	xid = pj->pj_replay_xid;
	PJ_ULOCK(pj);

	return (xid);
}

uint64_t
pjournal_next_distill(struct psc_journal *pj)
{
	uint64_t xid;

	PJ_LOCK(pj);
	xid = pj->pj_distill_xid;
	PJ_ULOCK(pj);

	return (xid);
}

uint64_t
pjournal_next_reclaim(struct psc_journal *pj)
{
	uint64_t seqno;

	PJ_LOCK(pj);
	seqno = pj->pj_reclaim_seqno++;
	PJ_ULOCK(pj);

	return (seqno);
}

__static void
pjournal_next_xid(struct psc_journal *pj, struct psc_journal_xidhndl *xh)
{
	/*
	 * Note that even though we issue xids in increasing order here,
	 * it does not necessarily mean transactions will end up in the
	 * log in the same order.
	 */
	PJ_LOCK(pj);
	do {
		xh->pjx_xid = ++pj->pj_lastxid;
	} while (xh->pjx_xid == PJE_XID_NONE);
	/*
	 * Make sure that transactions appear on the distill list in strict
	 * order.  That way we can get accurate information about the lowest
	 * xid that has been distilled.
	 *
	 * If we add to the list after the transaction is written, the order
	 * may not be guaranteed, as I said above.
	 */
	if (xh->pjx_flags & PJX_DISTILL)
		pll_addtail(&pj->pj_distillxids, xh);
	PJ_ULOCK(pj);
}


/**
 * pjournal_next_slot - Determine where to write the transaction's log.
 *	Because we have already reserved a slot for it, we can simply<commit_msg>be conservative on the distill xids, also remove some unused stuff<commit_after>/* $Id$ */
/*
 * %PSC_START_COPYRIGHT%
 * -----------------------------------------------------------------------------
 * Copyright (c) 2007-2011, Pittsburgh Supercomputing Center (PSC).
 *
 * Permission to use, copy, and modify this software and its documentation
 * without fee for personal use or non-commercial use within your organization
 * is hereby granted, provided that the above copyright notice is preserved in
 * all copies and that the copyright and this permission notice appear in
 * supporting documentation.  Permission to redistribute this software to other
 * organizations or individuals is not permitted without the written permission
 * of the Pittsburgh Supercomputing Center.  PSC makes no representations about
 * the suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 * -----------------------------------------------------------------------------
 * %PSC_END_COPYRIGHT%
 */

#include <sys/types.h>
#include <sys/stat.h>

#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>

#include "pfl/fcntl.h"
#include "pfl/time.h"
#include "pfl/types.h"
#include "psc_ds/dynarray.h"
#include "psc_util/alloc.h"
#include "psc_util/atomic.h"
#include "psc_util/crc.h"
#include "psc_util/iostats.h"
#include "psc_util/journal.h"
#include "psc_util/lock.h"
#include "psc_util/thread.h"
#include "psc_util/waitq.h"

#include "zfs-fuse/zfs_slashlib.h"

struct psc_journalthr {
	struct psc_journal *pjt_pj;
};

__static void		pjournal_logwrite(struct psc_journal_xidhndl *, int,
				struct psc_journal_enthdr *, int);

__static int		pjournal_logwrite_internal(struct psc_journal *,
				struct psc_journal_enthdr *, uint32_t);

struct psc_waitq	pjournal_waitq = PSC_WAITQ_INIT;
psc_spinlock_t		pjournal_waitqlock = SPINLOCK_INIT;

#define JIO_READ	0
#define JIO_WRITE	1

#define psc_journal_read(pj, p, len, off)	psc_journal_io((pj), (p), (len), (off), JIO_READ)
#define psc_journal_write(pj, p, len, off)	psc_journal_io((pj), (p), (len), (off), JIO_WRITE)

/**
 * psc_journal_io - Perform a low-level I/O operation on the journal store.
 * @pj: the owning journal.
 */
__static int
psc_journal_io(struct psc_journal *pj, void *p, size_t len, off_t off,
    int rw)
{
	ssize_t nb;
	int rc;

	if (rw == JIO_READ)
		nb = pread(pj->pj_fd, p, len, off);
	else
		nb = pwrite(pj->pj_fd, p, len, off);

	if (nb == -1) {
		rc = errno;
		psc_error("journal %s (pj=%p, len=%zd, off=%"PSCPRIdOFFT")",
		    rw == JIO_READ ? "read" : "write", pj, len, off);
	} else if ((size_t)nb != len) {
		/*
		 * At least on one instance, short write actually
		 * returns "success" on a RAM-backed file system.
		 */
		rc = ENOSPC;
		psc_errorx("journal %s (pj=%p, len=%zd, off=%"PSCPRIdOFFT", "
		    "nb=%zd): short I/O", rw == JIO_READ ? "read" : "write",
		    pj, len, off, nb);
	} else {
		rc = 0;
		psc_iostats_intv_add(rw == JIO_READ ?
		    &pj->pj_rdist : &pj->pj_wrist, nb);

		if (rw == JIO_WRITE) {
			if (pj->pj_flags & PJF_ISBLKDEV) {
#ifdef HAVE_SYNC_FILE_RANGE
				rc = sync_file_range(pj->pj_fd, off, len,
					     SYNC_FILE_RANGE_WRITE |
					     SYNC_FILE_RANGE_WAIT_AFTER);
#else
				rc = fdatasync(pj->pj_fd);
#endif
			} else
				rc = fsync(pj->pj_fd);

			if (rc)
				psc_error("sync_file_range failed (len=%zd, off=%"
				    PSCPRIdOFFT")", len, off);
		}
	}
	return (rc);
}

int
pjournal_has_peers(struct psc_journal *pj)
{
	return(pj->pj_npeers);
}

uint64_t
pjournal_next_replay(struct psc_journal *pj)
{
	uint64_t xid;

	PJ_LOCK(pj);
	xid = pj->pj_replay_xid;
	PJ_ULOCK(pj);

	return (xid);
}

__static void
pjournal_next_xid(struct psc_journal *pj, struct psc_journal_xidhndl *xh)
{
	/*
	 * Note that even though we issue xids in increasing order here,
	 * it does not necessarily mean transactions will end up in the
	 * log in the same order.
	 */
	PJ_LOCK(pj);
	do {
		xh->pjx_xid = ++pj->pj_lastxid;
	} while (xh->pjx_xid == PJE_XID_NONE);
	/*
	 * Make sure that transactions appear on the distill list in strict
	 * order.  That way we can get accurate information about the lowest
	 * xid that has been distilled.
	 *
	 * If we add to the list after the transaction is written, the order
	 * may not be guaranteed, as I said above.
	 */
	if (xh->pjx_flags & PJX_DISTILL)
		pll_addtail(&pj->pj_distillxids, xh);
	PJ_ULOCK(pj);
}


/**
 * pjournal_next_slot - Determine where to write the transaction's log.
 *	Because we have already reserved a slot for it, we can simply
{'fraction_non_alphanumeric': 0.15159208716809477, 'fraction_numerical': 0.004654607003067809, 'mean_word_length': 3.453132359868111, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2344891', 'n_tokens_mistral': 3858, 'n_tokens_neox': 3611, 'n_words': 975}