a237e38e9161f0acd6451439d4a7dd597e66291dth/*
a237e38e9161f0acd6451439d4a7dd597e66291dth * CDDL HEADER START
a237e38e9161f0acd6451439d4a7dd597e66291dth *
a237e38e9161f0acd6451439d4a7dd597e66291dth * The contents of this file are subject to the terms of the
a237e38e9161f0acd6451439d4a7dd597e66291dth * Common Development and Distribution License (the "License").
a237e38e9161f0acd6451439d4a7dd597e66291dth * You may not use this file except in compliance with the License.
a237e38e9161f0acd6451439d4a7dd597e66291dth *
a237e38e9161f0acd6451439d4a7dd597e66291dth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a237e38e9161f0acd6451439d4a7dd597e66291dth * or http://www.opensolaris.org/os/licensing.
a237e38e9161f0acd6451439d4a7dd597e66291dth * See the License for the specific language governing permissions
a237e38e9161f0acd6451439d4a7dd597e66291dth * and limitations under the License.
a237e38e9161f0acd6451439d4a7dd597e66291dth *
a237e38e9161f0acd6451439d4a7dd597e66291dth * When distributing Covered Code, include this CDDL HEADER in each
a237e38e9161f0acd6451439d4a7dd597e66291dth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a237e38e9161f0acd6451439d4a7dd597e66291dth * If applicable, add the following below this CDDL HEADER, with the
a237e38e9161f0acd6451439d4a7dd597e66291dth * fields enclosed by brackets "[]" replaced with your own identifying
a237e38e9161f0acd6451439d4a7dd597e66291dth * information: Portions Copyright [yyyy] [name of copyright owner]
a237e38e9161f0acd6451439d4a7dd597e66291dth *
a237e38e9161f0acd6451439d4a7dd597e66291dth * CDDL HEADER END
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth/*
0616fd7f2fe52dfe4b6189a7f510069a5b2aed73Pavel Filipensky * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/types.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/types32.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/param.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/systm.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <rpc/types.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/vfs.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/siginfo.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/proc.h> /* for exit() declaration */
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/kmem.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/pathname.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/debug.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/vtrace.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/cmn_err.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sys/atomic.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/policy.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth#include <sharefs/sharefs.h>
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth/*
a237e38e9161f0acd6451439d4a7dd597e66291dth * A macro to avoid cut-and-paste errors on getting a string field
a237e38e9161f0acd6451439d4a7dd597e66291dth * from user-land.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth#define SHARETAB_COPYIN(field) \
a237e38e9161f0acd6451439d4a7dd597e66291dth if (copyinstr(STRUCT_FGETP(u_sh, sh_##field), \
a237e38e9161f0acd6451439d4a7dd597e66291dth buf, \
a237e38e9161f0acd6451439d4a7dd597e66291dth bufsz + 1, /* Add one for extra NUL */ \
a237e38e9161f0acd6451439d4a7dd597e66291dth &len)) { \
a237e38e9161f0acd6451439d4a7dd597e66291dth error = EFAULT; \
a237e38e9161f0acd6451439d4a7dd597e66291dth goto cleanup; \
a237e38e9161f0acd6451439d4a7dd597e66291dth } \
a237e38e9161f0acd6451439d4a7dd597e66291dth /* \
a237e38e9161f0acd6451439d4a7dd597e66291dth * Need to remove 1 because copyinstr() counts the NUL. \
a237e38e9161f0acd6451439d4a7dd597e66291dth */ \
a237e38e9161f0acd6451439d4a7dd597e66291dth len--; \
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_##field = kmem_alloc(len + 1, KM_SLEEP); \
a237e38e9161f0acd6451439d4a7dd597e66291dth bcopy(buf, sh->sh_##field, len); \
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_##field[len] = '\0'; \
a237e38e9161f0acd6451439d4a7dd597e66291dth shl.shl_##field = (int)len; \
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_size += shl.shl_##field; /* Debug counting */
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth#define SHARETAB_DELETE_FIELD(field) \
a237e38e9161f0acd6451439d4a7dd597e66291dth if (sh->sh_##field) { \
a237e38e9161f0acd6451439d4a7dd597e66291dth kmem_free(sh->sh_##field, \
a237e38e9161f0acd6451439d4a7dd597e66291dth shl ? shl->shl_##field + 1 : \
a237e38e9161f0acd6451439d4a7dd597e66291dth strlen(sh->sh_##field) + 1); \
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthsharetab_t *sharefs_sharetab = NULL; /* The incore sharetab. */
a237e38e9161f0acd6451439d4a7dd597e66291dthsize_t sharetab_size;
a237e38e9161f0acd6451439d4a7dd597e66291dthuint_t sharetab_count;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthkrwlock_t sharetab_lock; /* lock to protect the cached sharetab */
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthkrwlock_t sharefs_lock; /* lock to protect the vnode ops */
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthtimestruc_t sharetab_mtime;
a237e38e9161f0acd6451439d4a7dd597e66291dthtimestruc_t sharetab_snap_time;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthuint_t sharetab_generation; /* Only increments and wraps! */
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth/*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Take care of cleaning up a share.
a237e38e9161f0acd6451439d4a7dd597e66291dth * If passed in a length array, use it to determine how much
a237e38e9161f0acd6451439d4a7dd597e66291dth * space to clean up. Else, figure that out.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic void
a237e38e9161f0acd6451439d4a7dd597e66291dthsharefree(share_t *sh, sharefs_lens_t *shl)
a237e38e9161f0acd6451439d4a7dd597e66291dth{
a237e38e9161f0acd6451439d4a7dd597e66291dth if (!sh)
a237e38e9161f0acd6451439d4a7dd597e66291dth return;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_DELETE_FIELD(path);
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_DELETE_FIELD(res);
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_DELETE_FIELD(fstype);
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_DELETE_FIELD(opts);
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_DELETE_FIELD(descr);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth kmem_free(sh, sizeof (share_t));
a237e38e9161f0acd6451439d4a7dd597e66291dth}
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth/*
a237e38e9161f0acd6451439d4a7dd597e66291dth * If there is no error, then this function is responsible for
a237e38e9161f0acd6451439d4a7dd597e66291dth * cleaning up the memory associated with the share argument.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int
a237e38e9161f0acd6451439d4a7dd597e66291dthsharefs_remove(share_t *sh, sharefs_lens_t *shl)
a237e38e9161f0acd6451439d4a7dd597e66291dth{
a237e38e9161f0acd6451439d4a7dd597e66291dth int iHash;
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_t *sht;
a237e38e9161f0acd6451439d4a7dd597e66291dth share_t *s, *p;
a237e38e9161f0acd6451439d4a7dd597e66291dth int iPath;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth if (!sh)
a237e38e9161f0acd6451439d4a7dd597e66291dth return (ENOENT);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_enter(&sharetab_lock, RW_WRITER);
a237e38e9161f0acd6451439d4a7dd597e66291dth for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
a237e38e9161f0acd6451439d4a7dd597e66291dth if (strcmp(sh->sh_fstype, sht->s_fstype) == 0) {
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * There does not exist a fstype in memory which
a237e38e9161f0acd6451439d4a7dd597e66291dth * matches the share passed in.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth if (!sht) {
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_exit(&sharetab_lock);
a237e38e9161f0acd6451439d4a7dd597e66291dth return (ENOENT);
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth iPath = shl ? shl->shl_path : strlen(sh->sh_path);
0616fd7f2fe52dfe4b6189a7f510069a5b2aed73Pavel Filipensky iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Now walk down the hash table and find the entry to free!
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s != NULL; s = s->sh_next) {
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * We need exact matches.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth if (strcmp(sh->sh_path, s->sh_path) == 0 &&
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks strlen(s->sh_path) == iPath) {
a237e38e9161f0acd6451439d4a7dd597e66291dth if (p) {
a237e38e9161f0acd6451439d4a7dd597e66291dth p->sh_next = s->sh_next;
a237e38e9161f0acd6451439d4a7dd597e66291dth } else {
a237e38e9161f0acd6451439d4a7dd597e66291dth sht->s_buckets[iHash].ssh_sh = s->sh_next;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth ASSERT(sht->s_buckets[iHash].ssh_count != 0);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&sht->s_buckets[iHash].ssh_count);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&sht->s_count);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_dec_32(&sharetab_count);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth ASSERT(sharetab_size >= s->sh_size);
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_size -= s->sh_size;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth gethrestime(&sharetab_mtime);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&sharetab_generation);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth p = s;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_exit(&sharetab_lock);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth if (!s) {
a237e38e9161f0acd6451439d4a7dd597e66291dth return (ENOENT);
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth s->sh_next = NULL;
a237e38e9161f0acd6451439d4a7dd597e66291dth sharefree(s, NULL);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * We need to free the share for the caller.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth sharefree(sh, shl);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth return (0);
a237e38e9161f0acd6451439d4a7dd597e66291dth}
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth/*
a237e38e9161f0acd6451439d4a7dd597e66291dth * The caller must have allocated memory for us to use.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dthstatic int
a237e38e9161f0acd6451439d4a7dd597e66291dthsharefs_add(share_t *sh, sharefs_lens_t *shl)
a237e38e9161f0acd6451439d4a7dd597e66291dth{
a237e38e9161f0acd6451439d4a7dd597e66291dth int iHash;
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_t *sht;
a237e38e9161f0acd6451439d4a7dd597e66291dth share_t *s, *p;
a237e38e9161f0acd6451439d4a7dd597e66291dth int iPath;
a237e38e9161f0acd6451439d4a7dd597e66291dth int n;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth if (!sh) {
a237e38e9161f0acd6451439d4a7dd597e66291dth return (ENOENT);
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * We need to find the hash buckets for the fstype.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_enter(&sharetab_lock, RW_WRITER);
a237e38e9161f0acd6451439d4a7dd597e66291dth for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
a237e38e9161f0acd6451439d4a7dd597e66291dth if (strcmp(sh->sh_fstype, sht->s_fstype) == 0) {
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Did not exist, so allocate one and add it to the
a237e38e9161f0acd6451439d4a7dd597e66291dth * sharetab.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth if (!sht) {
a237e38e9161f0acd6451439d4a7dd597e66291dth sht = kmem_zalloc(sizeof (*sht), KM_SLEEP);
a237e38e9161f0acd6451439d4a7dd597e66291dth n = strlen(sh->sh_fstype);
a237e38e9161f0acd6451439d4a7dd597e66291dth sht->s_fstype = kmem_zalloc(n + 1, KM_SLEEP);
a237e38e9161f0acd6451439d4a7dd597e66291dth (void) strncpy(sht->s_fstype, sh->sh_fstype, n);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth sht->s_next = sharefs_sharetab;
a237e38e9161f0acd6451439d4a7dd597e66291dth sharefs_sharetab = sht;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Now we need to find where we have to add the entry.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
0616fd7f2fe52dfe4b6189a7f510069a5b2aed73Pavel Filipensky iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth iPath = shl ? shl->shl_path : strlen(sh->sh_path);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth if (shl) {
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_size = shl->shl_path + shl->shl_res +
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks shl->shl_fstype + shl->shl_opts + shl->shl_descr;
a237e38e9161f0acd6451439d4a7dd597e66291dth } else {
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_size = strlen(sh->sh_path) +
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks strlen(sh->sh_res) + strlen(sh->sh_fstype) +
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks strlen(sh->sh_opts) + strlen(sh->sh_descr);
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * We need to account for field seperators and
a237e38e9161f0acd6451439d4a7dd597e66291dth * the EOL.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_size += 5;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Now walk down the hash table and add the new entry!
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s != NULL; s = s->sh_next) {
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * We need exact matches.
a237e38e9161f0acd6451439d4a7dd597e66291dth *
a237e38e9161f0acd6451439d4a7dd597e66291dth * We found a matching path. Either we have a
a237e38e9161f0acd6451439d4a7dd597e66291dth * duplicate path in a share command or we are
a237e38e9161f0acd6451439d4a7dd597e66291dth * being asked to replace an existing entry.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth if (strcmp(sh->sh_path, s->sh_path) == 0 &&
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks strlen(s->sh_path) == iPath) {
a237e38e9161f0acd6451439d4a7dd597e66291dth if (p) {
a237e38e9161f0acd6451439d4a7dd597e66291dth p->sh_next = sh;
a237e38e9161f0acd6451439d4a7dd597e66291dth } else {
a237e38e9161f0acd6451439d4a7dd597e66291dth sht->s_buckets[iHash].ssh_sh = sh;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_next = s->sh_next;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth ASSERT(sharetab_size >= s->sh_size);
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_size -= s->sh_size;
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_size += sh->sh_size;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Get rid of the old node.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth sharefree(s, NULL);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth gethrestime(&sharetab_mtime);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&sharetab_generation);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth ASSERT(sht->s_buckets[iHash].ssh_count != 0);
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_exit(&sharetab_lock);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth return (0);
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth p = s;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Okay, we have gone through the entire hash chain and not
a237e38e9161f0acd6451439d4a7dd597e66291dth * found a match. We just need to add this node.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth sh->sh_next = sht->s_buckets[iHash].ssh_sh;
a237e38e9161f0acd6451439d4a7dd597e66291dth sht->s_buckets[iHash].ssh_sh = sh;
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&sht->s_buckets[iHash].ssh_count);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&sht->s_count);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&sharetab_count);
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_size += sh->sh_size;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth gethrestime(&sharetab_mtime);
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_32(&sharetab_generation);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_exit(&sharetab_lock);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth return (0);
a237e38e9161f0acd6451439d4a7dd597e66291dth}
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthvoid
a237e38e9161f0acd6451439d4a7dd597e66291dthsharefs_sharetab_init(void)
a237e38e9161f0acd6451439d4a7dd597e66291dth{
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_init(&sharetab_lock, NULL, RW_DEFAULT, NULL);
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_init(&sharefs_lock, NULL, RW_DEFAULT, NULL);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_size = 0;
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_count = 0;
a237e38e9161f0acd6451439d4a7dd597e66291dth sharetab_generation = 1;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth gethrestime(&sharetab_mtime);
a237e38e9161f0acd6451439d4a7dd597e66291dth gethrestime(&sharetab_snap_time);
a237e38e9161f0acd6451439d4a7dd597e66291dth}
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthint
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarkssharefs_impl(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
a237e38e9161f0acd6451439d4a7dd597e66291dth{
a237e38e9161f0acd6451439d4a7dd597e66291dth int error = 0;
a237e38e9161f0acd6451439d4a7dd597e66291dth size_t len;
a237e38e9161f0acd6451439d4a7dd597e66291dth size_t bufsz;
a237e38e9161f0acd6451439d4a7dd597e66291dth share_t *sh;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth sharefs_lens_t shl;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth model_t model;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth char *buf = NULL;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth STRUCT_DECL(share, u_sh);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth bufsz = iMaxLen;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Before we do anything, lets make sure we have
a237e38e9161f0acd6451439d4a7dd597e66291dth * a sharetab in memory if we need one.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_enter(&sharetab_lock, RW_READER);
a237e38e9161f0acd6451439d4a7dd597e66291dth switch (opcode) {
a237e38e9161f0acd6451439d4a7dd597e66291dth case (SHAREFS_REMOVE) :
a237e38e9161f0acd6451439d4a7dd597e66291dth case (SHAREFS_REPLACE) :
a237e38e9161f0acd6451439d4a7dd597e66291dth if (!sharefs_sharetab) {
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_exit(&sharetab_lock);
a237e38e9161f0acd6451439d4a7dd597e66291dth return (set_errno(ENOENT));
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth case (SHAREFS_ADD) :
a237e38e9161f0acd6451439d4a7dd597e66291dth default :
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth rw_exit(&sharetab_lock);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth model = get_udatamodel();
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Initialize the data pointers.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth STRUCT_INIT(u_sh, model);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (copyin(sh_in, STRUCT_BUF(u_sh), STRUCT_SIZE(u_sh))) {
a237e38e9161f0acd6451439d4a7dd597e66291dth return (set_errno(EFAULT));
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Get the share.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth sh = kmem_zalloc(sizeof (share_t), KM_SLEEP);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Get some storage for copying in the strings.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth buf = kmem_zalloc(bufsz + 1, KM_SLEEP);
a237e38e9161f0acd6451439d4a7dd597e66291dth bzero(&shl, sizeof (sharefs_lens_t));
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * Only grab these two until we know what we want.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_COPYIN(path);
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_COPYIN(fstype);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth switch (opcode) {
a237e38e9161f0acd6451439d4a7dd597e66291dth case (SHAREFS_ADD) :
a237e38e9161f0acd6451439d4a7dd597e66291dth case (SHAREFS_REPLACE) :
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_COPYIN(res);
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_COPYIN(opts);
a237e38e9161f0acd6451439d4a7dd597e66291dth SHARETAB_COPYIN(descr);
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth error = sharefs_add(sh, &shl);
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth case (SHAREFS_REMOVE) :
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth error = sharefs_remove(sh, &shl);
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth default:
a237e38e9161f0acd6451439d4a7dd597e66291dth error = EINVAL;
a237e38e9161f0acd6451439d4a7dd597e66291dth break;
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dthcleanup:
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth /*
a237e38e9161f0acd6451439d4a7dd597e66291dth * If there is no error, then we have stashed the structure
a237e38e9161f0acd6451439d4a7dd597e66291dth * away in the sharetab hash table or have deleted it.
a237e38e9161f0acd6451439d4a7dd597e66291dth *
a237e38e9161f0acd6451439d4a7dd597e66291dth * Either way, the only reason to blow away the data is if
a237e38e9161f0acd6451439d4a7dd597e66291dth * there was an error.
a237e38e9161f0acd6451439d4a7dd597e66291dth */
a237e38e9161f0acd6451439d4a7dd597e66291dth if (error != 0) {
a237e38e9161f0acd6451439d4a7dd597e66291dth sharefree(sh, &shl);
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth if (buf) {
a237e38e9161f0acd6451439d4a7dd597e66291dth kmem_free(buf, bufsz + 1);
a237e38e9161f0acd6451439d4a7dd597e66291dth }
a237e38e9161f0acd6451439d4a7dd597e66291dth
a237e38e9161f0acd6451439d4a7dd597e66291dth return ((error != 0) ? set_errno(error) : 0);
a237e38e9161f0acd6451439d4a7dd597e66291dth}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksint
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarkssharefs(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (secpolicy_sys_config(CRED(), B_FALSE) != 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (set_errno(EPERM));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (sharefs_impl(opcode, sh_in, iMaxLen));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}