cachefs_log.c revision f48205be61a214698b763ff550ab9e657525104c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <sys/stat.h>
#include <sys/kstat.h>
#include <sys/time.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <sys/mode.h>
#include <sys/pathname.h>
#include <sys/cmn_err.h>
#include <sys/debug.h>
#include <sys/fs/cachefs_fs.h>
#include <sys/fs/cachefs_log.h>
#include <vm/seg.h>
#include <vm/seg_map.h>
#include <sys/sysmacros.h>
/*
* ino64_t is a unsigned long on LP64 and unsigned long long on ILP32,
* the compiler emits many warnings when calling xdr_u_longlong_t with an
* unsigned long pointer on LP64 even though it's safe.
*/
#define xdr_ino64(xdrs, p) xdr_u_longlong_t((xdrs), (u_longlong_t *)(p))
/*
* cfs_time_t is an int in both LP64 and ILP32. To avoid compiler warnings
* define its xdr here explicitely
*/
#define xdr_cfs_time_t(xdrs, p) xdr_int((xdrs), (int *)(p))
#define CACHEFS_LOG_MAX_BUFFERED 65536
#define CACHEFS_LOG_LOWATER 8192
#define CACHEFS_LOG_ENCODE_SIZE 4096
#if (defined(_SYSCALL32_IMPL) || defined(_LP64))
#define OUT_IF_TIME_OVERFLOW(cachep, time) \
if (TIME_OVERFLOW(time)) { \
cachefs_log_error(cachep, EOVERFLOW, 1); \
goto out; \
}
#define RET_IF_TIME_OVERFLOW(cachep, time) \
if (TIME_OVERFLOW(time)) { \
cachefs_log_error(cachep, EOVERFLOW, 1); \
return; \
}
#else /* not (_SYSCALL32_IMPL || _LP64) */
#define OUT_IF_TIME_OVERFLOW(cachep, time)
#define RET_IF_TIME_OVERFLOW(cachep, time)
#endif /* (_SYSCALL32_IMPL || _LP64) */
typedef struct cachefs_log_work_list {
void *data;
size_t size;
xdrproc_t translate;
struct cachefs_log_work_list *next;
} *cachefs_log_work_list_t;
/* forward declarations of static functions */
static void cachefs_log_enqueue(cachefscache_t *, void *, int, xdrproc_t);
static int cachefs_log_save_lc(cachefscache_t *);
static int cachefs_log_write_header(struct vnode *, cachefscache_t *, int);
static bool_t cachefs_xdr_logfile_header(XDR *,
struct cachefs_log_logfile_header *);
static bool_t cachefs_xdr_mount(XDR *, struct cachefs_log_mount_record *);
static bool_t cachefs_xdr_umount(XDR *, struct cachefs_log_umount_record *);
static bool_t cachefs_xdr_getpage(XDR *, struct cachefs_log_getpage_record *);
static bool_t cachefs_xdr_readdir(XDR *, struct cachefs_log_readdir_record *);
static bool_t cachefs_xdr_readlink(XDR *,
struct cachefs_log_readlink_record *);
static bool_t cachefs_xdr_remove(XDR *, struct cachefs_log_remove_record *);
static bool_t cachefs_xdr_rmdir(XDR *, struct cachefs_log_rmdir_record *);
static bool_t cachefs_xdr_truncate(XDR *,
struct cachefs_log_truncate_record *);
static bool_t cachefs_xdr_putpage(XDR *, struct cachefs_log_putpage_record *);
static bool_t cachefs_xdr_create(XDR *, struct cachefs_log_create_record *);
static bool_t cachefs_xdr_mkdir(XDR *, struct cachefs_log_mkdir_record *);
static bool_t cachefs_xdr_rename(XDR *, struct cachefs_log_rename_record *);
static bool_t cachefs_xdr_symlink(XDR *, struct cachefs_log_symlink_record *);
static bool_t cachefs_xdr_populate(XDR *,
struct cachefs_log_populate_record *);
static bool_t cachefs_xdr_csymlink(XDR *,
struct cachefs_log_csymlink_record *);
static bool_t cachefs_xdr_filldir(XDR *,
struct cachefs_log_filldir_record *);
static bool_t cachefs_xdr_mdcreate(XDR *,
struct cachefs_log_mdcreate_record *);
static bool_t cachefs_xdr_gpfront(XDR *,
struct cachefs_log_gpfront_record *);
static bool_t cachefs_xdr_rfdir(XDR *,
struct cachefs_log_rfdir_record *);
static bool_t cachefs_xdr_ualloc(XDR *,
struct cachefs_log_ualloc_record *);
static bool_t cachefs_xdr_calloc(XDR *,
struct cachefs_log_calloc_record *);
static bool_t cachefs_xdr_nocache(XDR *,
struct cachefs_log_nocache_record *);
extern time_t time;
/*
* cachefs_log_kstat_snapshot(kstat_t *ksp, void *buf, int rw)
*
* called from /dev/kstat or somesuch.
*
*/
int
cachefs_log_kstat_snapshot(kstat_t *ksp, void *buf, int rw)
{
cachefs_log_control_t *lc = (cachefs_log_control_t *)ksp->ks_data;
cachefs_log_control_t *buflc = (cachefs_log_control_t *)buf;
cachefscache_t *cachep = (cachefscache_t *)(uintptr_t)lc->lc_cachep;
cachefs_log_cookie_t *cl = cachep->c_log;
int error = 0;
ASSERT(MUTEX_HELD(&cachep->c_log_mutex));
/* if they just want to read the kstat, get that out of the way. */
if (rw != KSTAT_WRITE) {
bcopy(lc, buflc, sizeof (*lc));
return (0);
}
/* make sure they're passing us a valid control cookie */
if ((buflc->lc_cachep != lc->lc_cachep) ||
(buflc->lc_magic != CACHEFS_LOG_MAGIC))
return (EIO);
/*
* if logging is currently off
* o insist that we're being handed a logfile path
* o set cl, and give our cachep its value
*
* after that, if something goes wrong, we must call
* cachefs_log_error to clear cachep->c_log.
*/
if (cl == NULL) {
if (buflc->lc_path[0] == '\0')
return (EIO);
cl = cachep->c_log = cachefs_log_create_cookie(lc);
if (cl == NULL) {
cachefs_log_error(cachep, ENOMEM, 0);
return (EIO);
}
}
/*
* if we're being handed an empty logpath, then they must be
* turning off logging; also, logging must have been turned on
* before, or else the previous paragraph would have caught
* it.
*/
if (buflc->lc_path[0] == '\0') {
cachefs_log_process_queue(cachep, 0);
cachep->c_log = NULL;
cachefs_log_destroy_cookie(cl);
bzero(lc, sizeof (*lc));
lc->lc_magic = CACHEFS_LOG_MAGIC;
lc->lc_cachep = (uint64_t)(uintptr_t)cachep;
(void) VOP_REMOVE(cachep->c_dirvp, LOG_STATUS_NAME, kcred);
return (0);
}
/*
* if we get here, we know that we're being handed a valid log
* control cookie, and that a path is set. try to open the
* log file, even if it's the same path, because they might
* have removed the old log file out from under us. if it
* really is the same file, no harm done.
*/
if ((error = cachefs_log_logfile_open(cachep, buflc->lc_path)) != 0) {
cachefs_log_error(cachep, error, 0);
return (EIO);
}
/*
* if we get here, we have a valid logfile open. we don't do
* anything here with the bitmap of what's being logged, other
* than copy it. we're home free!
*/
bcopy(buflc, lc, sizeof (*lc));
if ((error = cachefs_log_save_lc(cachep)) != 0) {
cachefs_log_error(cachep, error, 0);
return (EIO);
}
return (0);
}
static int
cachefs_log_save_lc(cachefscache_t *cachep)
{
cachefs_log_control_t *lc = (cachefs_log_control_t *)cachep->c_log_ctl;
struct vnode *savevp;
struct vattr attr;
int error = 0;
if (lc == NULL)
return (EINVAL);
attr.va_mode = S_IFREG | 0666;
attr.va_uid = 0;
attr.va_gid = 0;
attr.va_type = VREG;
attr.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
if (((error = VOP_LOOKUP(cachep->c_dirvp, LOG_STATUS_NAME, &savevp,
NULL, 0, NULL, kcred)) != 0) &&
((error = VOP_CREATE(cachep->c_dirvp, LOG_STATUS_NAME, &attr, EXCL,
0600, &savevp, kcred, 0)) != 0))
return (error);
ASSERT(savevp != NULL);
if (savevp == NULL)
return (ENOENT);
error = vn_rdwr(UIO_WRITE, savevp,
(caddr_t)lc, sizeof (*lc),
0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL);
VN_RELE(savevp);
return (error);
}
/*
* cachefs_log_cookie_t *cachefs_log_create_cookie(void *)
*
* creates and initializes the cookie, which lives in cachep. called
* from either a kstat write which turns on logging, or from
* initializing cachep when a log-info-file exists.
*/
cachefs_log_cookie_t *
cachefs_log_create_cookie(cachefs_log_control_t *lc)
{
cachefs_log_cookie_t *rc;
rc = cachefs_kmem_zalloc(sizeof (*rc), KM_NOSLEEP);
if (rc == NULL)
return (NULL);
rc->cl_magic = CACHEFS_LOG_MAGIC;
rc->cl_logctl = lc;
return (rc);
}
/*
* void cachefs_log_destroy_cookie(cachefs_log_cookie_t *)
*
* destroys the log cookie. called from cachefs_log_error, or from
* destroying the cachep.
*
*/
void
cachefs_log_destroy_cookie(cachefs_log_cookie_t *cl)
{
cachefs_log_work_list_t node, oldnode;
if (cl == NULL)
return;
ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC);
cl->cl_magic++;
node = cl->cl_head;
while (node != NULL) {
cachefs_kmem_free(node->data, node->size);
oldnode = node;
node = node->next;
cachefs_kmem_free(oldnode, sizeof (*oldnode));
}
if (cl->cl_logvp != NULL)
VN_RELE(cl->cl_logvp);
cachefs_kmem_free(cl, sizeof (*cl));
}
/*
* int cachefs_log_logfile_open(cachefscache_t *, char *)
*
* opens the logfile, and stores the path string if its successful.
*
* returns an errno if one occured.
*
*/
int
cachefs_log_logfile_open(cachefscache_t *cachep, char *path)
{
cachefs_log_cookie_t *cl = cachep->c_log;
struct vnode *newvp = NULL;
int error = 0;
int i;
ASSERT(MUTEX_HELD(&cachep->c_log_mutex));
ASSERT(cl != NULL);
ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC);
/* lookup the pathname -- it must already exist! */
error = lookupname(path, UIO_SYSSPACE, FOLLOW, NULL, &newvp);
if (error)
goto out;
ASSERT(newvp != NULL);
if (newvp == NULL) {
error = ENOENT; /* XXX this shouldn't happen (yeah right) */
goto out;
}
/* easy out if we just re-opened the same logfile */
if (cl->cl_logvp == newvp) {
VN_RELE(newvp);
goto out;
}
/* XXX we may change this to allow named pipes */
if (newvp->v_type != VREG) {
error = EINVAL;
goto out;
}
if (vn_matchops(newvp, cachefs_getvnodeops())) {
error = EINVAL;
goto out;
}
/* write out the header */
error = cachefs_log_write_header(newvp, cachep, 0);
if (error)
goto out;
/* if we get here, we successfully opened the log. */
if (cl->cl_logvp != NULL)
VN_RELE(cl->cl_logvp);
cl->cl_logvp = newvp;
/*
* `fake' a mount entry for each mounted cachefs filesystem.
* this is overkill, but it's easiest and most foolproof way
* to do things here. the user-level consumers of the logfile
* have to expect extraneous mount entries and deal with it
* correctly.
*/
mutex_exit(&cachep->c_log_mutex);
for (i = 0; i < cachefs_kstat_key_n; i++) {
cachefs_kstat_key_t *k;
struct vfs *vfsp;
struct fscache *fscp;
k = cachefs_kstat_key + i;
if (! k->ks_mounted)
continue;
vfsp = (struct vfs *)(uintptr_t)k->ks_vfsp;
fscp = VFS_TO_FSCACHE(vfsp);
cachefs_log_mount(cachep, 0, vfsp, fscp,
(char *)(uintptr_t)k->ks_mountpoint, UIO_SYSSPACE,
(char *)(uintptr_t)k->ks_cacheid);
}
mutex_enter(&cachep->c_log_mutex);
out:
if ((error != 0) && (newvp != NULL))
VN_RELE(newvp);
return (error);
}
/*
* called when an error occured during logging. send the error to
* syslog, invalidate the logfile, and stop logging.
*/
void
cachefs_log_error(cachefscache_t *cachep, int error, int getlock)
{
cachefs_log_cookie_t *cl = cachep->c_log;
cachefs_log_control_t *lc = cachep->c_log_ctl;
int writable = 0;
ASSERT((getlock) || (MUTEX_HELD(&cachep->c_log_mutex)));
if (getlock)
mutex_enter(&cachep->c_log_mutex);
if ((cachep->c_flags & (CACHE_NOCACHE | CACHE_NOFILL)) == 0)
writable = 1;
cmn_err(CE_WARN, "cachefs logging: error %d\n", error);
if ((writable) && (cl != NULL) && (cl->cl_logvp != NULL))
(void) cachefs_log_write_header(cl->cl_logvp, cachep, error);
cachep->c_log = NULL;
if (cl != NULL)
cachefs_log_destroy_cookie(cl);
bzero(lc, sizeof (cachefs_log_control_t));
lc->lc_magic = CACHEFS_LOG_MAGIC;
lc->lc_cachep = (uint64_t)(uintptr_t)cachep;
if (writable)
(void) VOP_REMOVE(cachep->c_dirvp, LOG_STATUS_NAME, kcred);
if (getlock)
mutex_exit(&cachep->c_log_mutex);
}
static int
cachefs_log_write_header(struct vnode *vp, cachefscache_t *cachep, int error)
{
struct cachefs_log_logfile_header header, oheader;
char buffy[2 * sizeof (header)];
int Errno = 0;
struct vattr attr;
int gotold = 0;
XDR xdrm;
attr.va_mask = AT_SIZE;
if ((error = VOP_GETATTR(vp, &attr, 0, kcred)) != 0)
goto out;
if (attr.va_size != 0) {
error = vn_rdwr(UIO_READ, vp, buffy,
MIN(sizeof (buffy), attr.va_size),
0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL);
if (error != 0)
goto out;
xdrm.x_ops = NULL;
xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_DECODE);
if ((xdrm.x_ops == NULL) ||
(! cachefs_xdr_logfile_header(&xdrm, &oheader))) {
if (xdrm.x_ops != NULL)
xdr_destroy(&xdrm);
error = EINVAL;
goto out;
}
xdr_destroy(&xdrm);
gotold = 1;
if (oheader.lh_magic != CACHEFS_LOG_MAGIC) {
error = EINVAL;
goto out;
}
}
xdrm.x_ops = NULL;
xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_ENCODE);
if (gotold) {
header = oheader;
} else {
header.lh_magic = CACHEFS_LOG_MAGIC;
header.lh_revision = CACHEFS_LOG_FILE_REV;
header.lh_blocks = cachep->c_usage.cu_blksused;
header.lh_files = cachep->c_usage.cu_filesused;
header.lh_maxbsize = MAXBSIZE;
header.lh_pagesize = PAGESIZE;
}
/* these are things that we stomp over for every header write */
header.lh_errno = Errno;
if (! cachefs_xdr_logfile_header(&xdrm, &header)) {
error = ENOMEM;
goto out;
}
error = vn_rdwr(UIO_WRITE, vp,
(caddr_t)buffy, xdr_getpos(&xdrm),
0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL);
if (error)
goto out;
out:
if (xdrm.x_ops != NULL)
xdr_destroy(&xdrm);
return (error);
}
/*
* enqueues a record to be written to the logfile.
*/
static void
cachefs_log_enqueue(cachefscache_t *cachep, void *record, int size,
xdrproc_t translate)
{
cachefs_log_cookie_t *cl;
cachefs_log_work_list_t newnode, oldnode;
mutex_enter(&cachep->c_log_mutex);
cl = cachep->c_log;
if (cl == NULL) { /* someone turned off logging out from under us */
mutex_exit(&cachep->c_log_mutex);
cachefs_kmem_free(record, size);
return;
}
ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC);
cl->cl_size += size;
newnode = cachefs_kmem_zalloc(sizeof (*newnode), KM_NOSLEEP);
if ((cl->cl_size > CACHEFS_LOG_MAX_BUFFERED) || (newnode == NULL)) {
cachefs_log_error(cachep, ENOMEM, 0);
if (newnode != NULL)
cachefs_kmem_free(newnode, sizeof (*newnode));
cachefs_kmem_free(record, size);
mutex_exit(&cachep->c_log_mutex);
return;
}
newnode->data = record;
newnode->size = size;
newnode->translate = translate;
newnode->next = NULL;
oldnode = (cachefs_log_work_list_t)cl->cl_tail;
if (oldnode != NULL)
oldnode->next = newnode;
cl->cl_tail = newnode;
if (cl->cl_head == NULL)
cl->cl_head = newnode;
mutex_exit(&cachep->c_log_mutex);
if (cl->cl_size >= CACHEFS_LOG_LOWATER) {
mutex_enter(&cachep->c_workq.wq_queue_lock);
cachep->c_workq.wq_logwork = 1;
cv_signal(&cachep->c_workq.wq_req_cv);
mutex_exit(&cachep->c_workq.wq_queue_lock);
}
}
/*
* processes the log queue. run by an async worker thread, or via
* cachefs_cache_sync().
*/
void
cachefs_log_process_queue(cachefscache_t *cachep, int getlock)
{
cachefs_log_cookie_t *cl;
cachefs_log_work_list_t work, workhead, oldwork;
struct vnode *logvp = NULL;
struct uio uio;
struct iovec iov;
int error = 0;
XDR xdrm;
char *buffy = NULL;
/*
* NULL out the x_ops field of XDR. this way, if x_ops !=
* NULL, we know that we did the xdr*_create() successfully.
* this is documented in the xdr_create man page.
*/
xdrm.x_ops = NULL;
/* see if we're still logging */
if (getlock)
mutex_enter(&cachep->c_log_mutex);
cl = cachep->c_log;
if ((cl == NULL) || (cl->cl_magic != CACHEFS_LOG_MAGIC)) {
if (getlock)
mutex_exit(&cachep->c_log_mutex);
return;
}
/* get the work, and let go of the mutex asap. */
workhead = cl->cl_head;
cl->cl_head = cl->cl_tail = NULL;
cl->cl_size = 0;
logvp = cl->cl_logvp;
ASSERT(logvp != NULL);
if (logvp == NULL) {
if (getlock)
mutex_exit(&cachep->c_log_mutex);
return;
}
VN_HOLD(logvp);
if (getlock)
mutex_exit(&cachep->c_log_mutex);
/* we don't use vn_rdwr() because there's no way to set FNONBLOCK */
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_loffset = 0; /* fake -- we do FAPPEND */
uio.uio_segflg = (short)UIO_SYSSPACE;
uio.uio_llimit = MAXOFFSET_T;
uio.uio_fmode = FWRITE | FNONBLOCK;
uio.uio_extflg = UIO_COPY_CACHED;
buffy = cachefs_kmem_alloc(CACHEFS_LOG_ENCODE_SIZE, KM_SLEEP);
xdrmem_create(&xdrm, buffy, CACHEFS_LOG_ENCODE_SIZE, XDR_ENCODE);
(void) VOP_RWLOCK(logvp, V_WRITELOCK_TRUE, NULL);
for (work = workhead; work != NULL; work = work->next) {
if (! (work->translate)(&xdrm, work->data)) {
VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
error = ENOMEM;
goto out;
}
iov.iov_base = buffy;
iov.iov_len = uio.uio_resid = xdr_getpos(&xdrm);
(void) xdr_setpos(&xdrm, 0);
error = VOP_WRITE(logvp, &uio, FAPPEND, kcred, NULL);
/* XXX future -- check for EAGAIN */
if ((error) || (uio.uio_resid)) {
if (uio.uio_resid != 0)
error = EIO;
VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
goto out;
}
}
VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
out:
if (xdrm.x_ops != NULL)
xdr_destroy(&xdrm);
if (buffy != NULL)
cachefs_kmem_free(buffy, CACHEFS_LOG_ENCODE_SIZE);
/*
* if an error occured, we need to free the buffers ourselves.
* cachefs_destory_cookie() can't do it.
*/
work = workhead;
while (work != NULL) {
cachefs_kmem_free(work->data, work->size);
oldwork = work;
work = work->next;
cachefs_kmem_free(oldwork, sizeof (*oldwork));
}
if (logvp != NULL)
VN_RELE(logvp);
if (error) {
cachefs_log_error(cachep, error, 1);
return;
}
}
static bool_t
cachefs_xdr_logfile_header(XDR *xdrs, struct cachefs_log_logfile_header *h)
{
if ((! xdr_u_int(xdrs, &h->lh_magic)) ||
(! xdr_u_int(xdrs, &h->lh_revision)) ||
(! xdr_int(xdrs, &h->lh_errno)) ||
(! xdr_u_int(xdrs, &h->lh_blocks)) ||
(! xdr_u_int(xdrs, &h->lh_files)) ||
(! xdr_u_int(xdrs, &h->lh_maxbsize)) ||
(! xdr_u_int(xdrs, &h->lh_pagesize)))
return (FALSE);
return (TRUE);
}
/*
* the routines for logging each transaction follow...
*/
void
cachefs_log_mount(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fscache_t *fscp, char *upath, enum uio_seg seg, char *cacheid)
{
struct cachefs_log_mount_record *record;
char *cacheidt;
char *path = NULL;
size_t len;
int len1, len2;
int size, error;
/* In Solaris 64 - if can't represent time don't bother */
OUT_IF_TIME_OVERFLOW(cachep, time)
if (seg == UIO_USERSPACE) {
path = cachefs_kmem_alloc(MAXPATHLEN, KM_NOSLEEP);
if (path == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
goto out;
}
if ((error = copyinstr(upath, path, MAXPATHLEN, &len)) != 0) {
cachefs_log_error(cachep, error, 1);
goto out;
}
} else {
path = upath;
}
len1 = (path != NULL) ? strlen(path) : 0;
len2 = (cacheid != NULL) ? strlen(cacheid) : 0;
size = (int)sizeof (*record) + len1 + len2 -
(int)CLPAD(cachefs_log_mount_record, path);
record = cachefs_kmem_zalloc(size, KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
goto out;
}
record->type = CACHEFS_LOG_MOUNT;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fscp) {
record->flags = fscp->fs_info.fi_mntflags;
record->popsize = fscp->fs_info.fi_popsize;
record->fgsize = fscp->fs_info.fi_fgsize;
}
record->pathlen = (ushort_t)len1;
record->cacheidlen = (ushort_t)len2;
if (path != NULL)
(void) strcpy(record->path, path);
cacheidt = record->path + len1 + 1;
if (cacheid != NULL)
(void) strcpy(cacheidt, cacheid);
cachefs_log_enqueue(cachep, record, size, cachefs_xdr_mount);
out:
if ((seg == UIO_USERSPACE) && (path != NULL))
cachefs_kmem_free(path, MAXPATHLEN);
}
static bool_t
cachefs_xdr_mount(XDR *xdrs, struct cachefs_log_mount_record *rec)
{
char *path = rec->path;
char *cacheid;
cacheid = path + strlen(path) + 1;
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_u_int(xdrs, &rec->flags)) ||
(! xdr_u_int(xdrs, &rec->popsize)) ||
(! xdr_u_int(xdrs, &rec->fgsize)) ||
(! xdr_u_short(xdrs, &rec->pathlen)) ||
(! xdr_u_short(xdrs, &rec->cacheidlen)) ||
(! xdr_wrapstring(xdrs, &path)) ||
(! xdr_wrapstring(xdrs, &cacheid)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_umount(cachefscache_t *cachep, int Errno, struct vfs *vfsp)
{
struct cachefs_log_umount_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_UMOUNT;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_umount);
}
static bool_t
cachefs_xdr_umount(XDR *xdrs, struct cachefs_log_umount_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))))
return (FALSE);
return (TRUE);
}
void
cachefs_log_getpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len)
{
struct cachefs_log_getpage_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_GETPAGE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
record->offset = offset;
record->len = (uint_t)len;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_getpage);
}
static bool_t
cachefs_xdr_getpage(XDR *xdrs, struct cachefs_log_getpage_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)) ||
(! xdr_u_longlong_t(xdrs, &rec->offset)) ||
(! xdr_u_int(xdrs, &rec->len)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_readdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, int eof)
{
struct cachefs_log_readdir_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_READDIR;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
record->offset = offset;
record->eof = eof;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_readdir);
}
static bool_t
cachefs_xdr_readdir(XDR *xdrs, struct cachefs_log_readdir_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)) ||
(! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) ||
(! xdr_int(xdrs, &rec->eof)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_readlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid, size_t length)
{
struct cachefs_log_readlink_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_READLINK;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
record->length = (uint_t)length;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_readlink);
}
static bool_t
cachefs_xdr_readlink(XDR *xdrs, struct cachefs_log_readlink_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)) ||
(! xdr_u_int(xdrs, &rec->length)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_remove(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid)
{
struct cachefs_log_remove_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_REMOVE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_remove);
}
static bool_t
cachefs_xdr_remove(XDR *xdrs, struct cachefs_log_remove_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_rmdir(cachefscache_t *cachep, int Errno,
struct vfs *vfsp, fid_t *fidp, ino64_t fileno, uid_t uid)
{
struct cachefs_log_rmdir_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_RMDIR;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_rmdir);
}
static bool_t
cachefs_xdr_rmdir(XDR *xdrs, struct cachefs_log_rmdir_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_truncate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t size)
{
struct cachefs_log_truncate_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_TRUNCATE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
record->size = size;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_truncate);
}
static bool_t
cachefs_xdr_truncate(XDR *xdrs, struct cachefs_log_truncate_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)) ||
(! xdr_u_longlong_t(xdrs, &rec->size)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_putpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len)
{
struct cachefs_log_putpage_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_PUTPAGE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
record->offset = offset;
record->len = (uint_t)len;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_putpage);
}
static bool_t
cachefs_xdr_putpage(XDR *xdrs, struct cachefs_log_putpage_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)) ||
(! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) ||
(! xdr_u_int(xdrs, &rec->len)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_create(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *filefidp, ino64_t fileno, uid_t uid)
{
struct cachefs_log_create_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_CREATE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (filefidp != NULL) {
CACHEFS_FID_COPY(filefidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_create);
}
static bool_t
cachefs_xdr_create(XDR *xdrs, struct cachefs_log_create_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_mkdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *cfidp, ino64_t fileno, uid_t uid)
{
struct cachefs_log_mkdir_record *record;
int size;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
size = (int)sizeof (*record);
record = cachefs_kmem_zalloc(size, KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_MKDIR;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (cfidp != NULL) {
CACHEFS_FID_COPY(cfidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
cachefs_log_enqueue(cachep, record, size,
cachefs_xdr_mkdir);
}
static bool_t
cachefs_xdr_mkdir(XDR *xdrs, struct cachefs_log_mkdir_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_rename(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *gfp, ino64_t fileno, int removed, uid_t uid)
{
struct cachefs_log_rename_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_RENAME;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (gfp != NULL) {
CACHEFS_FID_COPY(gfp, &record->gone);
}
record->fileno = fileno;
record->removed = removed;
record->uid = uid;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_rename);
}
static bool_t
cachefs_xdr_rename(XDR *xdrs, struct cachefs_log_rename_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->gone, sizeof (rec->gone))) ||
(! xdr_int(xdrs, &rec->removed)) ||
(! xdr_u_int(xdrs, &rec->uid)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_symlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid, int size)
{
struct cachefs_log_symlink_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_SYMLINK;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
record->size = size;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_symlink);
}
static bool_t
cachefs_xdr_symlink(XDR *xdrs, struct cachefs_log_symlink_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)) ||
(! xdr_u_int(xdrs, &rec->size)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_populate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, u_offset_t off, size_t popsize)
{
struct cachefs_log_populate_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_POPULATE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->off = off;
record->size = (int)popsize;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_populate);
}
static bool_t
cachefs_xdr_populate(XDR *xdrs, struct cachefs_log_populate_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
(! xdr_u_int(xdrs, &rec->size)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_csymlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, int size)
{
struct cachefs_log_csymlink_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_CSYMLINK;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->size = size;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_csymlink);
}
static bool_t
cachefs_xdr_csymlink(XDR *xdrs, struct cachefs_log_csymlink_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_int(xdrs, &rec->size)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_filldir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, u_offset_t size)
{
struct cachefs_log_filldir_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_FILLDIR;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->size = (uint_t)size;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_filldir);
}
static bool_t
cachefs_xdr_filldir(XDR *xdrs, struct cachefs_log_filldir_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, (uint_t *)&rec->size)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_mdcreate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uint_t count)
{
struct cachefs_log_mdcreate_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_MDCREATE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->count = count;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_mdcreate);
}
static bool_t
cachefs_xdr_mdcreate(XDR *xdrs, struct cachefs_log_mdcreate_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->count)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_gpfront(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, uint_t len)
{
struct cachefs_log_gpfront_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_GPFRONT;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
record->off = offset;
record->len = len;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_gpfront);
}
static bool_t
cachefs_xdr_gpfront(XDR *xdrs, struct cachefs_log_gpfront_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)) ||
(! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
(! xdr_u_int(xdrs, &rec->len)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_rfdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, uid_t uid)
{
struct cachefs_log_rfdir_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_RFDIR;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->uid = uid;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_rfdir);
}
static bool_t
cachefs_xdr_rfdir(XDR *xdrs, struct cachefs_log_rfdir_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_int(xdrs, &rec->uid)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_ualloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len)
{
struct cachefs_log_ualloc_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_UALLOC;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->off = off;
record->len = (uint_t)len;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_ualloc);
}
static bool_t
cachefs_xdr_ualloc(XDR *xdrs, struct cachefs_log_ualloc_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
(! xdr_u_int(xdrs, (uint_t *)&rec->len)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_calloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len)
{
struct cachefs_log_calloc_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_CALLOC;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
record->off = off;
record->len = (uint_t)len;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_calloc);
}
static bool_t
cachefs_xdr_calloc(XDR *xdrs, struct cachefs_log_calloc_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)) ||
(! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
(! xdr_u_int(xdrs, &rec->len)))
return (FALSE);
return (TRUE);
}
void
cachefs_log_nocache(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
fid_t *fidp, ino64_t fileno)
{
struct cachefs_log_nocache_record *record;
/* In Solaris 64 - if can't represent time don't bother */
RET_IF_TIME_OVERFLOW(cachep, time)
record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
if (record == NULL) {
cachefs_log_error(cachep, ENOMEM, 1);
return;
}
record->type = CACHEFS_LOG_NOCACHE;
record->time = time;
record->error = Errno;
record->vfsp = (uint64_t)(uintptr_t)vfsp;
if (fidp != NULL) {
CACHEFS_FID_COPY(fidp, &record->fid);
}
record->fileno = fileno;
cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
cachefs_xdr_nocache);
}
static bool_t
cachefs_xdr_nocache(XDR *xdrs, struct cachefs_log_nocache_record *rec)
{
if ((! xdr_int(xdrs, &rec->type)) ||
(! xdr_int(xdrs, &rec->error)) ||
(! xdr_cfs_time_t(xdrs, &rec->time)) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
(! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
(! xdr_ino64(xdrs, &rec->fileno)))
return (FALSE);
return (TRUE);
}