usr/src/uts/common/fs/nfs/nfs4_callback.c
author jpk
Fri, 24 Mar 2006 12:29:20 -0800
changeset 1676 37f4a3e2bd99
parent 1665 c2118a3da4a0
child 4033 ce32e5a0eea0
permissions -rw-r--r--
PSARC/2002/762 Layered Trusted Solaris PSARC/2005/060 TSNET: Trusted Networking with Security Labels PSARC/2005/259 Layered Trusted Solaris Label Interfaces PSARC/2005/573 Solaris Trusted Extensions for Printing PSARC/2005/691 Trusted Extensions for Device Allocation PSARC/2005/723 Solaris Trusted Extensions Filesystem Labeling PSARC/2006/009 Labeled Auditing PSARC/2006/155 Trusted Extensions RBAC Changes PSARC/2006/191 is_system_labeled 6293271 Zone processes should use zone_kcred instead of kcred 6394554 integrate Solaris Trusted Extensions
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1649
be48c32b76e8 6378538 nfsv4 client hung waiting for nfs4_server_lst_lock
dm120769
parents: 1232
diff changeset
     5
 * Common Development and Distribution License (the "License").
be48c32b76e8 6378538 nfsv4 client hung waiting for nfs4_server_lst_lock
dm120769
parents: 1232
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
/*
1232
1a9b1651d839 4799697 nfs messages could be more useful
robinson
parents: 766
diff changeset
    22
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
/* All Rights Reserved */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/cred.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/vfs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/vnode.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/pathname.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/kstat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/mkdev.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/mount.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/statvfs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/utsname.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <sys/bootconf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/modctl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/acl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/flock.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/kstr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/stropts.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <sys/strsubr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <sys/atomic.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <sys/disp.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include <sys/policy.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <sys/list.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <sys/zone.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <rpc/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <rpc/auth.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <rpc/rpcsec_gss.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <rpc/clnt.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <rpc/xdr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <nfs/nfs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <nfs/nfs_clnt.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
#include <nfs/mount.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <nfs/nfs_acl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <fs/fs_subr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#include <nfs/nfs4.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
#include <nfs/rnode4.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#include <nfs/nfs4_clnt.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
#include <nfs/nfssys.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 * These are "special" state IDs and file handles that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 * match any delegation state ID or file handled.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 * is for testing purposes only.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
stateid4 nfs4_deleg_any = { 0x7FFFFFF0 };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
char nfs4_deleg_fh[] = "\0377\0376\0375\0374";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
nfs_fh4 nfs4_deleg_anyfh = { sizeof (nfs4_deleg_fh)-1, nfs4_deleg_fh };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
int nfs4_deleg_accept_phony = OPEN_DELEGATE_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
nfsace4 nfs4_deleg_ace_phony;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
nfs_space_limit4 nfs4_deleg_space_phony = { NFS_LIMIT_SIZE, 8192 };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
nfs_space_limit4 nfs4_deleg_space_phony2 = { NFS_LIMIT_BLOCKS, 0 };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
nfs_modified_limit4 nfs4_deleg_space_phonyl = { 8, 512 };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
changeid4 nfs4_deleg_change_phony = 0x7eeeeeee76666660LL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
int nfs4_use_phony_limit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
int nfs4_use_phony_recall;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
int nfs4_phony_recall_v;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
nfsstat4 cb4_getattr_fail = NFS4_OK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
nfsstat4 cb4_recall_fail = NFS4_OK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
int nfs4_callback_debug;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
int nfs4_recall_debug;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
int nfs4_drat_debug;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
#define	CB_NOTE(x)	NFS4_DEBUG(nfs4_callback_debug, (CE_NOTE, x))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
#define	CB_WARN(x)	NFS4_DEBUG(nfs4_callback_debug, (CE_WARN, x))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
#define	CB_WARN1(x, y)	NFS4_DEBUG(nfs4_callback_debug, (CE_WARN, x, y))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
enum nfs4_delegreturn_policy nfs4_delegreturn_policy = INACTIVE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
static zone_key_t nfs4_callback_zone_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
 * NFS4_MAPSIZE is the number of bytes we are willing to consume
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
 * for the block allocation map when the server grants a NFS_LIMIT_BLOCK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
 * style delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
#define	NFS4_MAPSIZE	8192
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
#define	NFS4_MAPWORDS	NFS4_MAPSIZE/sizeof (uint_t)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
#define	NbPW		(NBBY*sizeof (uint_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
static int nfs4_num_prognums = 1024;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
static SVC_CALLOUT_TABLE nfs4_cb_sct;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
struct nfs4_dnode {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	list_node_t	linkage;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
	rnode4_t	*rnodep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
	int		flags;		/* Flags for nfs4delegreturn_impl() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
static const struct nfs4_callback_stats nfs4_callback_stats_tmpl = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	{ "delegations",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	{ "cb_getattr",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	{ "cb_recall",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	{ "cb_null",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	{ "cb_dispatch",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	{ "delegaccept_r",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	{ "delegaccept_rw",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
	{ "delegreturn",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	{ "callbacks",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
	{ "claim_cur",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	{ "claim_cur_ok",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	{ "recall_trunc",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	{ "recall_failed",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	{ "return_limit_write",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
	{ "return_limit_addmap", KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
	{ "deleg_recover",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
	{ "cb_illegal",		KSTAT_DATA_UINT64 }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
struct nfs4_cb_port {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
	list_node_t		linkage; /* linkage into per-zone port list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
	char			netid[KNC_STRSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	char			uaddr[KNC_STRSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	char			protofmly[KNC_STRSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	char			proto[KNC_STRSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
static int cb_getattr_bytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
struct cb_recall_pass {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	rnode4_t	*rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	int		flags;		/* Flags for nfs4delegreturn_impl() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	bool_t		truncate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
static nfs4_open_stream_t *get_next_deleg_stream(rnode4_t *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
static void nfs4delegreturn_thread(struct cb_recall_pass *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
static int deleg_reopen(vnode_t *, bool_t *, struct nfs4_callback_globals *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
    int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
static void nfs4_dlistadd(rnode4_t *, struct nfs4_callback_globals *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
static void nfs4_dlistclean_impl(struct nfs4_callback_globals *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
static int nfs4delegreturn_impl(rnode4_t *, int,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
    struct nfs4_callback_globals *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
static void nfs4delegreturn_cleanup_impl(rnode4_t *, nfs4_server_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
    struct nfs4_callback_globals *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
cb_getattr(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
	struct compound_state *cs, struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
	CB_GETATTR4args *args = &argop->nfs_cb_argop4_u.opcbgetattr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
	CB_GETATTR4res *resp = &resop->nfs_cb_resop4_u.opcbgetattr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
	bool_t found = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
	struct nfs4_server *sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
	struct fattr4 *fap;
1232
1a9b1651d839 4799697 nfs messages could be more useful
robinson
parents: 766
diff changeset
   192
	rpc_inline_t *fdata;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	long mapcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
	fattr4_change change;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
	fattr4_size size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
	uint_t rflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
	ncg->nfs4_callback_stats.cb_getattr.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	 * error injection hook: set cb_getattr_fail global to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	 * NFS4 pcol error to be returned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	if (cb4_getattr_fail != NFS4_OK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
		*cs->statusp = resp->status = cb4_getattr_fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	resp->obj_attributes.attrmask = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	sp = ncg->nfs4prog2server[req->rq_prog - NFS4_CALLBACK];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
	if (nfs4_server_vlock(sp, 0) == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
		CB_WARN("cb_getattr: cannot find server\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
		*cs->statusp = resp->status = NFS4ERR_BADHANDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
	 * In cb_compound, callback_ident was validated against rq_prog,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
	 * but we couldn't verify that it was set to the value we provided
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
	 * at setclientid time (because we didn't have server struct yet).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
	 * Now we have the server struct, but don't have callback_ident
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
	 * handy.  So, validate server struct program number against req
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
	 * RPC's prog number.  At this point, we know the RPC prog num
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
	 * is valid (else we wouldn't be here); however, we don't know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
	 * that it was the prog number we supplied to this server at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
	 * setclientid time.  If the prog numbers aren't equivalent, then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
	 * log the problem and fail the request because either cbserv
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
	 * and/or cbclient are confused.  This will probably never happen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
	if (sp->s_program != req->rq_prog) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
		zcmn_err(getzoneid(), CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
		    "cb_getattr: wrong server program number srv=%d req=%d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
		    sp->s_program, req->rq_prog);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
		zcmn_err(getzoneid(), CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
		    "cb_getattr: wrong server program number\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
		mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
		nfs4_server_rele(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
		*cs->statusp = resp->status = NFS4ERR_BADHANDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	 * Search the delegation list for a matching file handle;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
	 * mutex on sp prevents the list from changing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
	rp = list_head(&sp->s_deleg_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
	for (; rp != NULL; rp = list_next(&sp->s_deleg_list, rp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
		nfs4_fhandle_t fhandle;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
		sfh4_copyval(rp->r_fh, &fhandle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
		if ((fhandle.fh_len == args->fh.nfs_fh4_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
		    bcmp(fhandle.fh_buf, args->fh.nfs_fh4_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
		    fhandle.fh_len) == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
			found = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
		if (nfs4_deleg_anyfh.nfs_fh4_len == args->fh.nfs_fh4_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
		    bcmp(nfs4_deleg_anyfh.nfs_fh4_val, args->fh.nfs_fh4_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
		    args->fh.nfs_fh4_len) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
			found = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
	 * VN_HOLD the vnode before releasing s_lock to guarantee
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
	 * we have a valid vnode reference.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
	if (found == TRUE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
		vp = RTOV4(rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
		VN_HOLD(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
	mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
	nfs4_server_rele(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
	if (found == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
		CB_WARN("cb_getattr: bad fhandle\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
		*cs->statusp = resp->status = NFS4ERR_BADHANDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
	 * Figure out which attributes the server wants.  We only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
	 * offer FATTR4_CHANGE & FATTR4_SIZE; ignore the rest.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
	fdata = kmem_alloc(cb_getattr_bytes, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
	 * Don't actually need to create XDR to encode these
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
	 * simple data structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
	 * xdrmem_create(&xdr, fdata, cb_getattr_bytes, XDR_ENCODE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
	fap = &resp->obj_attributes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
	fap->attrmask = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
	/* attrlist4_len starts at 0 and increases as attrs are processed */
1232
1a9b1651d839 4799697 nfs messages could be more useful
robinson
parents: 766
diff changeset
   317
	fap->attrlist4 = (char *)fdata;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	fap->attrlist4_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	/* don't supply attrs if request was zero */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
	if (args->attr_request != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
		if (args->attr_request & FATTR4_CHANGE_MASK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
			 * If the file is mmapped, then increment the change
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
			 * attribute and return it.  This will guarantee that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
			 * the server will perceive that the file has changed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
			 * if there is any chance that the client application
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
			 * has changed it.  Otherwise, just return the change
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
			 * attribute as it has been updated by nfs4write_deleg.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
			mutex_enter(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
			mapcnt = rp->r_mapcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
			rflag = rp->r_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
			mutex_exit(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
			mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
			 * If object mapped, then always return new change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
			 * Otherwise, return change if object has dirty
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
			 * pages.  If object doesn't have any dirty pages,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
			 * then all changes have been pushed to server, so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
			 * reset change to grant change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
			if (mapcnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
				rp->r_deleg_change++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
			else if (! (rflag & R4DIRTY))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
				rp->r_deleg_change = rp->r_deleg_change_grant;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
			change = rp->r_deleg_change;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
			mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
			 * Use inline XDR code directly, we know that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
			 * going to a memory buffer and it has enough
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
			 * space so it cannot fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
			IXDR_PUT_U_HYPER(fdata, change);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
			fap->attrlist4_len += 2 * BYTES_PER_XDR_UNIT;
1232
1a9b1651d839 4799697 nfs messages could be more useful
robinson
parents: 766
diff changeset
   359
			fap->attrmask |= FATTR4_CHANGE_MASK;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
		if (args->attr_request & FATTR4_SIZE_MASK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
			 * Use an atomic add of 0 to fetch a consistent view
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
			 * of r_size; this avoids having to take rw_lock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
			 * which could cause a deadlock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
			size = atomic_add_64_nv((uint64_t *)&rp->r_size, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
			 * Use inline XDR code directly, we know that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
			 * going to a memory buffer and it has enough
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
			 * space so it cannot fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
			IXDR_PUT_U_HYPER(fdata, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
			fap->attrlist4_len += 2 * BYTES_PER_XDR_UNIT;
1232
1a9b1651d839 4799697 nfs messages could be more useful
robinson
parents: 766
diff changeset
   377
			fap->attrmask |= FATTR4_SIZE_MASK;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
	VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
	*cs->statusp = resp->status = NFS4_OK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
cb_getattr_free(nfs_cb_resop4 *resop)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
	if (resop->nfs_cb_resop4_u.opcbgetattr.obj_attributes.attrlist4)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
		kmem_free(resop->nfs_cb_resop4_u.opcbgetattr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
			obj_attributes.attrlist4,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
			cb_getattr_bytes);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
cb_recall(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	struct compound_state *cs, struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	CB_RECALL4args * args = &argop->nfs_cb_argop4_u.opcbrecall;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	CB_RECALL4res *resp = &resop->nfs_cb_resop4_u.opcbrecall;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
	struct nfs4_server *sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
	bool_t found = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
	ncg->nfs4_callback_stats.cb_recall.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
	ASSERT(req->rq_prog >= NFS4_CALLBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
	ASSERT(req->rq_prog < NFS4_CALLBACK+nfs4_num_prognums);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
	 * error injection hook: set cb_recall_fail global to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
	 * NFS4 pcol error to be returned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
	if (cb4_recall_fail != NFS4_OK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
		*cs->statusp = resp->status = cb4_recall_fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
	mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
	sp = ncg->nfs4prog2server[req->rq_prog - NFS4_CALLBACK];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
	mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	if (nfs4_server_vlock(sp, 0) == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
		CB_WARN("cb_recall: cannot find server\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
		*cs->statusp = resp->status = NFS4ERR_BADHANDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
	 * Search the delegation list for a matching file handle
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
	 * AND stateid; mutex on sp prevents the list from changing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
	rp = list_head(&sp->s_deleg_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
	for (; rp != NULL; rp = list_next(&sp->s_deleg_list, rp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
		mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
		/* check both state id and file handle! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
		if ((bcmp(&rp->r_deleg_stateid, &args->stateid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
		    sizeof (stateid4)) == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
			nfs4_fhandle_t fhandle;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
			sfh4_copyval(rp->r_fh, &fhandle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
			if ((fhandle.fh_len == args->fh.nfs_fh4_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
			    bcmp(fhandle.fh_buf, args->fh.nfs_fh4_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
			    fhandle.fh_len) == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
				found = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
				CB_WARN("cb_recall: stateid OK, bad fh");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
		if (bcmp(&args->stateid, &nfs4_deleg_any,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
		    sizeof (stateid4)) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
			found = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
		mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
	 * VN_HOLD the vnode before releasing s_lock to guarantee
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
	 * we have a valid vnode reference.  The async thread will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
	 * release the hold when it's done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
	if (found == TRUE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
		mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
		vp = RTOV4(rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
		VN_HOLD(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
	mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
	nfs4_server_rele(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
	if (found == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
		CB_WARN("cb_recall: bad stateid\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
	/* Fire up a thread to do the delegreturn */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
	nfs4delegreturn_async(rp, NFS4_DR_RECALL|NFS4_DR_REOPEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
					args->truncate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
	*cs->statusp = resp->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
cb_recall_free(nfs_cb_resop4 *resop)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
	/* nothing to do here, cb_recall doesn't kmem_alloc */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
 * This function handles the CB_NULL proc call from an NFSv4 Server.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
 * We take note that the server has sent a CB_NULL for later processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
 * in the recovery logic. It is noted so we may pause slightly after the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
 * setclientid and before reopening files. The pause is to allow the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
 * NFSv4 Server time to receive the CB_NULL reply and adjust any of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
 * its internal structures such that it has the opportunity to grant
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
 * delegations to reopened files.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
cb_null(CB_COMPOUND4args *args, CB_COMPOUND4res *resp, struct svc_req *req,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
    struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
	struct nfs4_server *sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
	ncg->nfs4_callback_stats.cb_null.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
	ASSERT(req->rq_prog >= NFS4_CALLBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
	ASSERT(req->rq_prog < NFS4_CALLBACK+nfs4_num_prognums);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
	mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
	sp = ncg->nfs4prog2server[req->rq_prog - NFS4_CALLBACK];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
	mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
	if (nfs4_server_vlock(sp, 0) != FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		sp->s_flags |= N4S_CB_PINGED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
		cv_broadcast(&sp->wait_cb_null);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
		nfs4_server_rele(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
 * cb_illegal	args: void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
 *		res : status (NFS4ERR_OP_CB_ILLEGAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
cb_illegal(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	struct compound_state *cs, struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
	CB_ILLEGAL4res *resp = &resop->nfs_cb_resop4_u.opcbillegal;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
	ncg->nfs4_callback_stats.cb_illegal.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
	resop->resop = OP_CB_ILLEGAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
	*cs->statusp = resp->status = NFS4ERR_OP_ILLEGAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
cb_compound(CB_COMPOUND4args *args, CB_COMPOUND4res *resp, struct svc_req *req,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
	struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
	uint_t i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
	struct compound_state cs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
	nfs_cb_argop4 *argop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
	nfs_cb_resop4 *resop, *new_res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
	uint_t op;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	bzero(&cs, sizeof (cs));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	cs.statusp = &resp->status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	cs.cont = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
	 * Form a reply tag by copying over the reqeuest tag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	resp->tag.utf8string_len = args->tag.utf8string_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
	resp->tag.utf8string_val = kmem_alloc(resp->tag.utf8string_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
					KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
	bcopy(args->tag.utf8string_val, resp->tag.utf8string_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
		args->tag.utf8string_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
	 * XXX for now, minorversion should be zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	if (args->minorversion != CB4_MINORVERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
		resp->array_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
		resp->array = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
		resp->status = NFS4ERR_MINOR_VERS_MISMATCH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
	 * Verify callback_ident.  It doesn't really matter if it's wrong
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	 * because we don't really use callback_ident -- we use prog number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	 * of the RPC request instead.  In this case, just print a DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
	 * console message to reveal brokenness of cbclient (at bkoff/cthon).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
	if (args->callback_ident != req->rq_prog)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
		zcmn_err(getzoneid(), CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
		    "cb_compound: cb_client using wrong "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
		    "callback_ident(%d), should be %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
		    args->callback_ident, req->rq_prog);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
	resp->array_len = args->array_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
	resp->array = kmem_zalloc(args->array_len * sizeof (nfs_cb_resop4),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
							KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
	for (i = 0; i < args->array_len && cs.cont; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
		argop = &args->array[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
		resop = &resp->array[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
		resop->resop = argop->argop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
		op = (uint_t)resop->resop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
		switch (op) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
		case OP_CB_GETATTR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
			cb_getattr(argop, resop, req, &cs, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
		case OP_CB_RECALL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
			cb_recall(argop, resop, req, &cs, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
		case OP_CB_ILLEGAL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
			/* fall through */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
			 * Handle OP_CB_ILLEGAL and any undefined opcode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
			 * Currently, the XDR code will return BADXDR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
			 * if cb op doesn't decode to legal value, so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
			 * it really only handles OP_CB_ILLEGAL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
			op = OP_CB_ILLEGAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
			cb_illegal(argop, resop, req, &cs, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
		if (*cs.statusp != NFS4_OK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
			cs.cont = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
		 * If not at last op, and if we are to stop, then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
		 * compact the results array.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
		if ((i + 1) < args->array_len && !cs.cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
			new_res = kmem_alloc(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
				(i+1) * sizeof (nfs_cb_resop4), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
			bcopy(resp->array,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
				new_res, (i+1) * sizeof (nfs_cb_resop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
			kmem_free(resp->array,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
				args->array_len * sizeof (nfs_cb_resop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
			resp->array_len =  i + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
			resp->array = new_res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
cb_compound_free(CB_COMPOUND4res *resp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
	uint_t i, op;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
	nfs_cb_resop4 *resop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	if (resp->tag.utf8string_val) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
		UTF8STRING_FREE(resp->tag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
	for (i = 0; i < resp->array_len; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
		resop = &resp->array[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
		op = (uint_t)resop->resop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
		switch (op) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
		case OP_CB_GETATTR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
			cb_getattr_free(resop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
		case OP_CB_RECALL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
			cb_recall_free(resop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
	if (resp->array != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
		kmem_free(resp->array,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
			resp->array_len * sizeof (nfs_cb_resop4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
cb_dispatch(struct svc_req *req, SVCXPRT *xprt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
	CB_COMPOUND4args args;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
	CB_COMPOUND4res res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
	bool_t (*xdr_args)(), (*xdr_res)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
	void (*proc)(CB_COMPOUND4args *, CB_COMPOUND4res *, struct svc_req *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
	    struct nfs4_callback_globals *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	void (*freeproc)(CB_COMPOUND4res *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
   718
	ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone());
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	ASSERT(ncg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
	ncg->nfs4_callback_stats.cb_dispatch.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
	switch (req->rq_proc) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
	case CB_NULL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
		xdr_args = xdr_void;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
		xdr_res = xdr_void;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
		proc = cb_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
		freeproc = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
	case CB_COMPOUND:
1232
1a9b1651d839 4799697 nfs messages could be more useful
robinson
parents: 766
diff changeset
   732
		xdr_args = xdr_CB_COMPOUND4args_clnt;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
		xdr_res = xdr_CB_COMPOUND4res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
		proc = cb_compound;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		freeproc = cb_compound_free;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
		CB_WARN("cb_dispatch: no proc\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
		svcerr_noproc(xprt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
	args.tag.utf8string_val = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	args.array = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
	if (!SVC_GETARGS(xprt, xdr_args, (caddr_t)&args)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
		CB_WARN("cb_dispatch: cannot getargs\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
		svcerr_decode(xprt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
	(*proc)(&args, &res, req, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
	if (svc_sendreply(xprt, xdr_res, (caddr_t)&res) == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
		CB_WARN("cb_dispatch: bad sendreply\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
		 * svcerr_systemerr(xprt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
	if (freeproc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
		(*freeproc)(&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
	if (!SVC_FREEARGS(xprt, xdr_args, (caddr_t)&args)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
		CB_WARN("cb_dispatch: bad freeargs\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
static rpcprog_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
nfs4_getnextprogram(struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	int i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
	j = ncg->nfs4_program_hint;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
	for (i = 0; i < nfs4_num_prognums; i++, j++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
		if (j >= nfs4_num_prognums)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
			j = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
		if (ncg->nfs4prog2server[j] == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
			ncg->nfs4_program_hint = j+1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
			return (j+NFS4_CALLBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
nfs4callback_destroy(nfs4_server_t *np)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
	if (np->s_program == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
	ncg = np->zone_globals;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
	i = np->s_program - NFS4_CALLBACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
	mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
	ASSERT(ncg->nfs4prog2server[i] == np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	ncg->nfs4prog2server[i] = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
	if (i < ncg->nfs4_program_hint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
		ncg->nfs4_program_hint = i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
	mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
 * nfs4_setport - This function saves a netid and univeral address for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
 * the callback program.  These values will be used during setclientid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
nfs4_setport(char *netid, char *uaddr, char *protofmly, char *proto,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
	struct nfs4_cb_port *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	bool_t found = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	ASSERT(MUTEX_HELD(&ncg->nfs4_cb_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
	p = list_head(&ncg->nfs4_cb_ports);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
	for (; p != NULL; p = list_next(&ncg->nfs4_cb_ports, p)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
		if (strcmp(p->netid, netid) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
			found = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
	if (found == TRUE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
		(void) strcpy(p->uaddr, uaddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
		p = kmem_alloc(sizeof (*p), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
		(void) strcpy(p->uaddr, uaddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
		(void) strcpy(p->netid, netid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
		(void) strcpy(p->protofmly, protofmly);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
		(void) strcpy(p->proto, proto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
		list_insert_head(&ncg->nfs4_cb_ports, p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
 * nfs4_cb_args - This function is used to construct the callback
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
 * portion of the arguments needed for setclientid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
nfs4_cb_args(nfs4_server_t *np, struct knetconfig *knc, SETCLIENTID4args *args)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
	struct nfs4_cb_port *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
	bool_t found = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
	rpcprog_t pgm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
	struct nfs4_callback_globals *ncg = np->zone_globals;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
	 * This server structure may already have a program number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
	 * assigned to it.  This happens when the client has to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
	 * re-issue SETCLIENTID.  Just re-use the information.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
	if (np->s_program >= NFS4_CALLBACK &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
	    np->s_program < NFS4_CALLBACK + nfs4_num_prognums)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
		nfs4callback_destroy(np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
	mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
	p = list_head(&ncg->nfs4_cb_ports);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
	for (; p != NULL; p = list_next(&ncg->nfs4_cb_ports, p)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
		if (strcmp(p->protofmly, knc->knc_protofmly) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
		    strcmp(p->proto, knc->knc_proto) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
			found = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
	if (found == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
		NFS4_DEBUG(nfs4_callback_debug,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
		(CE_WARN, "nfs4_cb_args: could not find netid for %s/%s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
			knc->knc_protofmly, knc->knc_proto));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
		args->callback.cb_program = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
		args->callback.cb_location.r_netid = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
		args->callback.cb_location.r_addr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
		args->callback_ident = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
		mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
	if ((pgm = nfs4_getnextprogram(ncg)) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
		CB_WARN("nfs4_cb_args: out of program numbers\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
		args->callback.cb_program = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
		args->callback.cb_location.r_netid = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
		args->callback.cb_location.r_addr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
		args->callback_ident = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
		mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
	ncg->nfs4prog2server[pgm-NFS4_CALLBACK] = np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
	args->callback.cb_program = pgm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
	args->callback.cb_location.r_netid = p->netid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
	args->callback.cb_location.r_addr = p->uaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
	args->callback_ident = pgm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
	np->s_program = pgm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
	mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
nfs4_dquery(struct nfs4_svc_args *arg, model_t model)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
	file_t *fp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
	STRUCT_HANDLE(nfs4_svc_args, uap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
	STRUCT_SET_HANDLE(uap, model, arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
	if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
		return (EBADF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
	vp = fp->f_vnode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
	if (vp == NULL || vp->v_type != VREG ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
	    !vn_matchops(vp, nfs4_vnodeops)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
		releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
		return (EBADF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
	rp = VTOR4(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
	 * I can't convince myself that we need locking here.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
	 * rnode cannot disappear and the value returned is instantly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
	 * stale anway, so why bother?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
	error = suword32(STRUCT_FGETP(uap, netid), rp->r_deleg_type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
	releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
 * NFS4 client system call.  This service does the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
 * necessary initialization for the callback program.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
 * This is fashioned after the server side interaction
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
 * between nfsd and the kernel.  On the client, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
 * mount command forks and the child process does the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
 * necessary interaction with the kernel.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
 * uap->fd is the fd of an open transport provider
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
nfs4_svc(struct nfs4_svc_args *arg, model_t model)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
	file_t *fp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
	int readsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
	char buf[KNC_STRSIZE], uaddr[KNC_STRSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
	char protofmly[KNC_STRSIZE], proto[KNC_STRSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
	size_t len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
	STRUCT_HANDLE(nfs4_svc_args, uap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
	struct netbuf addrmask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
	int cmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
	SVCMASTERXPRT *cb_xprt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
#ifdef lint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
	model = model;		/* STRUCT macros don't always refer to it */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
	STRUCT_SET_HANDLE(uap, model, arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
	if (STRUCT_FGET(uap, cmd) == NFS4_DQUERY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
		return (nfs4_dquery(arg, model));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
	if (secpolicy_nfs(CRED()) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
		return (EPERM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
	if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
		return (EBADF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
	 * Set read buffer size to rsize
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
	 * and add room for RPC headers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
	readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
	if (readsize < RPC_MAXDATASIZE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
		readsize = RPC_MAXDATASIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
	error = copyinstr((const char *)STRUCT_FGETP(uap, netid), buf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
	    KNC_STRSIZE, &len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
		releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
	cmd = STRUCT_FGET(uap, cmd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
	if (cmd & NFS4_KRPC_START) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
		addrmask.len = STRUCT_FGET(uap, addrmask.len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
		addrmask.maxlen = STRUCT_FGET(uap, addrmask.maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
		addrmask.buf = kmem_alloc(addrmask.maxlen, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
		error = copyin(STRUCT_FGETP(uap, addrmask.buf), addrmask.buf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
		    addrmask.len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
			releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
			kmem_free(addrmask.buf, addrmask.maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
		addrmask.buf = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
	error = copyinstr((const char *)STRUCT_FGETP(uap, addr), uaddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
	    sizeof (uaddr), &len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
		releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
		if (addrmask.buf)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
			kmem_free(addrmask.buf, addrmask.maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
	error = copyinstr((const char *)STRUCT_FGETP(uap, protofmly), protofmly,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
	    sizeof (protofmly), &len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
		releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
		if (addrmask.buf)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
			kmem_free(addrmask.buf, addrmask.maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
	error = copyinstr((const char *)STRUCT_FGETP(uap, proto), proto,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
	    sizeof (proto), &len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
		releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
		if (addrmask.buf)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
			kmem_free(addrmask.buf, addrmask.maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  1055
	ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone());
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
	ASSERT(ncg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
	mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
	if (cmd & NFS4_SETPORT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
		nfs4_setport(buf, uaddr, protofmly, proto, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
	if (cmd & NFS4_KRPC_START) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
		error = svc_tli_kcreate(fp, readsize, buf, &addrmask, &cb_xprt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
		    &nfs4_cb_sct, NULL, NFS_CB_SVCPOOL_ID, FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
			CB_WARN1("nfs4_svc: svc_tli_kcreate failed %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
				error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
			kmem_free(addrmask.buf, addrmask.maxlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
	mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
	releasef(STRUCT_FGET(uap, fd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
struct nfs4_callback_globals *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
nfs4_get_callback_globals(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
{
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  1080
	return (zone_getspecific(nfs4_callback_zone_key, nfs_zone()));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
static void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
nfs4_callback_init_zone(zoneid_t zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
	kstat_t *nfs4_callback_kstat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
	ncg = kmem_zalloc(sizeof (*ncg), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
	ncg->nfs4prog2server = kmem_zalloc(nfs4_num_prognums *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
		sizeof (struct nfs4_server *), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
	/* initialize the dlist */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
	mutex_init(&ncg->nfs4_dlist_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
	list_create(&ncg->nfs4_dlist, sizeof (struct nfs4_dnode),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
	    offsetof(struct nfs4_dnode, linkage));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
	/* initialize cb_port list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
	mutex_init(&ncg->nfs4_cb_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
	list_create(&ncg->nfs4_cb_ports, sizeof (struct nfs4_cb_port),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
	    offsetof(struct nfs4_cb_port, linkage));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
	/* get our own copy of the kstats */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
	bcopy(&nfs4_callback_stats_tmpl, &ncg->nfs4_callback_stats,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
	    sizeof (nfs4_callback_stats_tmpl));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
	/* register "nfs:0:nfs4_callback_stats" for this zone */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
	if ((nfs4_callback_kstat =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
		kstat_create_zone("nfs", 0, "nfs4_callback_stats", "misc",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
		    KSTAT_TYPE_NAMED,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
		    sizeof (ncg->nfs4_callback_stats) / sizeof (kstat_named_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
		    KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
		    zoneid)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
		nfs4_callback_kstat->ks_data = &ncg->nfs4_callback_stats;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
		kstat_install(nfs4_callback_kstat);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
	return (ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
nfs4_discard_delegations(struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
	nfs4_server_t *sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
	int i, num_removed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
	 * It's OK here to just run through the registered "programs", as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
	 * servers without programs won't have any delegations to handle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
	for (i = 0; i < nfs4_num_prognums; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
		rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
		mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
		sp = ncg->nfs4prog2server[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
		mutex_exit(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
		if (nfs4_server_vlock(sp, 1) == FALSE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
		num_removed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
		while ((rp = list_head(&sp->s_deleg_list)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
			mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
			if (rp->r_deleg_type == OPEN_DELEGATE_NONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
				 * We need to take matters into our own hands,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
				 * as nfs4delegreturn_cleanup_impl() won't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
				 * remove this from the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
				list_remove(&sp->s_deleg_list, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
				mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
				nfs4_dec_state_ref_count_nolock(sp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
				    VTOMI4(RTOV4(rp)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
				num_removed++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
			mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
			VN_HOLD(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
			mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
			 * The following will remove the node from the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
			nfs4delegreturn_cleanup_impl(rp, sp, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
			VN_RELE(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
			mutex_enter(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
		mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
		/* each removed list node reles a reference */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
		while (num_removed-- > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
			nfs4_server_rele(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
		/* remove our reference for nfs4_server_vlock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
		nfs4_server_rele(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
nfs4_callback_shutdown_zone(zoneid_t zoneid, void *data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
	struct nfs4_callback_globals *ncg = data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
	 * Clean pending delegation return list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
	nfs4_dlistclean_impl(ncg, NFS4_DR_DISCARD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
	 * Discard all delegations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
	nfs4_discard_delegations(ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
nfs4_callback_fini_zone(zoneid_t zoneid, void *data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
	struct nfs4_callback_globals *ncg = data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
	struct nfs4_cb_port *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
	nfs4_server_t *sp, *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
	nfs4_server_t freelist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
	kstat_delete_byname_zone("nfs", 0, "nfs4_callback_stats", zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
	 * Discard all delegations that may have crept in since we did the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
	 * _shutdown.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
	nfs4_discard_delegations(ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
	 * We're completely done with this zone and all associated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
	 * nfs4_server_t's.  Any remaining nfs4_server_ts should only have one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
	 * more reference outstanding -- the reference we didn't release in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
	 * nfs4_renew_lease_thread().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
	 * Here we need to run through the global nfs4_server_lst as we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
	 * deal with nfs4_server_ts without programs, as they also have threads
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
	 * created for them, and so have outstanding references that we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
	 * release.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
	freelist.forw = &freelist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
	freelist.back = &freelist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
	mutex_enter(&nfs4_server_lst_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
	sp = nfs4_server_lst.forw;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
	while (sp != &nfs4_server_lst) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
		next = sp->forw;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
		if (sp->zoneid == zoneid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
			remque(sp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
			insque(sp, &freelist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
		sp = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
	mutex_exit(&nfs4_server_lst_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
	sp = freelist.forw;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
	while (sp != &freelist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
		next = sp->forw;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
		nfs4_server_rele(sp);	/* free the list's reference */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
		sp = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
	for (i = 0; i < nfs4_num_prognums; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
		ASSERT(ncg->nfs4prog2server[i] == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
	kmem_free(ncg->nfs4prog2server, nfs4_num_prognums *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
	    sizeof (struct nfs4_server *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
	mutex_enter(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
	while ((p = list_head(&ncg->nfs4_cb_ports)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
		list_remove(&ncg->nfs4_cb_ports, p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
		kmem_free(p, sizeof (*p));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
	list_destroy(&ncg->nfs4_cb_ports);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
	mutex_destroy(&ncg->nfs4_cb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
	list_destroy(&ncg->nfs4_dlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
	mutex_destroy(&ncg->nfs4_dlist_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
	kmem_free(ncg, sizeof (*ncg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
nfs4_callback_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
	SVC_CALLOUT *nfs4_cb_sc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
	/* initialize the callback table */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
	nfs4_cb_sc = kmem_alloc(nfs4_num_prognums *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
		sizeof (SVC_CALLOUT), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
	for (i = 0; i < nfs4_num_prognums; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
		nfs4_cb_sc[i].sc_prog = NFS4_CALLBACK+i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
		nfs4_cb_sc[i].sc_versmin = NFS_CB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
		nfs4_cb_sc[i].sc_versmax = NFS_CB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
		nfs4_cb_sc[i].sc_dispatch = cb_dispatch;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
	nfs4_cb_sct.sct_size = nfs4_num_prognums;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
	nfs4_cb_sct.sct_free = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
	nfs4_cb_sct.sct_sc = nfs4_cb_sc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
	 * Compute max bytes required for dyamically allocated parts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
	 * of cb_getattr reply.  Only size and change are supported now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
	 * If CB_GETATTR is changed to reply with additional attrs,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
	 * additional sizes must be added below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
	 * fattr4_change + fattr4_size == uint64_t + uint64_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
	cb_getattr_bytes = 2 * BYTES_PER_XDR_UNIT + 2 * BYTES_PER_XDR_UNIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
	zone_key_create(&nfs4_callback_zone_key, nfs4_callback_init_zone,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
	    nfs4_callback_shutdown_zone, nfs4_callback_fini_zone);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
nfs4_callback_fini(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
 * NB: This function can be called from the *wrong* zone (ie, the zone that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
 * 'rp' belongs to and the caller's zone may not be the same).  This can happen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
 * if the zone is going away and we get called from nfs4_async_inactive().  In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
 * this case the globals will be NULL and we won't update the counters, which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
 * doesn't matter as the zone is going away anyhow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
nfs4delegreturn_cleanup_impl(rnode4_t *rp, nfs4_server_t *np,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
	struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
	mntinfo4_t *mi = VTOMI4(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
	boolean_t need_rele = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
	mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
	if (rp->r_deleg_type == OPEN_DELEGATE_NONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
		mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
	 * Free the cred originally held when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
	 * the delegation was granted.  Caller must
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
	 * hold this cred if it wants to use it after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
	 * this call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
	crfree(rp->r_deleg_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
	rp->r_deleg_cred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
	rp->r_deleg_type = OPEN_DELEGATE_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
	rp->r_deleg_needs_recovery = OPEN_DELEGATE_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
	rp->r_deleg_needs_recall = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
	rp->r_deleg_return_pending = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
	mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
	 * Caller must be holding mi_recovlock in read mode
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
	 * to call here.  This is provided by start_op.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
	if (np == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
		np = find_nfs4_server_all(mi, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
		ASSERT(np != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
		need_rele = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
		mutex_enter(&np->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
	 * Remove the rnode from the server's list and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
	 * update the ref counts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
	list_remove(&np->s_deleg_list, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
	nfs4_dec_state_ref_count_nolock(np, mi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
	mutex_exit(&np->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
	/* removed list node removes a reference */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
	nfs4_server_rele(np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
	if (need_rele)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
		nfs4_server_rele(np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
	if (ncg != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
		ncg->nfs4_callback_stats.delegations.value.ui64--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
nfs4delegreturn_cleanup(rnode4_t *rp, nfs4_server_t *np)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
	if (np != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
		ncg = np->zone_globals;
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  1369
	} else if (nfs_zone() == VTOMI4(RTOV4(rp))->mi_zone) {
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  1370
		ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone());
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
		ASSERT(ncg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
		 * Request coming from the wrong zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
		ASSERT(getzoneid() == GLOBAL_ZONEID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
		ncg = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
	nfs4delegreturn_cleanup_impl(rp, np, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
nfs4delegreturn_save_lost_rqst(int error, nfs4_lost_rqst_t *lost_rqstp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
	cred_t *cr, vnode_t *vp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
	if (error != ETIMEDOUT && error != EINTR &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
	    !NFS4_FRC_UNMT_ERR(error, vp->v_vfsp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
		lost_rqstp->lr_op = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
	NFS4_DEBUG(nfs4_lost_rqst_debug, (CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
			"nfs4close_save_lost_rqst: error %d", error));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
	lost_rqstp->lr_op = OP_DELEGRETURN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
	 * The vp is held and rele'd via the recovery code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
	 * See nfs4_save_lost_rqst.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
	lost_rqstp->lr_vp = vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
	lost_rqstp->lr_dvp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
	lost_rqstp->lr_oop = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
	lost_rqstp->lr_osp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
	lost_rqstp->lr_lop = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
	lost_rqstp->lr_cr = cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
	lost_rqstp->lr_flk = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
	lost_rqstp->lr_putfirst = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
nfs4delegreturn_otw(rnode4_t *rp, cred_t *cr, nfs4_error_t *ep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
	COMPOUND4args_clnt args;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
	COMPOUND4res_clnt res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
	nfs_argop4 argops[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
	nfs4_ga_res_t *garp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
	hrtime_t t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
	int numops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
	int doqueue = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
	args.ctag = TAG_DELEGRETURN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
	numops = 3;		/* PUTFH, GETATTR, DELEGRETURN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
	args.array = argops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
	args.array_len = numops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
	argops[0].argop = OP_CPUTFH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
	argops[0].nfs_argop4_u.opcputfh.sfh = rp->r_fh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
	argops[1].argop = OP_GETATTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
	argops[1].nfs_argop4_u.opgetattr.attr_request = NFS4_VATTR_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
	argops[1].nfs_argop4_u.opgetattr.mi = VTOMI4(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
	argops[2].argop = OP_DELEGRETURN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
	argops[2].nfs_argop4_u.opdelegreturn.deleg_stateid =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
		rp->r_deleg_stateid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
	t = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
	rfs4call(VTOMI4(RTOV4(rp)), &args, &res, cr, &doqueue, 0, ep);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
	if (ep->error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
	if (res.status == NFS4_OK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
		garp = &res.array[1].nfs_resop4_u.opgetattr.ga_res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
		nfs4_attr_cache(RTOV4(rp), garp, t, cr, TRUE, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
	(void) xdr_free(xdr_COMPOUND4res_clnt, (caddr_t)&res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
nfs4_do_delegreturn(rnode4_t *rp, int flags, cred_t *cr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
	struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
	vnode_t *vp = RTOV4(rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
	mntinfo4_t *mi = VTOMI4(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
	nfs4_lost_rqst_t lost_rqst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
	nfs4_recov_state_t recov_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
	bool_t needrecov = FALSE, recovonly, done = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
	ncg->nfs4_callback_stats.delegreturn.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
	while (!done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
		e.error = nfs4_start_fop(mi, vp, NULL, OH_DELEGRETURN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
				&recov_state, &recovonly);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
		if (e.error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
			if (flags & NFS4_DR_FORCE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
				(void) nfs_rw_enter_sig(&mi->mi_recovlock,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
				    RW_READER, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
				nfs4delegreturn_cleanup_impl(rp, NULL, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
				nfs_rw_exit(&mi->mi_recovlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
		 * Check to see if the delegation has already been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
		 * returned by the recovery thread.   The state of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
		 * the delegation cannot change at this point due
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
		 * to start_fop and the r_deleg_recall_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
		if (rp->r_deleg_type == OPEN_DELEGATE_NONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
			e.error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
			nfs4_end_op(mi, vp, NULL, &recov_state, needrecov);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
		if (recovonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
			 * Delegation will be returned via the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
			 * recovery framework.  Build a lost request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
			 * structure, start recovery and get out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
			nfs4_error_init(&e, EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
			nfs4delegreturn_save_lost_rqst(e.error, &lost_rqst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
				cr, vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
			(void) nfs4_start_recovery(&e, mi, vp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
				NULL, &rp->r_deleg_stateid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
				lost_rqst.lr_op == OP_DELEGRETURN ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
				&lost_rqst : NULL, OP_DELEGRETURN, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
			nfs4_end_op(mi, vp, NULL, &recov_state, needrecov);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
		nfs4delegreturn_otw(rp, cr, &e);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
		 * Ignore some errors on delegreturn; no point in marking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
		 * the file dead on a state destroying operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
		if (e.error == 0 && (nfs4_recov_marks_dead(e.stat) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
		    e.stat == NFS4ERR_BADHANDLE ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
		    e.stat == NFS4ERR_STALE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
			needrecov = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
			needrecov = nfs4_needs_recovery(&e, TRUE, vp->v_vfsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
		if (needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
			nfs4delegreturn_save_lost_rqst(e.error, &lost_rqst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
				cr, vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
			(void) nfs4_start_recovery(&e, mi, vp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
				NULL, &rp->r_deleg_stateid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
				lost_rqst.lr_op == OP_DELEGRETURN ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
				&lost_rqst : NULL, OP_DELEGRETURN, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
			nfs4delegreturn_cleanup_impl(rp, NULL, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
			done = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
		nfs4_end_op(mi, vp, NULL, &recov_state, needrecov);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
	return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
 * nfs4_resend_delegreturn - used to drive the delegreturn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
 * operation via the recovery thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
nfs4_resend_delegreturn(nfs4_lost_rqst_t *lorp, nfs4_error_t *ep,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
	nfs4_server_t *np)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
	rnode4_t *rp = VTOR4(lorp->lr_vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
	/* If the file failed recovery, just quit. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
	mutex_enter(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
	if (rp->r_flags & R4RECOVERR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
		ep->error = EIO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
	mutex_exit(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
	if (!ep->error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
		nfs4delegreturn_otw(rp, lorp->lr_cr, ep);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
	 * If recovery is now needed, then return the error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
	 * and status and let the recovery thread handle it,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
	 * including re-driving another delegreturn.  Otherwise,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
	 * just give up and clean up the delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
	if (nfs4_needs_recovery(ep, TRUE, lorp->lr_vp->v_vfsp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
	if (rp->r_deleg_type != OPEN_DELEGATE_NONE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
		nfs4delegreturn_cleanup(rp, np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
	nfs4_error_zinit(ep);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
 * nfs4delegreturn - general function to return a delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
 * NFS4_DR_FORCE - return the delegation even if start_op fails
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
 * NFS4_DR_PUSH - push modified data back to the server via VOP_PUTPAGE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
 * NFS4_DR_DISCARD - discard the delegation w/o delegreturn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
 * NFS4_DR_DID_OP - calling function already did nfs4_start_op
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
 * NFS4_DR_RECALL - delegreturned initiated via CB_RECALL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
 * NFS4_DR_REOPEN - do file reopens, if applicable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
nfs4delegreturn_impl(rnode4_t *rp, int flags, struct nfs4_callback_globals *ncg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
	cred_t *cr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
	bool_t needrecov = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
	bool_t rw_entered = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
	bool_t do_reopen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
	vp = RTOV4(rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
	 * If NFS4_DR_DISCARD is set by itself, take a short-cut and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
	 * discard without doing an otw DELEGRETURN.  This may only be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
	 * by the recovery thread because it bypasses the synchronization
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
	 * with r_deleg_recall_lock and mi->mi_recovlock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
	if (flags == NFS4_DR_DISCARD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
		nfs4delegreturn_cleanup_impl(rp, NULL, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
	if (flags & NFS4_DR_DID_OP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
		 * Caller had already done start_op, which means the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
		 * r_deleg_recall_lock is already held in READ mode
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
		 * so we cannot take it in write mode.  Return the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
		 * delegation asynchronously.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
		 * Remove the NFS4_DR_DID_OP flag so we don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
		 * get stuck looping through here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
		VN_HOLD(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
		nfs4delegreturn_async(rp, (flags & ~NFS4_DR_DID_OP), FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
	 * Take r_deleg_recall_lock to verify we still have a delegation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
	 * and to crhold the credential.  We have to release the lock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
	 * before we call VOP_PUTPAGE or else we'll deadlock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
	(void) nfs_rw_enter_sig(&rp->r_deleg_recall_lock, RW_WRITER, FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
	rw_entered = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
	if (rp->r_deleg_type == OPEN_DELEGATE_NONE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
	cr = rp->r_deleg_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
	crhold(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
	nfs_rw_exit(&rp->r_deleg_recall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
	rw_entered = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
	 * Push the modified data back to the server synchronously
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
	 * before doing DELEGRETURN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
	if (flags & NFS4_DR_PUSH)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
		(void) VOP_PUTPAGE(vp, 0, 0, 0, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
	 * Take r_deleg_recall_lock in WRITE mode, this will prevent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
	 * nfs4_is_otw_open_necessary from trying to use the delegation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
	 * while the DELEGRETURN is in progress.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
	(void) nfs_rw_enter_sig(&rp->r_deleg_recall_lock, RW_WRITER, FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
	rw_entered = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
	if (rp->r_deleg_type == OPEN_DELEGATE_NONE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
	if (flags & NFS4_DR_REOPEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
		 * If R4RECOVERRP is already set, then skip re-opening
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
		 * the delegation open streams and go straight to doing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
		 * delegreturn.  (XXX if the file has failed recovery, then the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
		 * delegreturn attempt is likely to be futile.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
		mutex_enter(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
		do_reopen = !(rp->r_flags & R4RECOVERRP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
		mutex_exit(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
		if (do_reopen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
			error = deleg_reopen(vp, &needrecov, ncg, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
			if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
				if ((flags & (NFS4_DR_FORCE | NFS4_DR_RECALL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
									== 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
					goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
			} else if (needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
				if ((flags & NFS4_DR_FORCE) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
					goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
	if (flags & NFS4_DR_DISCARD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
		mntinfo4_t *mi = VTOMI4(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
		mutex_enter(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
		 * deleg_return_pending is cleared inside of delegation_accept
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
		 * when a delegation is accepted.  if this flag has been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
		 * cleared, then a new delegation has overwritten the one we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
		 * were about to throw away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
		if (!rp->r_deleg_return_pending) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
			mutex_exit(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
		mutex_exit(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
		(void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER, FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
		nfs4delegreturn_cleanup_impl(rp, NULL, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
		nfs_rw_exit(&mi->mi_recovlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
		error = nfs4_do_delegreturn(rp, flags, cr, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
	if (cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
		crfree(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
	if (rw_entered)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
		nfs_rw_exit(&rp->r_deleg_recall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
nfs4delegreturn(rnode4_t *rp, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  1715
	ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone());
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
	ASSERT(ncg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
	return (nfs4delegreturn_impl(rp, flags, ncg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
nfs4delegreturn_async(rnode4_t *rp, int flags, bool_t trunc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
	struct cb_recall_pass *pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
	pp = kmem_alloc(sizeof (struct cb_recall_pass), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
	pp->rp = rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
	pp->flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
	pp->truncate = trunc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
	 * Fire up a thread to do the actual delegreturn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
	 * Caller must guarantee that the rnode doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
	 * vanish (by calling VN_HOLD).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
	(void) zthread_create(NULL, 0, nfs4delegreturn_thread, pp, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
				minclsyspri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
delegreturn_all_thread(rpcprog_t *pp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
	nfs4_server_t *np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
	bool_t found = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
	rpcprog_t prog;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
	zoneid_t zoneid = getzoneid();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
	NFS4_DEBUG(nfs4_drat_debug,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
		(CE_NOTE, "delereturn_all_thread: prog %d\n", *pp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
	prog = *pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
	kmem_free(pp, sizeof (*pp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
	pp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
	mutex_enter(&nfs4_server_lst_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
	for (np = nfs4_server_lst.forw; np != &nfs4_server_lst; np = np->forw) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
		if (np->zoneid == zoneid && np->s_program == prog) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
			mutex_enter(&np->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
			found = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
	mutex_exit(&nfs4_server_lst_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
	 * It's possible that the nfs4_server which was using this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
	 * program number has vanished since this thread is async.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
	 * If so, just return.  Your work here is finished, my friend.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
	if (!found)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
	ncg = np->zone_globals;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
	while ((rp = list_head(&np->s_deleg_list)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
		vp = RTOV4(rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
		VN_HOLD(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
		mutex_exit(&np->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
		(void) nfs4delegreturn_impl(rp, NFS4_DR_PUSH|NFS4_DR_REOPEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
									ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
		VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
		/* retake the s_lock for next trip through the loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
		mutex_enter(&np->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
	mutex_exit(&np->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
	NFS4_DEBUG(nfs4_drat_debug,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
		(CE_NOTE, "delereturn_all_thread: complete\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
	zthread_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1796
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
nfs4_delegreturn_all(nfs4_server_t *sp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
	rpcprog_t pro, *pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
	mutex_enter(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
	/* Check to see if the delegation list is empty */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
	if (list_head(&sp->s_deleg_list) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
		mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
	 * Grab the program number; the async thread will use this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
	 * to find the nfs4_server.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
	pro = sp->s_program;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
	mutex_exit(&sp->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
	pp = kmem_alloc(sizeof (rpcprog_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
	*pp = pro;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
	(void) zthread_create(NULL, 0, delegreturn_all_thread, pp, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
	    minclsyspri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
 * Discard any delegations
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
 * Iterate over the servers s_deleg_list and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
 * for matching mount-point rnodes discard
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
 * the delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
nfs4_deleg_discard(mntinfo4_t *mi, nfs4_server_t *sp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
	rnode4_t *rp, *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
	mntinfo4_t *r_mi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
	ASSERT(mutex_owned(&sp->s_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
	ncg = sp->zone_globals;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
	for (rp = list_head(&sp->s_deleg_list); rp != NULL; rp = next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
		r_mi = VTOMI4(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
		next = list_next(&sp->s_deleg_list, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
		if (r_mi != mi) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
			 * Skip if this rnode is in not on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
			 * same mount-point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
		ASSERT(rp->r_deleg_type == OPEN_DELEGATE_READ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
		if (nfs4_client_recov_debug) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
			zprintf(getzoneid(),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
			    "nfs4_deleg_discard: matched rnode %p "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
			"-- discarding delegation\n", (void *)rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
		mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
		 * Free the cred originally held when the delegation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
		 * was granted. Also need to decrement the refcnt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
		 * on this server for each delegation we discard
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
		if (rp->r_deleg_cred)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
			crfree(rp->r_deleg_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
		rp->r_deleg_cred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
		rp->r_deleg_type = OPEN_DELEGATE_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
		rp->r_deleg_needs_recovery = OPEN_DELEGATE_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
		rp->r_deleg_needs_recall = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
		ASSERT(sp->s_refcnt > 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
		sp->s_refcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
		list_remove(&sp->s_deleg_list, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
		mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
		nfs4_dec_state_ref_count_nolock(sp, mi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
		ncg->nfs4_callback_stats.delegations.value.ui64--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
 * Reopen any open streams that were covered by the given file's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
 * delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
 * Returns zero or an errno value.  If there was no error, *recovp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
 * indicates whether recovery was initiated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
deleg_reopen(vnode_t *vp, bool_t *recovp, struct nfs4_callback_globals *ncg,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
	int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
	nfs4_open_stream_t *osp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
	nfs4_recov_state_t recov_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	bool_t needrecov = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
	mntinfo4_t *mi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
	nfs4_error_t e = { 0, NFS4_OK, RPC_SUCCESS };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
	int claimnull;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
	mi = VTOMI4(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
	rp = VTOR4(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
	recov_state.rs_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
	recov_state.rs_num_retry_despite_err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
	if ((e.error = nfs4_start_op(mi, vp, NULL, &recov_state)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
		return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
	 * if we mean to discard the delegation, it must be BAD, so don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
	 * use it when doing the reopen or it will fail too.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
	claimnull = (flags & NFS4_DR_DISCARD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
	 * Loop through the open streams for this rnode to find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
	 * all of the ones created using the delegation state ID.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
	 * Each of these needs to be re-opened.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
	while ((osp = get_next_deleg_stream(rp, claimnull)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
		if (claimnull) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
			nfs4_reopen(vp, osp, &e, CLAIM_NULL, FALSE, FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
			ncg->nfs4_callback_stats.claim_cur.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
			nfs4_reopen(vp, osp, &e, CLAIM_DELEGATE_CUR, FALSE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
					FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
			if (e.error == 0 && e.stat == NFS4_OK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
				ncg->nfs4_callback_stats.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
					claim_cur_ok.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
		if (e.error == EAGAIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
			nfs4_end_op(mi, vp, NULL, &recov_state, TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
		 * if error is EINTR, ETIMEDOUT, or NFS4_FRC_UNMT_ERR, then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
		 * recovery has already been started inside of nfs4_reopen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
		if (e.error == EINTR || e.error == ETIMEDOUT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
		    NFS4_FRC_UNMT_ERR(e.error, vp->v_vfsp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
			open_stream_rele(osp, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
		needrecov = nfs4_needs_recovery(&e, TRUE, vp->v_vfsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
		if (e.error != 0 && !needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
			 * Recovery is not possible, but don't give up yet;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
			 * we'd still like to do delegreturn after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
			 * reopening as many streams as possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
			 * Continue processing the open streams.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
			ncg->nfs4_callback_stats.recall_failed.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
		} else if (needrecov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
			 * Start recovery and bail out.  The recovery
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
			 * thread will take it from here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
			(void) nfs4_start_recovery(&e, mi, vp, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
				NULL, OP_OPEN, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
			open_stream_rele(osp, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
			*recovp = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
		open_stream_rele(osp, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
	nfs4_end_op(mi, vp, NULL, &recov_state, needrecov);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
	return (e.error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
 * get_next_deleg_stream - returns the next open stream which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
 * represents a delegation for this rnode.  In order to assure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
 * forward progress, the caller must guarantee that each open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
 * stream returned is changed so that a future call won't return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
 * it again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
 * There are several ways for the open stream to change.  If the open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
 * stream is !os_delegation, then we aren't interested in it.  Also, if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
 * either os_failed_reopen or !os_valid, then don't return the osp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
 * If claimnull is false (doing reopen CLAIM_DELEGATE_CUR) then return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
 * the osp if it is an os_delegation open stream.  Also, if the rnode still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
 * has r_deleg_return_pending, then return the os_delegation osp.  Lastly,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
 * if the rnode's r_deleg_stateid is different from the osp's open_stateid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
 * then return the osp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
 * We have already taken the 'r_deleg_recall_lock' as WRITER, which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
 * prevents new OPENs from going OTW (as start_fop takes this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
 * lock in READ mode); thus, no new open streams can be created
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
 * (which inheretly means no new delegation open streams are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
 * being created).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
static nfs4_open_stream_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
get_next_deleg_stream(rnode4_t *rp, int claimnull)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
	nfs4_open_stream_t	*osp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
	ASSERT(nfs_rw_lock_held(&rp->r_deleg_recall_lock, RW_WRITER));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
	 * Search through the list of open streams looking for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
	 * one that was created while holding the delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
	mutex_enter(&rp->r_os_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
	for (osp = list_head(&rp->r_open_streams); osp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
	    osp = list_next(&rp->r_open_streams, osp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
		mutex_enter(&osp->os_sync_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
		if (!osp->os_delegation || osp->os_failed_reopen ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
		    !osp->os_valid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
			mutex_exit(&osp->os_sync_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
		if (!claimnull || rp->r_deleg_return_pending ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
		    !stateid4_cmp(&osp->open_stateid, &rp->r_deleg_stateid)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
			osp->os_ref_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
			mutex_exit(&osp->os_sync_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
			mutex_exit(&rp->r_os_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
			return (osp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
		mutex_exit(&osp->os_sync_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
	mutex_exit(&rp->r_os_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
nfs4delegreturn_thread(struct cb_recall_pass *args)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
	cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
	int dtype, error, flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
	bool_t rdirty, rip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
	kmutex_t cpr_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
	callb_cpr_t cpr_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  2053
	ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone());
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
	ASSERT(ncg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
	mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
	CALLB_CPR_INIT(&cpr_info, &cpr_lock, callb_generic_cpr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
			"nfsv4delegRtn");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
	rp = args->rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
	vp = RTOV4(rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
	mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
	if (rp->r_deleg_type == OPEN_DELEGATE_NONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
		mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
	mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
	 * Take the read-write lock in read mode to prevent other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
	 * threads from modifying the data during the recall.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
	 * doesn't affect mmappers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
	(void) nfs_rw_enter_sig(&rp->r_rwlock, RW_READER, FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
	/* Proceed with delegreturn */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
	mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2081
	if (rp->r_deleg_type == OPEN_DELEGATE_NONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
		mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
		nfs_rw_exit(&rp->r_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
	dtype = rp->r_deleg_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
	cr = rp->r_deleg_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
	ASSERT(cr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
	crhold(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
	mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
	flags = args->flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
	 * If the file is being truncated at the server, then throw
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
	 * away all of the pages, it doesn't matter what flavor of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
	 * delegation we have.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
	if (args->truncate) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
		ncg->nfs4_callback_stats.recall_trunc.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
		nfs4_invalidate_pages(vp, 0, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
	} else if (dtype == OPEN_DELEGATE_WRITE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
		mutex_enter(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
		rdirty = rp->r_flags & R4DIRTY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
		mutex_exit(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
		if (rdirty) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
			error = VOP_PUTPAGE(vp, 0, 0, 0, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
			if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
				CB_WARN1("nfs4delegreturn_thread:"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
				" VOP_PUTPAGE: %d\n", error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
		/* turn off NFS4_DR_PUSH because we just did that above. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
		flags &= ~NFS4_DR_PUSH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
	mutex_enter(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
	rip =  rp->r_flags & R4RECOVERRP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
	mutex_exit(&rp->r_statelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
	/* If a failed recovery is indicated, discard the pages */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
	if (rip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
		error = VOP_PUTPAGE(vp, 0, 0, B_INVAL, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
			CB_WARN1("nfs4delegreturn_thread: VOP_PUTPAGE: %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
				error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
	 * Pass the flags to nfs4delegreturn_impl, but be sure not to pass
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
	 * NFS4_DR_DID_OP, which just calls nfs4delegreturn_async again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
	flags &= ~NFS4_DR_DID_OP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
	(void) nfs4delegreturn_impl(rp, flags, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
	nfs_rw_exit(&rp->r_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
	crfree(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
	kmem_free(args, sizeof (struct cb_recall_pass));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
	VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
	mutex_enter(&cpr_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
	CALLB_CPR_EXIT(&cpr_info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
	mutex_destroy(&cpr_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
	zthread_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
 * This function has one assumption that the caller of this function is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
 * either doing recovery (therefore cannot call nfs4_start_op) or has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
 * already called nfs4_start_op().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
nfs4_delegation_accept(rnode4_t *rp, open_claim_type4 claim,  OPEN4res *res,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
	nfs4_ga_res_t *garp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
	open_read_delegation4 *orp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
	open_write_delegation4 *owp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
	nfs4_server_t *np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
	bool_t already = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
	bool_t recall = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
	bool_t valid_garp = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
	long mapcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
	uint_t rflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
	mntinfo4_t *mi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
	bool_t recov;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
	struct nfs4_callback_globals *ncg;
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2174
	open_delegation_type4 odt;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  2176
	ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone());
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
	ASSERT(ncg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
	mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
	if (rp->r_deleg_type == OPEN_DELEGATE_READ ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
	    rp->r_deleg_type == OPEN_DELEGATE_WRITE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
		already = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2185
	odt = res->delegation.delegation_type;
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2186
	mutex_exit(&rp->r_statev4_lock);
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2187
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2188
	if (odt == OPEN_DELEGATE_READ) {
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2189
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2190
		mutex_enter(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
		rp->r_deleg_type = res->delegation.delegation_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
		orp = &res->delegation.open_delegation4_u.read;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
		rp->r_deleg_stateid = orp->stateid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
		rp->r_deleg_perms = orp->permissions;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
		recall = orp->recall;
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2196
		mutex_exit(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
		ncg->nfs4_callback_stats.delegations.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
		ncg->nfs4_callback_stats.delegaccept_r.value.ui64++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2201
	} else if (odt == OPEN_DELEGATE_WRITE) {
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2202
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2203
		mutex_enter(&rp->r_statelock);
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2204
		mutex_enter(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
		rp->r_deleg_type = res->delegation.delegation_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
		owp = &res->delegation.open_delegation4_u.write;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
		rp->r_deleg_stateid = owp->stateid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
		rp->r_deleg_perms = owp->permissions;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
		rp->r_deleg_limit = owp->space_limit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
		recall = owp->recall;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
		if (garp == NULL || !garp->n4g_change_valid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
			valid_garp = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
			rp->r_deleg_change = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
			rp->r_deleg_change_grant = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
			rp->r_deleg_change = garp->n4g_change;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
			rp->r_deleg_change_grant = garp->n4g_change;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
		mapcnt = rp->r_mapcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
		rflag = rp->r_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
		 * Update the delegation change attribute if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
		 * there are mappers for the file is dirty.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
		 * might be the case during recovery after server
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
		 * reboot.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
		if (mapcnt > 0 || rflag & R4DIRTY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
			rp->r_deleg_change++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
		NFS4_DEBUG(nfs4_callback_debug, (CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
			"nfs4_delegation_accept: r_deleg_change: 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
			(int)(rp->r_deleg_change >> 32)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
		NFS4_DEBUG(nfs4_callback_debug, (CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
			"nfs4_delegation_accept: r_delg_change_grant: 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
			(int)(rp->r_deleg_change_grant >> 32)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2240
		if (nfs4_use_phony_limit == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2241
			rp->r_deleg_limit = nfs4_deleg_space_phony;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
		if (nfs4_use_phony_limit == 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
			rp->r_deleg_limit = nfs4_deleg_space_phony2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
			rp->r_deleg_limit.nfs_space_limit4_u.mod_blocks =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
				nfs4_deleg_space_phonyl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
#endif
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2248
		mutex_exit(&rp->r_statev4_lock);
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2249
		mutex_exit(&rp->r_statelock);
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2250
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2251
		ncg->nfs4_callback_stats.delegations.value.ui64++;
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2252
		ncg->nfs4_callback_stats.delegaccept_rw.value.ui64++;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
	} else if (nfs4_deleg_accept_phony == OPEN_DELEGATE_READ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2258
		mutex_enter(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
		rp->r_deleg_type = OPEN_DELEGATE_READ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
		rp->r_deleg_stateid = nfs4_deleg_any;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
		rp->r_deleg_perms = nfs4_deleg_ace_phony;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
		rp->r_deleg_change = nfs4_deleg_change_phony;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
		rp->r_deleg_change_grant = rp->r_deleg_change;
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2264
		mutex_exit(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
	} else if (nfs4_deleg_accept_phony == OPEN_DELEGATE_WRITE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2268
		mutex_enter(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
		rp->r_deleg_type = OPEN_DELEGATE_WRITE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
		rp->r_deleg_stateid = nfs4_deleg_any;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
		rp->r_deleg_perms = nfs4_deleg_ace_phony;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
		rp->r_deleg_limit = nfs4_deleg_space_phony;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
		rp->r_deleg_change = nfs4_deleg_change_phony;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
		rp->r_deleg_change_grant = rp->r_deleg_change;
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2275
		mutex_exit(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
		if (already) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
			switch (claim) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
			case CLAIM_NULL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
			case CLAIM_PREVIOUS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
				 * The file may already have a delegation when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
				 * it is reopened during recovery.  In this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
				 * case, we consider the delegation to no longer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
				 * be valid.  As a courtesy, attempt to return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
				 * the delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
				mi = VTOMI4(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
				mutex_enter(&mi->mi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
				recov = mi->mi_recovflags & MI4R_REOPEN_FILES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
				mutex_exit(&mi->mi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
				 * We need to hold rp->r_statev4_lock while
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
				 * checking rp->r_deleg_return_pending and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
				 * when calling nfs4_dlistadd() if we're in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
				 * recovery.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
				mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
				if (rp->r_deleg_return_pending == TRUE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
					 * We're alreading in the throes of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
					 * returning a delegation.  Drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
					 * the lock and head for the return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
					mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
				} else if (recov) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
					 * Cannot call delegreturn from inside
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
					 * of recovery or VOP_PUTPAGE will hang
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
					 * due to nfs4_start_fop call in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
					 * nfs4write.  Use dlistadd to add the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
					 * rnode to the list of rnodes needing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
					 * cleaning.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
					 * NB: We're in recover so don't reopen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
					nfs4_dlistadd(rp, ncg,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
						NFS4_DR_PUSH|NFS4_DR_DISCARD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
					mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
					mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
					/* XXX - Do we need to reopen? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
					(void) nfs4delegreturn_impl(rp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
						(NFS4_DR_PUSH |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
						    NFS4_DR_DID_OP |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
						    NFS4_DR_REOPEN),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
						ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
			default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
				 * CLAIM_DELEGATE_CUR, CLAIM_DELEGATE_PREV
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
				 * fall through here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
		/* No delegation granted, get out. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
536
ece52d2759f6 6300246 nfs4_delegation_accept(): Deadlock: cycle in blocking chain
rmesta
parents: 0
diff changeset
  2349
	mutex_enter(&rp->r_statev4_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
	rp->r_deleg_return_pending = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
	rp->r_deleg_needs_recovery = OPEN_DELEGATE_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
	if (claim == CLAIM_PREVIOUS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
		rp->r_deleg_needs_recall = recall;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
	if (nfs4_use_phony_recall)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
		rp->r_deleg_needs_recall = nfs4_phony_recall_v;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
	 * If the server has requested a recall, then put the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
	 * vnode on a list of files which need to be cleaned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
	 * This will be done later by the recovery thread to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
	 * avoid a deadlock.  If this were a CLAIM_NULL open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
	 * and the server set recall, then the server is just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
	 * confused; the delegation will be returned eventually.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
	if (rp->r_deleg_needs_recall)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
		nfs4_dlistadd(rp, ncg, NFS4_DR_PUSH|NFS4_DR_REOPEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
	if (already == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
		rp->r_deleg_cred = cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
		crhold(cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
	mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
	if (already == FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
		 * Add this rnode to the list of rnodes with delegations
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
		 * for this nfs4_server.  find_nfs4_server returns with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
		 * the mutex locked, so don't forget to mutex exit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
		if ((np = find_nfs4_server(VTOMI4(RTOV4(rp)))) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
			mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
			rp->r_deleg_type = OPEN_DELEGATE_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
			mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
		list_insert_head(&np->s_deleg_list, rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
		/* added list node gets a reference */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
		np->s_refcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
		nfs4_inc_state_ref_count_nolock(np, VTOMI4(RTOV4(rp)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
		mutex_exit(&np->s_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
		nfs4_server_rele(np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
	 * This call to nfs4delegreturn assumes that nfs4_start_op MUST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
	 * not be called by nfs4delegreturn.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
	if (nfs4_delegreturn_policy == IMMEDIATE || !valid_garp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
		(void) nfs4delegreturn_impl(rp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
			NFS4_DR_PUSH|NFS4_DR_DID_OP|NFS4_DR_REOPEN, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
 * nfs4delegabandon - Abandon the delegation on an rnode4.  This code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
 * is called when the client receives EXPIRED, BAD_STATEID, OLD_STATEID
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
 * or BADSEQID and the recovery code is unable to recover.  Push any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
 * dirty data back to the server and return the delegation (if any).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
nfs4delegabandon(rnode4_t *rp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
	struct cb_recall_pass *pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
	open_delegation_type4 dt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
	mutex_enter(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
	dt = rp->r_deleg_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
	mutex_exit(&rp->r_statev4_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
	if (dt == OPEN_DELEGATE_NONE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
	vp = RTOV4(rp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
	VN_HOLD(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
	pp = kmem_alloc(sizeof (struct cb_recall_pass), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
	pp->rp = rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
	 * Recovery on the file has failed and we want to return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
	 * the delegation.  We don't want to reopen files and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
	 * nfs4delegreturn_thread() figures out what to do about
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
	 * the data.  The only thing to do is attempt to return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
	 * the delegation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
	pp->flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
	pp->truncate = FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
	 * Fire up a thread to do the delegreturn; this is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
	 * necessary because we could be inside a GETPAGE or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
	 * PUTPAGE and we cannot do another one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
	(void) zthread_create(NULL, 0, nfs4delegreturn_thread, pp, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
				minclsyspri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
wait_for_recall1(vnode_t *vp, nfs4_op_hint_t op, nfs4_recov_state_t *rsp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
	int flg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
#ifdef lint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
	op = op;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
	if (vp && vp->v_type == VREG) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
		rp = VTOR4(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
		 * Take r_deleg_recall_lock in read mode to synchronize
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
		 * with delegreturn.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
		error = nfs_rw_enter_sig(&rp->r_deleg_recall_lock,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
			RW_READER, INTR4(vp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
		if (error == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
			rsp->rs_flags |= flg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
nfs4_end_op_recall(vnode_t *vp1, vnode_t *vp2, nfs4_recov_state_t *rsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
	NFS4_DEBUG(nfs4_recall_debug,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
		(CE_NOTE, "nfs4_end_op_recall: 0x%p, 0x%p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
		(void *)vp1, (void *)vp2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
	if (vp2 && rsp->rs_flags & NFS4_RS_RECALL_HELD2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
		nfs_rw_exit(&VTOR4(vp2)->r_deleg_recall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
	if (vp1 && rsp->rs_flags & NFS4_RS_RECALL_HELD1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
		nfs_rw_exit(&VTOR4(vp1)->r_deleg_recall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
wait_for_recall(vnode_t *vp1, vnode_t *vp2, nfs4_op_hint_t op,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
	nfs4_recov_state_t *rsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
	NFS4_DEBUG(nfs4_recall_debug,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
		(CE_NOTE, "wait_for_recall:    0x%p, 0x%p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
		(void *)vp1, (void *) vp2));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
	rsp->rs_flags &= ~(NFS4_RS_RECALL_HELD1|NFS4_RS_RECALL_HELD2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
	if ((error = wait_for_recall1(vp1, op, rsp, NFS4_RS_RECALL_HELD1)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
	if ((error = wait_for_recall1(vp2, op, rsp, NFS4_RS_RECALL_HELD2))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
	    != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
		if (rsp->rs_flags & NFS4_RS_RECALL_HELD1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
			nfs_rw_exit(&VTOR4(vp1)->r_deleg_recall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
			rsp->rs_flags &= ~NFS4_RS_RECALL_HELD1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
 * nfs4_dlistadd - Add this rnode to a list of rnodes to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
 * DELEGRETURN'd at the end of recovery.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
nfs4_dlistadd(rnode4_t *rp, struct nfs4_callback_globals *ncg, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
	struct nfs4_dnode *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
	ASSERT(mutex_owned(&rp->r_statev4_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
	 * Mark the delegation as having a return pending.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
	 * This will prevent the use of the delegation stateID
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
	 * by read, write, setattr and open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
	rp->r_deleg_return_pending = TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
	dp = kmem_alloc(sizeof (*dp), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
	VN_HOLD(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
	dp->rnodep = rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
	dp->flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
	mutex_enter(&ncg->nfs4_dlist_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
	list_insert_head(&ncg->nfs4_dlist, dp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
	ncg->nfs4_dlistadd_c++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
	mutex_exit(&ncg->nfs4_dlist_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
 * nfs4_dlistclean_impl - Do DELEGRETURN for each rnode on the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
 * of files awaiting cleaning.  If the override_flags are non-zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
 * then use them rather than the flags that were set when the rnode
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
 * was added to the dlist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
nfs4_dlistclean_impl(struct nfs4_callback_globals *ncg, int override_flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
	rnode4_t *rp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
	struct nfs4_dnode *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
	int flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
	ASSERT(override_flags == 0 || override_flags == NFS4_DR_DISCARD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
	mutex_enter(&ncg->nfs4_dlist_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
	while ((dp = list_head(&ncg->nfs4_dlist)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
		ncg->nfs4_dlistclean_c++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
		list_remove(&ncg->nfs4_dlist, dp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
		mutex_exit(&ncg->nfs4_dlist_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
		rp = dp->rnodep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
		flags = (override_flags != 0) ? override_flags : dp->flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
		kmem_free(dp, sizeof (*dp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
		(void) nfs4delegreturn_impl(rp, flags, ncg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
		VN_RELE(RTOV4(rp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
		mutex_enter(&ncg->nfs4_dlist_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
	mutex_exit(&ncg->nfs4_dlist_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
nfs4_dlistclean(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
	struct nfs4_callback_globals *ncg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 536
diff changeset
  2591
	ncg = zone_getspecific(nfs4_callback_zone_key, nfs_zone());
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
	ASSERT(ncg != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
	nfs4_dlistclean_impl(ncg, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
}