dc_vnops.c revision de710d24d2fae4468e64da999e1d952a247f142c
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * CDDL HEADER START
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * The contents of this file are subject to the terms of the
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Common Development and Distribution License (the "License").
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * You may not use this file except in compliance with the License.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * or http://www.opensolaris.org/os/licensing.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * See the License for the specific language governing permissions
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * and limitations under the License.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * When distributing Covered Code, include this CDDL HEADER in each
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * If applicable, add the following below this CDDL HEADER, with the
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * fields enclosed by brackets "[]" replaced with your own identifying
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * information: Portions Copyright [yyyy] [name of copyright owner]
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * CDDL HEADER END
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
0fbb751d81ab0a7c7ddfd8d4e447e075a9f7024fJohn Levon * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/* All Rights Reserved */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * University Copyright- Copyright (c) 1982, 1986, 1988
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * The Regents of the University of California
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * All Rights Reserved
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * University Acknowledgment- Portions of this document are derived from
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * software developed by the University of California, Berkeley, and its
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * contributors.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/types.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/thread.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/t_lock.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/param.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/systm.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/bitmap.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/buf.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/cmn_err.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/conf.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/ddi.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/debug.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/errno.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/time.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/fcntl.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/flock.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/file.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/kmem.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/mman.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/vmsystm.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/open.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/swap.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/sysmacros.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/uio.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/vfs.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/vfs_opreg.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/vnode.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/stat.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/poll.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/zmod.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/fs/decomp.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <vm/hat.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <vm/as.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <vm/page.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <vm/pvn.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <vm/seg_vn.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <vm/seg_kmem.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <vm/seg_map.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <fs/fs_subr.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * dcfs - A filesystem for automatic decompressing of fiocompressed files
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * This filesystem is a layered filesystem that sits on top of a normal
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * persistent filesystem and provides automatic decompression of files
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * that have been previously compressed and stored on the host file system.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * This is a pseudo filesystem in that it does not persist data, rather it
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * intercepts file lookup requests on the host filesystem and provides
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * transparent decompression of those files. Currently the only supported
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * host filesystem is ufs.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * A file is compressed via a userland utility (currently cmd/boot/fiocompress)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * and marked by fiocompress as a compressed file via a flag in the on-disk
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * inode (set via a ufs ioctl() - see `ufs_vnops.c`ufs_ioctl()`_FIO_COMPRESSED
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * ufs_lookup checks for this flag and if set, passes control to decompvp
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * a function defined in this (dcfs) filesystem. decomvp uncompresses the file
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * and returns a dcfs vnode to the VFS layer.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * dcfs is layered on top of ufs and passes requests involving persistence
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * to the underlying ufs filesystem. The compressed files currently cannot be
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * written to.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Define data structures within this file.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#define DCSHFT 5
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#define DCTABLESIZE 16
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#if ((DCTABLESIZE & (DCTABLESIZE - 1)) == 0)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#define DCHASH(vp) (((uintptr_t)(vp) >> DCSHFT) & (DCTABLESIZE - 1))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#else
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#define DCHASH(vp) (((uintptr_t)(vp) >> DCSHFT) % DTABLESIZEC)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#endif
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#define DCLRUSIZE 16
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#define DCCACHESIZE 4
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#define rounddown(x, y) ((x) & ~((y) - 1))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct dcnode *dctable[DCTABLESIZE];
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct dcnode *dclru;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dclru_len;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjekmutex_t dctable_lock;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedev_t dcdev;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct vfs dc_vfs;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct kmem_cache *dcnode_cache;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct kmem_cache *dcbuf_cache[DCCACHESIZE];
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjekmutex_t dccache_lock;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dcinit(int, char *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic struct dcnode *dcnode_alloc(void);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void dcnode_free(struct dcnode *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void dcnode_recycle(struct dcnode *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void dcinsert(struct dcnode *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void dcdelete(struct dcnode *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic struct dcnode *dcfind(struct vnode *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void dclru_add(struct dcnode *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void dclru_sub(struct dcnode *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * This is the loadable module wrapper.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#include <sys/modctl.h>
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct vfsops *dc_vfsops;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic vfsdef_t vfw = {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VFSDEF_VERSION,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje "dcfs",
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcinit,
0fbb751d81ab0a7c7ddfd8d4e447e075a9f7024fJohn Levon VSW_ZMOUNT,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje NULL
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje};
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Module linkage information for the kernel.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjeextern struct mod_ops mod_fsops;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic struct modlfs modlfs = {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje &mod_fsops, "compressed filesystem", &vfw
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje};
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic struct modlinkage modlinkage = {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje MODREV_1, (void *)&modlfs, NULL
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje};
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjeint
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje_init()
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (mod_install(&modlinkage));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjeint
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje_info(struct modinfo *modinfop)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (mod_info(&modlinkage, modinfop));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_open(struct vnode **, int, struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_close(struct vnode *, int, int, offset_t,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_read(struct vnode *, struct uio *, int, struct cred *,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct caller_context *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_getattr(struct vnode *, struct vattr *, int,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_setattr(struct vnode *, struct vattr *, int, struct cred *,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct caller_context *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_access(struct vnode *, int, int,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_fsync(struct vnode *, int, struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void dc_inactive(struct vnode *, struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_fid(struct vnode *, struct fid *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_seek(struct vnode *, offset_t, offset_t *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_frlock(struct vnode *, int, struct flock64 *, int, offset_t,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct flk_callback *, struct cred *, caller_context_t *);
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfourstatic int dc_realvp(struct vnode *, struct vnode **, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_getpage(struct vnode *, offset_t, size_t, uint_t *,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct page **, size_t, struct seg *, caddr_t, enum seg_rw,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_putpage(struct vnode *, offset_t, size_t, int,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_map(struct vnode *, offset_t, struct as *, caddr_t *, size_t,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje uchar_t, uchar_t, uint_t, struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_addmap(struct vnode *, offset_t, struct as *, caddr_t, size_t,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje uchar_t, uchar_t, uint_t, struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int dc_delmap(struct vnode *, offset_t, struct as *, caddr_t, size_t,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje uint_t, uint_t, uint_t, struct cred *, caller_context_t *);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct vnodeops *dc_vnodeops;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjeconst fs_operation_def_t dc_vnodeops_template[] = {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_OPEN, { .vop_open = dc_open },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_CLOSE, { .vop_close = dc_close },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_READ, { .vop_read = dc_read },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_GETATTR, { .vop_getattr = dc_getattr },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_SETATTR, { .vop_setattr = dc_setattr },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_ACCESS, { .vop_access = dc_access },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_FSYNC, { .vop_fsync = dc_fsync },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_INACTIVE, { .vop_inactive = dc_inactive },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_FID, { .vop_fid = dc_fid },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_SEEK, { .vop_seek = dc_seek },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_FRLOCK, { .vop_frlock = dc_frlock },
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour VOPNAME_REALVP, { .vop_realvp = dc_realvp },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_GETPAGE, { .vop_getpage = dc_getpage },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_PUTPAGE, { .vop_putpage = dc_putpage },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_MAP, { .vop_map = dc_map },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_ADDMAP, { .vop_addmap = dc_addmap },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VOPNAME_DELMAP, { .vop_delmap = dc_delmap },
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje NULL, NULL
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje};
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_open(struct vnode **vpp, int flag, struct cred *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_close(struct vnode *vp, int flag, int count, offset_t off,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje (void) cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cleanshares(vp, ttoproc(curthread)->p_pid);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *cr,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct caller_context *ct)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t rdsize = MAX(MAXBSIZE, dp->dc_hdr->ch_blksize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t fsize = dp->dc_hdr->ch_fsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int error;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Loop through file with segmap, decompression will occur
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * in dc_getapage
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje do {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje caddr_t base;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t n;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje offset_t mapon;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * read to end of block or file
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mapon = uiop->uio_loffset & (rdsize - 1);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje n = MIN(rdsize - mapon, uiop->uio_resid);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje n = MIN(n, fsize - uiop->uio_loffset);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (n == 0)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0); /* at EOF */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje base = segmap_getmapflt(segkmap, vp, uiop->uio_loffset, n, 1,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje S_READ);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = uiomove(base + mapon, n, UIO_READ, uiop);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (!error) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje uint_t flags;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (n + mapon == rdsize || uiop->uio_loffset == fsize)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje flags = SM_DONTNEED;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje else
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje flags = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = segmap_release(segkmap, base, flags);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje } else
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje (void) segmap_release(segkmap, base, 0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje } while (!error && uiop->uio_resid);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_getattr(struct vnode *vp, struct vattr *vap, int flags,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cred_t *cred, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *subvp = dp->dc_subvp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int error;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = VOP_GETATTR(subvp, vap, flags, cred, ctp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /* substitute uncompressed size */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vap->va_size = dp->dc_hdr->ch_fsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_setattr(struct vnode *vp, struct vattr *vap, int flags, cred_t *cred,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *subvp = dp->dc_subvp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (VOP_SETATTR(subvp, vap, flags, cred, ctp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_access(struct vnode *vp, int mode, int flags,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cred_t *cred, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *subvp = dp->dc_subvp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (VOP_ACCESS(subvp, mode, flags, cred, ctp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_fsync(vnode_t *vp, int syncflag, cred_t *cred, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_inactive(struct vnode *vp, cred_t *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&vp->v_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(vp->v_count >= 1);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (--vp->v_count != 0) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Somebody accessed the dcnode before we got a chance to
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * remove it. They will remove it when they do a vn_rele.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&vp->v_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&vp->v_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcnode_free(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_fid(struct vnode *vp, struct fid *fidp, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *subvp = dp->dc_subvp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (VOP_FID(subvp, fidp, ctp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_seek(struct vnode *vp, offset_t oof, offset_t *noffp, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *subvp = dp->dc_subvp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (VOP_SEEK(subvp, oof, noffp, ctp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_frlock(struct vnode *vp, int cmd, struct flock64 *bfp, int flag,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje offset_t offset, struct flk_callback *flk_cbp,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cred_t *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
53eed1cb389966d2dd60e74de0933f3b3277dbbdJohn.Zolnowsky@Sun.COM int error;
53eed1cb389966d2dd60e74de0933f3b3277dbbdJohn.Zolnowsky@Sun.COM struct vattr vattr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * If file is being mapped, disallow frlock.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
53eed1cb389966d2dd60e74de0933f3b3277dbbdJohn.Zolnowsky@Sun.COM vattr.va_mask = AT_MODE;
53eed1cb389966d2dd60e74de0933f3b3277dbbdJohn.Zolnowsky@Sun.COM if (error = VOP_GETATTR(dp->dc_subvp, &vattr, 0, cr, ctp))
53eed1cb389966d2dd60e74de0933f3b3277dbbdJohn.Zolnowsky@Sun.COM return (error);
53eed1cb389966d2dd60e74de0933f3b3277dbbdJohn.Zolnowsky@Sun.COM if (dp->dc_mapcnt > 0 && MANDLOCK(vp, vattr.va_mode))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (EAGAIN);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ctp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_getblock_miss(struct vnode *vp, offset_t off, size_t len, struct page **ppp,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct seg *seg, caddr_t addr, enum seg_rw rw, struct cred *cr)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct comphdr *hdr = dp->dc_hdr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct page *pp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct buf *bp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje caddr_t saddr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje off_t cblkno;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t rdoff, rdsize, dsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje long xlen;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int error, zerr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(len == hdr->ch_blksize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Get destination pages and make them addressable
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pp = page_create_va(vp, off, len, PG_WAIT, seg, addr);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje bp = pageio_setup(pp, len, vp, B_READ);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje bp_mapin(bp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * read compressed data from subordinate vnode
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje saddr = kmem_cache_alloc(dp->dc_bufcache, KM_SLEEP);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cblkno = off / len;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje rdoff = hdr->ch_blkmap[cblkno];
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje rdsize = hdr->ch_blkmap[cblkno + 1] - rdoff;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = vn_rdwr(UIO_READ, dp->dc_subvp, saddr, rdsize, rdoff,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje UIO_SYSSPACE, 0, 0, cr, NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (error)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje goto cleanup;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Uncompress
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dsize = len;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje zerr = z_uncompress(bp->b_un.b_addr, &dsize, saddr, dp->dc_zmax);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (zerr != Z_OK) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = EIO;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje goto cleanup;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Handle EOF
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje xlen = hdr->ch_fsize - off;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (xlen < len) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje bzero(bp->b_un.b_addr + xlen, len - xlen);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dsize != xlen)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = EIO;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje } else if (dsize != len)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = EIO;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Clean up
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjecleanup:
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje kmem_cache_free(dp->dc_bufcache, saddr);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pageio_done(bp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *ppp = pp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_getblock(struct vnode *vp, offset_t off, size_t len, struct page **ppp,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct seg *seg, caddr_t addr, enum seg_rw rw, struct cred *cr)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct page *pp, *plist = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje offset_t pgoff;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int rdblk;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * pvn_read_kluster() doesn't quite do what we want, since it
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * thinks sub block reads are ok. Here we always decompress
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * a full block.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Check page cache
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje rdblk = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje for (pgoff = off; pgoff < off + len; pgoff += PAGESIZE) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pp = page_lookup(vp, pgoff, SE_EXCL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (pp == NULL) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje rdblk = 1;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje break;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje page_io_lock(pp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje page_add(&plist, pp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje plist = plist->p_next;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (!rdblk) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *ppp = plist;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0); /* all pages in cache */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Undo any locks so getblock_miss has an open field
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (plist != NULL)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pvn_io_done(plist);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (dc_getblock_miss(vp, off, len, ppp, seg, addr, rw, cr));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfourstatic int
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfourdc_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour{
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour struct vnode *rvp;
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour vp = VTODC(vp)->dc_subvp;
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour if (VOP_REALVP(vp, &rvp, ct) == 0)
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour vp = rvp;
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour *vpp = vp;
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour return (0);
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour}
e38c922ef0e324c6fd8b205270fd97d564f88630Andrew Balfour
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED10*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_getpage(struct vnode *vp, offset_t off, size_t len, uint_t *protp,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct page *pl[], size_t plsz, struct seg *seg, caddr_t addr,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje enum seg_rw rw, struct cred *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct comphdr *hdr = dp->dc_hdr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct page *pp, *plist = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje caddr_t vp_baddr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje offset_t vp_boff, vp_bend;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t bsize = hdr->ch_blksize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int nblks, error;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /* does not support write */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (rw == S_WRITE) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje panic("write attempt on compressed file");
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*NOTREACHED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (protp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *protp = PROT_ALL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * We don't support asynchronous operation at the moment, so
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * just pretend we did it. If the pages are ever actually
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * needed, they'll get brought in then.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (pl == NULL)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Calc block start and end offsets
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp_boff = rounddown(off, bsize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp_bend = roundup(off + len, bsize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp_baddr = (caddr_t)rounddown((uintptr_t)addr, bsize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje nblks = (vp_bend - vp_boff) / bsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje while (nblks--) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = dc_getblock(vp, vp_boff, bsize, &pp, seg, vp_baddr,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje rw, cr);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje page_list_concat(&plist, &pp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp_boff += bsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp_baddr += bsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (!error)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pvn_plist_init(plist, pl, plsz, off, len, rw);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje else
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pvn_read_done(plist, B_ERROR);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * This function should never be called. We need to have it to pass
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * it as an argument to other functions.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_putapage(struct vnode *vp, struct page *pp, u_offset_t *offp, size_t *lenp,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int flags, struct cred *cr)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /* should never happen */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cmn_err(CE_PANIC, "dcfs: dc_putapage: dirty page");
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*NOTREACHED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * The only flags we support are B_INVAL, B_FREE and B_DONTNEED.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * B_INVAL is set by:
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * 1) the MC_SYNC command of memcntl(2) to support the MS_INVALIDATE flag.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * 2) the MC_ADVISE command of memcntl(2) with the MADV_DONTNEED advice
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * which translates to an MC_SYNC with the MS_INVALIDATE flag.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * The B_FREE (as well as the B_DONTNEED) flag is set when the
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * MADV_SEQUENTIAL advice has been used. VOP_PUTPAGE is invoked
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * from SEGVN to release pages behind a pagefault.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED5*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_putpage(struct vnode *vp, offset_t off, size_t len, int flags,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int error = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (vp->v_count == 0) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje panic("dcfs_putpage: bad v_count");
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*NOTREACHED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (vp->v_flag & VNOMAP)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (ENOSYS);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (!vn_has_cached_data(vp)) /* no pages mapped */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (len == 0) /* from 'off' to EOF */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = pvn_vplist_dirty(vp, off, dc_putapage, flags, cr);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje else {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje offset_t io_off;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje se_t se = (flags & (B_INVAL | B_FREE)) ? SE_EXCL : SE_SHARED;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje for (io_off = off; io_off < off + len; io_off += PAGESIZE) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje page_t *pp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * We insist on getting the page only if we are
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * about to invalidate, free or write it and
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * the B_ASYNC flag is not set.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if ((flags & B_INVAL) || ((flags & B_ASYNC) == 0))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pp = page_lookup(vp, io_off, se);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje else
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pp = page_lookup_nowait(vp, io_off, se);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (pp == NULL)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje continue;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Normally pvn_getdirty() should return 0, which
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * impies that it has done the job for us.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * The shouldn't-happen scenario is when it returns 1.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * This means that the page has been modified and
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * needs to be put back.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Since we can't write to a dcfs compressed file,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * we fake a failed I/O and force pvn_write_done()
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * to destroy the page.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (pvn_getdirty(pp, flags) == 1) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cmn_err(CE_NOTE, "dc_putpage: dirty page");
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje pvn_write_done(pp, flags |
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje B_ERROR | B_WRITE | B_INVAL | B_FORCE);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addrp,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *cred, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vattr vattr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct segvn_crargs vn_a;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int error;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (vp->v_flag & VNOMAP)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (ENOSYS);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (off < (offset_t)0 || (offset_t)(off + len) < (offset_t)0)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (ENXIO);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * If file is being locked, disallow mapping.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (error = VOP_GETATTR(VTODC(vp)->dc_subvp, &vattr, 0, cred, ctp))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (vn_has_mandatory_locks(vp, vattr.va_mode))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (EAGAIN);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje as_rangelock(as);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if ((flags & MAP_FIXED) == 0) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje map_addr(addrp, len, off, 1, flags);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (*addrp == NULL) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje as_rangeunlock(as);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (ENOMEM);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje } else {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * User specified address - blow away any previous mappings
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje (void) as_unmap(as, *addrp, len);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.vp = vp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.offset = off;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.type = flags & MAP_TYPE;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.prot = prot;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.maxprot = maxprot;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.flags = flags & ~MAP_TYPE;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.cred = cred;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.amp = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.szc = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_a.lgrp_mem_policy_flags = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = as_map(as, *addrp, len, segvn_create, &vn_a);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje as_rangeunlock(as);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_addmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (vp->v_flag & VNOMAP)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (ENOSYS);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&dp->dc_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_mapcnt += btopr(len);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dp->dc_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedc_delmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t len, uint_t prot, uint_t maxprot, uint_t flags,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct cred *cr, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (vp->v_flag & VNOMAP)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (ENOSYS);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = VTODC(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&dp->dc_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_mapcnt -= btopr(len);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(dp->dc_mapcnt >= 0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dp->dc_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Constructor/destructor routines for dcnodes
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED1*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcnode_constructor(void *buf, void *cdrarg, int kmflags)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = buf;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *vp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
8bd3a292467a7ce00ecf774f887442a82e26e438tomee vp = dp->dc_vp = vn_alloc(kmflags);
8bd3a292467a7ce00ecf774f887442a82e26e438tomee if (vp == NULL) {
8bd3a292467a7ce00ecf774f887442a82e26e438tomee return (-1);
8bd3a292467a7ce00ecf774f887442a82e26e438tomee }
8bd3a292467a7ce00ecf774f887442a82e26e438tomee vp->v_data = dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp->v_type = VREG;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp->v_flag = VNOSWAP;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp->v_vfsp = &dc_vfs;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_setops(vp, dc_vnodeops);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_exists(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_init(&dp->dc_lock, NULL, MUTEX_DEFAULT, NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_mapcnt = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_lrunext = dp->dc_lruprev = NULL;
8bd3a292467a7ce00ecf774f887442a82e26e438tomee dp->dc_hdr = NULL;
8bd3a292467a7ce00ecf774f887442a82e26e438tomee dp->dc_subvp = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*ARGSUSED*/
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcnode_destructor(void *buf, void *cdrarg)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp = buf;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *vp = DCTOV(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_destroy(&dp->dc_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VERIFY(dp->dc_hdr == NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VERIFY(dp->dc_subvp == NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_invalid(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_free(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic struct dcnode *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcnode_alloc(void)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * If the free list is above DCLRUSIZE
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * re-use one from it
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dclru_len < DCLRUSIZE) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = kmem_cache_alloc(dcnode_cache, KM_SLEEP);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje } else {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(dclru != NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = dclru;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru_sub(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcdelete(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcnode_recycle(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcnode_free(struct dcnode *dp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *vp = DCTOV(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(MUTEX_HELD(&dctable_lock));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * If no cached pages, no need to put it on lru
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (!vn_has_cached_data(vp)) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcdelete(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcnode_recycle(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje kmem_cache_free(dcnode_cache, dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Add to lru, if it's over the limit, free from head
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru_add(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dclru_len > DCLRUSIZE) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = dclru;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru_sub(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcdelete(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcnode_recycle(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje kmem_cache_free(dcnode_cache, dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcnode_recycle(struct dcnode *dp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vnode *vp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp = DCTOV(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VN_RELE(dp->dc_subvp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_subvp = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje (void) pvn_vplist_dirty(vp, 0, dc_putapage, B_INVAL, NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje kmem_free(dp->dc_hdr, dp->dc_hdrsize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_hdr = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_hdrsize = dp->dc_zmax = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_bufcache = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_mapcnt = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vn_reinit(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp->v_type = VREG;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp->v_flag = VNOSWAP;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje vp->v_vfsp = &dc_vfs;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcinit(int fstype, char *name)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje static const fs_operation_def_t dc_vfsops_template[] = {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje NULL, NULL
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje };
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int error;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje major_t dev;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = vfs_setfsops(fstype, dc_vfsops_template, &dc_vfsops);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (error) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cmn_err(CE_WARN, "dcinit: bad vfs ops template");
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VFS_INIT(&dc_vfs, dc_vfsops, NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dc_vfs.vfs_flag = VFS_RDONLY;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dc_vfs.vfs_fstype = fstype;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if ((dev = getudev()) == (major_t)-1)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dev = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcdev = makedevice(dev, 0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dc_vfs.vfs_dev = dcdev;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = vn_make_ops(name, dc_vnodeops_template, &dc_vnodeops);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (error != 0) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje (void) vfs_freevfsops_by_type(fstype);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cmn_err(CE_WARN, "dcinit: bad vnode ops template");
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (error);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_init(&dctable_lock, NULL, MUTEX_DEFAULT, NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_init(&dccache_lock, NULL, MUTEX_DEFAULT, NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcnode_cache = kmem_cache_create("dcnode_cache", sizeof (struct dcnode),
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje 0, dcnode_constructor, dcnode_destructor, NULL, NULL, NULL, 0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Return shadow vnode with the given vp as its subordinate
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestruct vnode *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedecompvp(struct vnode *vp, cred_t *cred, caller_context_t *ctp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp, *ndp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct comphdr thdr, *hdr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct kmem_cache **cpp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct vattr vattr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje size_t hdrsize, bsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int error;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * See if we have an existing shadow
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * If none, we have to manufacture one
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = dcfind(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dp != NULL)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (DCTOV(dp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Make sure it's a valid compressed file
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje hdr = &thdr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = vn_rdwr(UIO_READ, vp, (caddr_t)hdr, sizeof (struct comphdr), 0,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje UIO_SYSSPACE, 0, 0, cred, NULL);
1d7f3fadeebf3754e3f042d91e7a4439755dc598Krishnendu Sadhukhan - Sun Microsystems if (error || hdr->ch_magic != CH_MAGIC_ZLIB ||
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje hdr->ch_version != CH_VERSION || hdr->ch_algorithm != CH_ALG_ZLIB ||
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje hdr->ch_fsize == 0 || hdr->ch_blksize < PAGESIZE ||
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek hdr->ch_blksize > ptob(DCCACHESIZE) || !ISP2(hdr->ch_blksize))
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /* get underlying file size */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (VOP_GETATTR(vp, &vattr, 0, cred, ctp) != 0)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Re-read entire header
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje hdrsize = hdr->ch_blkmap[0] + sizeof (uint64_t);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje hdr = kmem_alloc(hdrsize, KM_SLEEP);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje error = vn_rdwr(UIO_READ, vp, (caddr_t)hdr, hdrsize, 0, UIO_SYSSPACE,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje 0, 0, cred, NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (error) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje kmem_free(hdr, hdrsize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * add extra blkmap entry to make dc_getblock()'s
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * life easier
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje bsize = hdr->ch_blksize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje hdr->ch_blkmap[((hdr->ch_fsize-1) / bsize) + 1] = vattr.va_size;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ndp = dcnode_alloc();
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ndp->dc_subvp = vp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VN_HOLD(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ndp->dc_hdr = hdr;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ndp->dc_hdrsize = hdrsize;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Allocate kmem cache if none there already
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ndp->dc_zmax = ZMAXBUF(bsize);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje cpp = &dcbuf_cache[btop(bsize)];
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&dccache_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (*cpp == NULL)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje *cpp = kmem_cache_create("dcbuf_cache", ndp->dc_zmax, 0, NULL,
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje NULL, NULL, NULL, NULL, 0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dccache_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ndp->dc_bufcache = *cpp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Recheck table in case someone else created shadow
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * while we were blocked above.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_enter(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = dcfind(vp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dp != NULL) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcnode_recycle(ndp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje kmem_cache_free(dcnode_cache, ndp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (DCTOV(dp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dcinsert(ndp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje mutex_exit(&dctable_lock);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (DCTOV(ndp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * dcnode lookup table
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * These routines maintain a table of dcnodes hashed by their
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * subordinate vnode so that they can be found if they already
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * exist in the vnode cache
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Put a dcnode in the table.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcinsert(struct dcnode *newdp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int idx = DCHASH(newdp->dc_subvp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(MUTEX_HELD(&dctable_lock));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje newdp->dc_hash = dctable[idx];
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dctable[idx] = newdp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Remove a dcnode from the hash table.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjevoid
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcdelete(struct dcnode *deldp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int idx = DCHASH(deldp->dc_subvp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp, *prevdp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(MUTEX_HELD(&dctable_lock));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp = dctable[idx];
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dp == deldp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dctable[idx] = dp->dc_hash;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje else {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje for (prevdp = dp, dp = dp->dc_hash; dp != NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje prevdp = dp, dp = dp->dc_hash) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dp == deldp) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje prevdp->dc_hash = dp->dc_hash;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje break;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(dp != NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje/*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Find a shadow vnode in the dctable hash list.
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic struct dcnode *
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedcfind(struct vnode *vp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(MUTEX_HELD(&dctable_lock));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje for (dp = dctable[DCHASH(vp)]; dp != NULL; dp = dp->dc_hash)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dp->dc_subvp == vp) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje VN_HOLD(DCTOV(dp));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dp->dc_lrunext)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru_sub(dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (dp);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (NULL);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#ifdef DEBUG
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic int
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedclru_count(void)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje int i = 0;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dclru == NULL)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (0);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje for (dp = dclru; dp->dc_lrunext != dclru; dp = dp->dc_lrunext)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje i++;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje return (i + 1);
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje#endif
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedclru_add(struct dcnode *dp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje /*
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje * Add to dclru as double-link chain
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje */
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(MUTEX_HELD(&dctable_lock));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dclru == NULL) {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru = dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_lruprev = dp->dc_lrunext = dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje } else {
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje struct dcnode *last = dclru->dc_lruprev;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru->dc_lruprev = dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje last->dc_lrunext = dp;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_lruprev = last;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_lrunext = dclru;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje }
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru_len++;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(dclru_len == dclru_count());
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjestatic void
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setjedclru_sub(struct dcnode *dp)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje{
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(MUTEX_HELD(&dctable_lock));
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_lrunext->dc_lruprev = dp->dc_lruprev;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_lruprev->dc_lrunext = dp->dc_lrunext;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje if (dp == dclru)
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru = dp->dc_lrunext == dp ? NULL : dp->dc_lrunext;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dp->dc_lrunext = dp->dc_lruprev = NULL;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje dclru_len--;
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje ASSERT(dclru_len == dclru_count());
986fd29a0dc13f7608ef7f508f6e700bd7bc2720setje}